From 48d3ed373acdf850db1e74a925a96e01d38e180c Mon Sep 17 00:00:00 2001 From: tyru Date: Sat, 27 Jan 2018 21:33:31 +0900 Subject: [PATCH 01/11] Vendoring 'dep' source code --- .gitattributes | 1 + Gopkg.lock | 99 +- Gopkg.toml | 2 + Makefile | 9 +- .../github.com/Masterminds/semver/.travis.yml | 24 + .../Masterminds/semver/CHANGELOG.md | 17 + .../github.com/Masterminds/semver/LICENSE.txt | 20 + vendor/github.com/Masterminds/semver/Makefile | 36 + .../github.com/Masterminds/semver/README.md | 146 + .../Masterminds/semver/appveyor.yml | 44 + .../Masterminds/semver/benchmark_test.go | 259 + .../Masterminds/semver/collection.go | 24 + .../Masterminds/semver/collection_test.go | 46 + .../Masterminds/semver/constraints.go | 315 ++ .../Masterminds/semver/constraints_test.go | 712 +++ vendor/github.com/Masterminds/semver/doc.go | 115 + vendor/github.com/Masterminds/semver/error.go | 83 + vendor/github.com/Masterminds/semver/magic.go | 107 + vendor/github.com/Masterminds/semver/parse.go | 240 + vendor/github.com/Masterminds/semver/range.go | 519 +++ .../Masterminds/semver/set_ops_test.go | 932 ++++ vendor/github.com/Masterminds/semver/union.go | 152 + .../github.com/Masterminds/semver/version.go | 447 ++ .../Masterminds/semver/version_test.go | 310 ++ vendor/github.com/Masterminds/vcs/.gitignore | 24 + vendor/github.com/Masterminds/vcs/.travis.yml | 30 + .../github.com/Masterminds/vcs/CHANGELOG.md | 170 + vendor/github.com/Masterminds/vcs/LICENSE.txt | 20 + vendor/github.com/Masterminds/vcs/Makefile | 41 + vendor/github.com/Masterminds/vcs/README.md | 48 + .../github.com/Masterminds/vcs/appveyor.yml | 26 + vendor/github.com/Masterminds/vcs/bzr.go | 342 ++ vendor/github.com/Masterminds/vcs/bzr_test.go | 328 ++ vendor/github.com/Masterminds/vcs/errors.go | 114 + .../github.com/Masterminds/vcs/errors_test.go | 36 + vendor/github.com/Masterminds/vcs/git.go | 457 ++ vendor/github.com/Masterminds/vcs/git_test.go | 599 +++ vendor/github.com/Masterminds/vcs/glide.yaml | 8 + vendor/github.com/Masterminds/vcs/hg.go | 317 ++ vendor/github.com/Masterminds/vcs/hg_test.go | 332 ++ vendor/github.com/Masterminds/vcs/repo.go | 276 ++ .../github.com/Masterminds/vcs/repo_test.go | 74 + vendor/github.com/Masterminds/vcs/svn.go | 386 ++ vendor/github.com/Masterminds/vcs/svn_test.go | 337 ++ .../Masterminds/vcs/vcs_local_lookup.go | 46 + .../Masterminds/vcs/vcs_remote_lookup.go | 374 ++ .../Masterminds/vcs/vcs_remote_lookup_test.go | 137 + vendor/github.com/armon/go-radix/.gitignore | 22 + vendor/github.com/armon/go-radix/.travis.yml | 3 + vendor/github.com/armon/go-radix/LICENSE | 20 + vendor/github.com/armon/go-radix/README.md | 38 + vendor/github.com/armon/go-radix/radix.go | 543 +++ .../github.com/armon/go-radix/radix_test.go | 359 ++ vendor/github.com/boltdb/bolt/.gitignore | 4 + vendor/github.com/boltdb/bolt/LICENSE | 20 + vendor/github.com/boltdb/bolt/Makefile | 18 + vendor/github.com/boltdb/bolt/README.md | 916 ++++ vendor/github.com/boltdb/bolt/appveyor.yml | 18 + vendor/github.com/boltdb/bolt/bolt_386.go | 10 + vendor/github.com/boltdb/bolt/bolt_amd64.go | 10 + vendor/github.com/boltdb/bolt/bolt_arm.go | 28 + vendor/github.com/boltdb/bolt/bolt_arm64.go | 12 + vendor/github.com/boltdb/bolt/bolt_linux.go | 10 + vendor/github.com/boltdb/bolt/bolt_openbsd.go | 27 + vendor/github.com/boltdb/bolt/bolt_ppc.go | 9 + vendor/github.com/boltdb/bolt/bolt_ppc64.go | 12 + vendor/github.com/boltdb/bolt/bolt_ppc64le.go | 12 + vendor/github.com/boltdb/bolt/bolt_s390x.go | 12 + vendor/github.com/boltdb/bolt/bolt_unix.go | 89 + .../boltdb/bolt/bolt_unix_solaris.go | 90 + vendor/github.com/boltdb/bolt/bolt_windows.go | 144 + .../github.com/boltdb/bolt/boltsync_unix.go | 8 + vendor/github.com/boltdb/bolt/bucket.go | 777 +++ vendor/github.com/boltdb/bolt/bucket_test.go | 1909 ++++++++ .../github.com/boltdb/bolt/cmd/bolt/main.go | 1740 +++++++ .../boltdb/bolt/cmd/bolt/main_test.go | 356 ++ vendor/github.com/boltdb/bolt/cursor.go | 400 ++ vendor/github.com/boltdb/bolt/cursor_test.go | 817 ++++ vendor/github.com/boltdb/bolt/db.go | 1039 +++++ vendor/github.com/boltdb/bolt/db_test.go | 1545 ++++++ vendor/github.com/boltdb/bolt/doc.go | 44 + vendor/github.com/boltdb/bolt/errors.go | 71 + vendor/github.com/boltdb/bolt/freelist.go | 252 + .../github.com/boltdb/bolt/freelist_test.go | 158 + vendor/github.com/boltdb/bolt/node.go | 604 +++ vendor/github.com/boltdb/bolt/node_test.go | 156 + vendor/github.com/boltdb/bolt/page.go | 197 + vendor/github.com/boltdb/bolt/page_test.go | 72 + vendor/github.com/boltdb/bolt/quick_test.go | 87 + .../github.com/boltdb/bolt/simulation_test.go | 329 ++ vendor/github.com/boltdb/bolt/tx.go | 684 +++ vendor/github.com/boltdb/bolt/tx_test.go | 716 +++ vendor/github.com/go-yaml/yaml/.travis.yml | 9 + vendor/github.com/go-yaml/yaml/LICENSE | 201 + .../github.com/go-yaml/yaml/LICENSE.libyaml | 31 + vendor/github.com/go-yaml/yaml/README.md | 135 + vendor/github.com/go-yaml/yaml/apic.go | 742 +++ vendor/github.com/go-yaml/yaml/decode.go | 685 +++ vendor/github.com/go-yaml/yaml/decode_test.go | 1032 ++++ vendor/github.com/go-yaml/yaml/emitterc.go | 1684 +++++++ vendor/github.com/go-yaml/yaml/encode.go | 306 ++ vendor/github.com/go-yaml/yaml/encode_test.go | 501 ++ .../go-yaml/yaml/example_embedded_test.go | 41 + vendor/github.com/go-yaml/yaml/parserc.go | 1095 +++++ vendor/github.com/go-yaml/yaml/readerc.go | 394 ++ vendor/github.com/go-yaml/yaml/resolve.go | 208 + vendor/github.com/go-yaml/yaml/scannerc.go | 2711 +++++++++++ vendor/github.com/go-yaml/yaml/sorter.go | 104 + vendor/github.com/go-yaml/yaml/suite_test.go | 12 + vendor/github.com/go-yaml/yaml/writerc.go | 89 + vendor/github.com/go-yaml/yaml/yaml.go | 357 ++ vendor/github.com/go-yaml/yaml/yamlh.go | 716 +++ .../github.com/go-yaml/yaml/yamlprivateh.go | 173 + vendor/github.com/golang/dep/.codeclimate.yml | 35 + vendor/github.com/golang/dep/.gitattributes | 2 + .../github.com/golang/dep/.github/CODEOWNERS | 25 + .../golang/dep/.github/ISSUE_TEMPLATE.md | 26 + .../dep/.github/PULL_REQUEST_TEMPLATE.md | 23 + vendor/github.com/golang/dep/.gitignore | 10 + vendor/github.com/golang/dep/.travis.yml | 87 + vendor/github.com/golang/dep/AUTHORS | 3 + vendor/github.com/golang/dep/CHANGELOG.md | 122 + .../github.com/golang/dep/CODE_OF_CONDUCT.md | 74 + vendor/github.com/golang/dep/CONTRIBUTING.md | 109 + vendor/github.com/golang/dep/CONTRIBUTORS | 3 + vendor/github.com/golang/dep/Gopkg.lock | 94 + vendor/github.com/golang/dep/Gopkg.toml | 37 + vendor/github.com/golang/dep/LICENSE | 27 + vendor/github.com/golang/dep/MAINTAINERS.md | 17 + vendor/github.com/golang/dep/PATENTS | 22 + vendor/github.com/golang/dep/README.md | 47 + vendor/github.com/golang/dep/analyzer.go | 53 + .../golang/dep/analyzer_notwindows_test.go | 24 + vendor/github.com/golang/dep/analyzer_test.go | 113 + .../golang/dep/analyzer_windows_test.go | 33 + vendor/github.com/golang/dep/appveyor.yml | 34 + .../github.com/golang/dep/cmd/dep/dep_test.go | 47 + vendor/github.com/golang/dep/cmd/dep/doc.go | 143 + .../github.com/golang/dep/cmd/dep/ensure.go | 917 ++++ .../golang/dep/cmd/dep/ensure_test.go | 256 + .../github.com/golang/dep/cmd/dep/failures.go | 23 + .../golang/dep/cmd/dep/gopath_scanner.go | 408 ++ .../golang/dep/cmd/dep/gopath_scanner_test.go | 189 + .../github.com/golang/dep/cmd/dep/graphviz.go | 110 + .../golang/dep/cmd/dep/graphviz_test.go | 83 + .../github.com/golang/dep/cmd/dep/hash_in.go | 51 + vendor/github.com/golang/dep/cmd/dep/init.go | 245 + .../golang/dep/cmd/dep/integration_test.go | 237 + vendor/github.com/golang/dep/cmd/dep/main.go | 329 ++ vendor/github.com/golang/dep/cmd/dep/mkdoc.sh | 11 + vendor/github.com/golang/dep/cmd/dep/prune.go | 211 + .../golang/dep/cmd/dep/root_analyzer.go | 209 + .../github.com/golang/dep/cmd/dep/status.go | 844 ++++ .../golang/dep/cmd/dep/status_test.go | 505 ++ .../dep/cmd/dep/testdata/cachedir/Gopkg.lock | 15 + .../dep/cmd/dep/testdata/cachedir/Gopkg.toml | 4 + .../dep/cmd/dep/testdata/cachedir/main.go | 12 + .../dep/cmd/dep/testdata/graphviz/case1.dot | 9 + .../dep/cmd/dep/testdata/graphviz/case2.dot | 4 + .../dep/cmd/dep/testdata/graphviz/empty.dot | 3 + .../cmd/dep/testdata/harness_tests/README.md | 85 + .../add/all-new-double-spec/final/Gopkg.lock | 21 + .../add/all-new-double-spec/final/Gopkg.toml | 12 + .../add/all-new-double-spec/initial/main.go | 13 + .../add/all-new-double-spec/testcase.json | 10 + .../add/all-new-double/final/Gopkg.lock | 24 + .../add/all-new-double/final/Gopkg.toml | 12 + .../ensure/add/all-new-double/initial/main.go | 13 + .../ensure/add/all-new-double/testcase.json | 10 + .../ensure/add/all-new-spec/final/Gopkg.lock | 21 + .../ensure/add/all-new-spec/final/Gopkg.toml | 12 + .../ensure/add/all-new-spec/initial/main.go | 13 + .../ensure/add/all-new-spec/testcase.json | 10 + .../ensure/add/all-new/final/Gopkg.lock | 21 + .../ensure/add/all-new/final/Gopkg.toml | 12 + .../ensure/add/all-new/initial/main.go | 13 + .../ensure/add/all-new/testcase.json | 10 + .../ensure/add/desync/final/Gopkg.lock | 27 + .../ensure/add/desync/final/Gopkg.toml | 6 + .../ensure/add/desync/final/main.go | 18 + .../ensure/add/desync/initial/Gopkg.lock | 15 + .../ensure/add/desync/initial/Gopkg.toml | 3 + .../ensure/add/desync/initial/main.go | 21 + .../ensure/add/desync/stdout.txt | 2 + .../ensure/add/desync/testcase.json | 10 + .../errs/double-diff-spec/final/Gopkg.lock | 15 + .../errs/double-diff-spec/final/Gopkg.toml | 8 + .../add/errs/double-diff-spec/initial/main.go | 13 + .../add/errs/double-diff-spec/testcase.json | 10 + .../add/errs/exists-manifest/final/Gopkg.lock | 15 + .../add/errs/exists-manifest/final/Gopkg.toml | 7 + .../errs/exists-manifest/initial/Gopkg.lock | 15 + .../errs/exists-manifest/initial/Gopkg.toml | 7 + .../add/errs/exists-manifest/initial/main.go | 13 + .../add/errs/exists-manifest/testcase.json | 6 + .../ensure/add/errs/exists/final/Gopkg.lock | 15 + .../ensure/add/errs/exists/final/Gopkg.toml | 3 + .../ensure/add/errs/exists/initial/Gopkg.lock | 15 + .../ensure/add/errs/exists/initial/Gopkg.toml | 3 + .../ensure/add/errs/exists/initial/main.go | 13 + .../ensure/add/errs/exists/testcase.json | 6 + .../ensure/add/errs/noarg/final/Gopkg.lock | 21 + .../ensure/add/errs/noarg/final/Gopkg.toml | 3 + .../ensure/add/errs/noarg/final/main.go | 18 + .../ensure/add/errs/noarg/initial/Gopkg.lock | 21 + .../ensure/add/errs/noarg/initial/Gopkg.toml | 3 + .../ensure/add/errs/noarg/initial/main.go | 18 + .../ensure/add/errs/noarg/testcase.json | 6 + .../add/errs/self-add/case1/final/Gopkg.lock | 15 + .../add/errs/self-add/case1/final/Gopkg.toml | 3 + .../errs/self-add/case1/initial/Gopkg.lock | 15 + .../errs/self-add/case1/initial/Gopkg.toml | 3 + .../add/errs/self-add/case1/initial/main.go | 13 + .../add/errs/self-add/case1/testcase.json | 6 + .../add/errs/self-add/case2/final/Gopkg.lock | 9 + .../add/errs/self-add/case2/final/Gopkg.toml | 4 + .../add/errs/self-add/case2/initial/main.go | 7 + .../add/errs/self-add/case2/testcase.json | 7 + .../add/exists-imports/final/Gopkg.lock | 15 + .../add/exists-imports/final/Gopkg.toml | 4 + .../add/exists-imports/initial/Gopkg.toml | 0 .../ensure/add/exists-imports/initial/main.go | 13 + .../ensure/add/exists-imports/testcase.json | 8 + .../final/Gopkg.lock | 21 + .../final/Gopkg.toml | 7 + .../initial/Gopkg.lock | 15 + .../initial/Gopkg.toml | 7 + .../initial/main.go | 13 + .../exists-manifest-constraint/testcase.json | 9 + .../errs/lockless-vendoronly/final/Gopkg.toml | 4 + .../errs/lockless-vendoronly/final/main.go | 12 + .../lockless-vendoronly/initial/Gopkg.toml | 4 + .../errs/lockless-vendoronly/initial/main.go | 12 + .../errs/lockless-vendoronly/testcase.json | 6 + .../default/errs/specargs/final/Gopkg.lock | 15 + .../default/errs/specargs/final/Gopkg.toml | 4 + .../default/errs/specargs/initial/Gopkg.lock | 15 + .../default/errs/specargs/initial/Gopkg.toml | 4 + .../default/errs/specargs/initial/main.go | 12 + .../default/errs/specargs/testcase.json | 6 + .../default/hasheq-dry/final/Gopkg.lock | 15 + .../default/hasheq-dry/final/Gopkg.toml | 4 + .../default/hasheq-dry/initial/Gopkg.lock | 15 + .../default/hasheq-dry/initial/Gopkg.toml | 4 + .../ensure/default/hasheq-dry/initial/main.go | 12 + .../ensure/default/hasheq-dry/testcase.json | 5 + .../hasheq-novendor-dry/final/Gopkg.lock | 15 + .../hasheq-novendor-dry/final/Gopkg.toml | 4 + .../hasheq-novendor-dry/initial/Gopkg.lock | 15 + .../hasheq-novendor-dry/initial/Gopkg.toml | 4 + .../hasheq-novendor-dry/initial/main.go | 12 + .../default/hasheq-novendor-dry/testcase.json | 5 + .../default/hasheq-novendor/final/Gopkg.lock | 15 + .../default/hasheq-novendor/final/Gopkg.toml | 4 + .../hasheq-novendor/initial/Gopkg.lock | 15 + .../hasheq-novendor/initial/Gopkg.toml | 4 + .../default/hasheq-novendor/initial/main.go | 12 + .../default/hasheq-novendor/testcase.json | 5 + .../ensure/default/hasheq/final/Gopkg.lock | 15 + .../ensure/default/hasheq/final/Gopkg.toml | 4 + .../ensure/default/hasheq/initial/Gopkg.lock | 15 + .../ensure/default/hasheq/initial/Gopkg.toml | 4 + .../ensure/default/hasheq/initial/main.go | 12 + .../ensure/default/hasheq/testcase.json | 8 + .../hashneq-novendor-dry/final/Gopkg.lock | 16 + .../hashneq-novendor-dry/final/Gopkg.toml | 4 + .../hashneq-novendor-dry/initial/Gopkg.lock | 16 + .../hashneq-novendor-dry/initial/Gopkg.toml | 4 + .../hashneq-novendor-dry/initial/main.go | 12 + .../hashneq-novendor-dry/testcase.json | 6 + .../hashneq-vendoronly/final/Gopkg.lock | 16 + .../hashneq-vendoronly/final/Gopkg.toml | 4 + .../hashneq-vendoronly/initial/Gopkg.lock | 16 + .../hashneq-vendoronly/initial/Gopkg.toml | 4 + .../hashneq-vendoronly/initial/main.go | 12 + .../default/hashneq-vendoronly/testcase.json | 8 + .../nocode-vendoronly/final/Gopkg.lock | 16 + .../nocode-vendoronly/final/Gopkg.toml | 4 + .../nocode-vendoronly/initial/Gopkg.lock | 16 + .../nocode-vendoronly/initial/Gopkg.toml | 4 + .../default/nocode-vendoronly/testcase.json | 8 + .../ensure/empty/case1/final/Gopkg.lock | 15 + .../ensure/empty/case1/final/Gopkg.toml | 8 + .../ensure/empty/case1/initial/main.go | 12 + .../ensure/empty/case1/testcase.json | 9 + .../ensure/empty/case2/final/Gopkg.lock | 15 + .../ensure/empty/case2/final/Gopkg.toml | 3 + .../ensure/empty/case2/initial/Gopkg.toml | 3 + .../ensure/empty/case2/initial/main.go | 12 + .../ensure/empty/case2/testcase.json | 9 + .../ensure/empty/case3/README.md | 2 + .../ensure/empty/case3/final/Gopkg.lock | 15 + .../ensure/empty/case3/final/Gopkg.toml | 5 + .../ensure/empty/case3/initial/Gopkg.lock | 15 + .../ensure/empty/case3/initial/Gopkg.toml | 5 + .../ensure/empty/case3/initial/main.go | 12 + .../empty/case3/initial/samples/samples.go | 7 + .../ensure/empty/case3/testcase.json | 9 + .../ensure/pkg-errors/case1/final/Gopkg.lock | 9 + .../ensure/pkg-errors/case1/final/Gopkg.toml | 4 + .../ensure/pkg-errors/case1/testcase.json | 8 + .../ensure/pkg-errors/case2/final/Gopkg.toml | 0 .../pkg-errors/case2/initial/Gopkg.toml | 0 .../pkg-errors/case2/initial/bar/bar.go | 3 + .../pkg-errors/case2/initial/baz/.gitignore | 0 .../ensure/pkg-errors/case2/testcase.json | 7 + .../wildcard-ignore/final/Gopkg.lock | 15 + .../wildcard-ignore/final/Gopkg.toml | 5 + .../wildcard-ignore/initial/Gopkg.lock | 9 + .../wildcard-ignore/initial/Gopkg.toml | 5 + .../wildcard-ignore/initial/main.go | 12 + .../initial/samples/samples.go | 7 + .../initial/samples/subsamples/subsamples.go | 7 + .../pkg-ignored/wildcard-ignore/stdout.txt | 11 + .../pkg-ignored/wildcard-ignore/testcase.json | 10 + .../wildcard-other-root/final/Gopkg.lock | 9 + .../wildcard-other-root/final/Gopkg.toml | 1 + .../wildcard-other-root/initial/Gopkg.lock | 9 + .../wildcard-other-root/initial/Gopkg.toml | 1 + .../wildcard-other-root/initial/main.go | 12 + .../initial/samples/samples.go | 7 + .../initial/samples/subsamples/subsamples.go | 7 + .../wildcard-other-root/stdout.txt | 9 + .../wildcard-other-root/testcase.json | 8 + .../ensure/update/case1/final/Gopkg.lock | 21 + .../ensure/update/case1/final/Gopkg.toml | 3 + .../ensure/update/case1/initial/Gopkg.lock | 21 + .../ensure/update/case1/initial/Gopkg.toml | 3 + .../ensure/update/case1/initial/main.go | 18 + .../ensure/update/case1/testcase.json | 10 + .../ensure/update/desync/final/Gopkg.lock | 21 + .../ensure/update/desync/final/Gopkg.toml | 3 + .../ensure/update/desync/final/main.go | 18 + .../ensure/update/desync/initial/Gopkg.lock | 21 + .../ensure/update/desync/initial/Gopkg.toml | 3 + .../ensure/update/desync/initial/main.go | 18 + .../ensure/update/desync/stdout.txt | 1 + .../ensure/update/desync/testcase.json | 9 + .../update/errs/lockless/final/Gopkg.toml | 4 + .../ensure/update/errs/lockless/final/main.go | 12 + .../update/errs/lockless/initial/Gopkg.toml | 4 + .../update/errs/lockless/initial/main.go | 12 + .../ensure/update/errs/lockless/testcase.json | 6 + .../update/errs/nonroot-arg/final/Gopkg.lock | 15 + .../update/errs/nonroot-arg/final/Gopkg.toml | 3 + .../errs/nonroot-arg/initial/Gopkg.lock | 15 + .../errs/nonroot-arg/initial/Gopkg.toml | 3 + .../update/errs/nonroot-arg/initial/main.go | 13 + .../update/errs/nonroot-arg/testcase.json | 6 + .../update/errs/not-in-lock/final/Gopkg.lock | 15 + .../update/errs/not-in-lock/final/Gopkg.toml | 3 + .../errs/not-in-lock/initial/Gopkg.lock | 15 + .../errs/not-in-lock/initial/Gopkg.toml | 3 + .../update/errs/not-in-lock/initial/main.go | 13 + .../update/errs/not-in-lock/testcase.json | 6 + .../spec-with-constraint/final/Gopkg.lock | 15 + .../spec-with-constraint/final/Gopkg.toml | 3 + .../spec-with-constraint/initial/Gopkg.lock | 15 + .../spec-with-constraint/initial/Gopkg.toml | 3 + .../errs/spec-with-constraint/initial/main.go | 13 + .../errs/spec-with-constraint/testcase.json | 6 + .../errs/spec-with-source/final/Gopkg.lock | 15 + .../errs/spec-with-source/final/Gopkg.toml | 3 + .../errs/spec-with-source/initial/Gopkg.lock | 15 + .../errs/spec-with-source/initial/Gopkg.toml | 3 + .../errs/spec-with-source/initial/main.go | 13 + .../errs/spec-with-source/testcase.json | 6 + .../ensure/update/novendor/final/Gopkg.lock | 15 + .../ensure/update/novendor/final/Gopkg.toml | 4 + .../ensure/update/novendor/initial/Gopkg.lock | 15 + .../ensure/update/novendor/initial/Gopkg.toml | 4 + .../ensure/update/novendor/initial/main.go | 12 + .../ensure/update/novendor/testcase.json | 5 + .../harness_tests/init/case1/final/Gopkg.lock | 20 + .../harness_tests/init/case1/final/Gopkg.toml | 8 + .../init/case1/initial/foo/bar.go | 13 + .../harness_tests/init/case1/initial/main.go | 19 + .../harness_tests/init/case1/testcase.json | 14 + .../harness_tests/init/case2/final/Gopkg.lock | 21 + .../harness_tests/init/case2/final/Gopkg.toml | 12 + .../init/case2/initial/foo/bar.go | 13 + .../harness_tests/init/case2/initial/main.go | 19 + .../harness_tests/init/case2/testcase.json | 13 + .../harness_tests/init/case3/final/Gopkg.lock | 20 + .../harness_tests/init/case3/final/Gopkg.toml | 8 + .../init/case3/initial/foo/bar.go | 13 + .../harness_tests/init/case3/initial/main.go | 19 + .../harness_tests/init/case3/testcase.json | 13 + .../harness_tests/init/case4/final/Gopkg.lock | 21 + .../harness_tests/init/case4/final/Gopkg.toml | 12 + .../init/case4/initial/foo/bar.go | 13 + .../harness_tests/init/case4/initial/main.go | 19 + .../harness_tests/init/case4/testcase.json | 12 + .../harness_tests/init/glide/case1/README.md | 1 + .../init/glide/case1/final/Gopkg.lock | 26 + .../init/glide/case1/final/Gopkg.toml | 12 + .../init/glide/case1/initial/glide.lock | 14 + .../init/glide/case1/initial/glide.yaml | 21 + .../init/glide/case1/initial/main.go | 17 + .../glide/case1/initial/samples/samples.go | 12 + .../init/glide/case1/testcase.json | 15 + .../harness_tests/init/glide/case2/README.md | 1 + .../init/glide/case2/final/Gopkg.lock | 21 + .../init/glide/case2/final/Gopkg.toml | 8 + .../init/glide/case2/initial/glide.lock | 12 + .../init/glide/case2/initial/glide.yaml | 20 + .../init/glide/case2/initial/main.go | 16 + .../init/glide/case2/testcase.json | 14 + .../harness_tests/init/glide/case3/README.md | 1 + .../init/glide/case3/final/Gopkg.lock | 21 + .../init/glide/case3/final/Gopkg.toml | 8 + .../init/glide/case3/initial/main.go | 16 + .../init/glide/case3/testcase.json.ignore | 11 + .../harness_tests/init/glide/case4/README.md | 1 + .../init/glide/case4/final/Gopkg.lock | 21 + .../init/glide/case4/final/Gopkg.toml | 8 + .../init/glide/case4/initial/glide.yaml | 20 + .../init/glide/case4/initial/main.go | 16 + .../init/glide/case4/testcase.json | 14 + .../init/glock/case1/final/Gopkg.lock | 21 + .../init/glock/case1/final/Gopkg.toml | 8 + .../init/glock/case1/initial/GLOCKFILE | 3 + .../init/glock/case1/initial/main.go | 16 + .../init/glock/case1/testcase.json | 13 + .../init/godep/case1/final/Gopkg.lock | 21 + .../init/godep/case1/final/Gopkg.toml | 8 + .../godep/case1/initial/Godeps/Godeps.json | 17 + .../init/godep/case1/initial/main.go | 16 + .../init/godep/case1/testcase.json | 13 + .../init/govend/case1/final/Gopkg.lock | 21 + .../init/govend/case1/final/Gopkg.toml | 8 + .../init/govend/case1/initial/main.go | 16 + .../init/govend/case1/initial/vendor.yml | 5 + .../init/govend/case1/testcase.json | 13 + .../init/govendor/case1/README.md | 1 + .../init/govendor/case1/final/Gopkg.lock | 21 + .../init/govendor/case1/final/Gopkg.toml | 12 + .../init/govendor/case1/initial/main.go | 16 + .../govendor/case1/initial/samples/samples.go | 12 + .../init/govendor/case1/testcase.json | 14 + .../init/gvt/case1/final/Gopkg.lock | 28 + .../init/gvt/case1/final/Gopkg.toml | 16 + .../init/gvt/case1/initial/main.go | 20 + .../init/gvt/case1/testcase.json | 13 + .../init/manifest-exists/final/Gopkg.toml | 0 .../init/manifest-exists/initial/Gopkg.toml | 0 .../init/manifest-exists/testcase.json | 7 + .../final/project_dir/Gopkg.lock | 14 + .../final/project_dir/Gopkg.toml | 8 + .../initial/project_dir/foo/bar.go | 13 + .../relative_path/initial/project_dir/main.go | 18 + .../init/relative_path/testcase.json | 7 + .../init/skip-hidden/final/Gopkg.lock | 15 + .../init/skip-hidden/final/Gopkg.toml | 8 + .../init/skip-hidden/initial/.foo/main.go | 19 + .../init/skip-hidden/initial/_foo/main.go | 19 + .../init/skip-hidden/initial/lib.go | 13 + .../init/skip-hidden/initial/testdata/main.go | 19 + .../init/skip-hidden/testcase.json | 9 + .../init/usage/with_h_flag/testcase.json | 6 + .../usage/with_not_defined_flag/testcase.json | 6 + .../init/vndr/case1/final/Gopkg.lock | 21 + .../init/vndr/case1/final/Gopkg.toml | 8 + .../init/vndr/case1/initial/main.go | 16 + .../init/vndr/case1/initial/vendor.conf | 3 + .../init/vndr/case1/testcase.json | 13 + .../status/case1/dot/final/Gopkg.lock | 21 + .../status/case1/dot/final/Gopkg.toml | 3 + .../status/case1/dot/initial/Gopkg.lock | 13 + .../status/case1/dot/initial/Gopkg.toml | 3 + .../status/case1/dot/initial/main.go | 18 + .../harness_tests/status/case1/dot/stdout.txt | 9 + .../status/case1/dot/testcase.json | 11 + .../status/case1/json/final/Gopkg.lock | 21 + .../status/case1/json/final/Gopkg.toml | 3 + .../status/case1/json/initial/Gopkg.lock | 13 + .../status/case1/json/initial/Gopkg.toml | 3 + .../status/case1/json/initial/main.go | 18 + .../status/case1/json/stdout.txt | 1 + .../status/case1/json/testcase.json | 11 + .../status/case1/table/final/Gopkg.lock | 21 + .../status/case1/table/final/Gopkg.toml | 3 + .../status/case1/table/initial/Gopkg.lock | 13 + .../status/case1/table/initial/Gopkg.toml | 3 + .../status/case1/table/initial/main.go | 18 + .../status/case1/table/stdout.txt | 3 + .../status/case1/table/testcase.json | 11 + .../status/case1/template/final/Gopkg.lock | 21 + .../status/case1/template/final/Gopkg.toml | 3 + .../status/case1/template/initial/Gopkg.lock | 13 + .../status/case1/template/initial/Gopkg.toml | 3 + .../status/case1/template/initial/main.go | 18 + .../status/case1/template/stdout.txt | 2 + .../status/case1/template/testcase.json | 11 + .../ignore_lock_mismatch/final/Gopkg.lock | 9 + .../ignore_lock_mismatch/final/Gopkg.toml | 2 + .../ignore_lock_mismatch/initial/Gopkg.lock | 9 + .../ignore_lock_mismatch/initial/Gopkg.toml | 2 + .../ignore_lock_mismatch/initial/main.go | 12 + .../status/ignore_lock_mismatch/testcase.json | 7 + .../final/Gopkg.lock | 9 + .../final/Gopkg.toml | 0 .../initial/Gopkg.lock | 9 + .../initial/Gopkg.toml | 0 .../initial/main.go | 12 + .../missing_pkgs_lock_mismatch/testcase.json | 7 + .../override_constraint/final/Gopkg.lock | 21 + .../override_constraint/final/Gopkg.toml | 3 + .../override_constraint/initial/Gopkg.lock | 21 + .../override_constraint/initial/Gopkg.toml | 3 + .../override_constraint/initial/main.go | 12 + .../status/override_constraint/stdout.txt | 3 + .../status/override_constraint/testcase.json | 11 + .../revision_constraint/final/Gopkg.lock | 20 + .../revision_constraint/final/Gopkg.toml | 3 + .../revision_constraint/initial/Gopkg.lock | 20 + .../revision_constraint/initial/Gopkg.toml | 3 + .../revision_constraint/initial/main.go | 12 + .../status/revision_constraint/stdout.txt | 3 + .../status/revision_constraint/testcase.json | 11 + .../status/without_lock/final/Gopkg.toml | 0 .../status/without_lock/initial/Gopkg.toml | 0 .../status/without_lock/testcase.json | 6 + .../cmd/dep/testdata/init/directdeps/main.go | 9 + .../status/collect_constraints/main.go | 14 + .../github.com/golang/dep/cmd/dep/version.go | 45 + vendor/github.com/golang/dep/context.go | 297 ++ vendor/github.com/golang/dep/context_test.go | 529 +++ vendor/github.com/golang/dep/doc.go | 6 + vendor/github.com/golang/dep/docs/FAQ.md | 491 ++ .../github.com/golang/dep/docs/Gopkg.lock.md | 86 + .../github.com/golang/dep/docs/Gopkg.toml.md | 255 + .../golang/dep/docs/assets/DigbyFlat.png | Bin 0 -> 393796 bytes .../golang/dep/docs/assets/DigbyFlat.svg | 1 + .../dep/docs/assets/DigbyFlatScene2.png | Bin 0 -> 550791 bytes .../dep/docs/assets/DigbyFlatScene2.svg | 1 + .../dep/docs/assets/DigbyScene2Flat.png | Bin 0 -> 600027 bytes .../dep/docs/assets/DigbyScene2Flat.svg | 1 + .../dep/docs/assets/DigbyScene2Shadows.png | Bin 0 -> 703064 bytes .../dep/docs/assets/DigbyScene2Shadows.svg | 1 + .../golang/dep/docs/assets/DigbyShadows.png | Bin 0 -> 456068 bytes .../golang/dep/docs/assets/DigbyShadows.svg | 1 + .../dep/docs/assets/DigbyShadowsScene2.png | Bin 0 -> 619236 bytes .../dep/docs/assets/DigbyShadowsScene2.svg | 1 + .../golang/dep/docs/assets/StatusGraph.png | Bin 0 -> 19271 bytes .../dep/docs/assets/annotated-func-arrows.png | Bin 0 -> 42366 bytes .../golang/dep/docs/assets/base-arrows.png | Bin 0 -> 33999 bytes .../golang/dep/docs/assets/four-states.png | Bin 0 -> 32855 bytes .../golang/dep/docs/assets/func-toggles.png | Bin 0 -> 50383 bytes .../golang/dep/docs/assets/in-sync.png | Bin 0 -> 34774 bytes .../golang/dep/docs/assets/lock-back.png | Bin 0 -> 35714 bytes .../dep/docs/assets/required-arrows.png | Bin 0 -> 46651 bytes .../github.com/golang/dep/docs/daily-dep.md | 127 + .../github.com/golang/dep/docs/deduction.md | 26 + .../golang/dep/docs/ensure-mechanics.md | 203 + .../golang/dep/docs/failure-modes.md | 204 + vendor/github.com/golang/dep/docs/glossary.md | 139 + .../golang/dep/docs/installation.md | 19 + .../golang/dep/docs/introduction.md | 11 + .../github.com/golang/dep/docs/migrating.md | 103 + .../github.com/golang/dep/docs/new-project.md | 37 + .../github.com/golang/dep/docs/the-solver.md | 84 + .../dep/gps/_testdata/badrepo/README.md | 5 + .../badrepo/corrupt_dot_git_directory.tar | Bin 0 -> 459 bytes .../gps/_testdata/cmd/echosleep/echosleep.go | 21 + .../cmd/stdout_stderr/stdout_stderr.go | 14 + .../digest/github.com/alice/match/match.go | 5 + .../github.com/alice/mismatch/mismatch.go | 5 + .../github.com/alice/notInLock/notInLock.go | 5 + .../github.com/bob/emptyDigest/emptyDigest.go | 5 + .../digest/github.com/bob/match/match.go | 5 + .../digest/launchpad.net/match/match.go | 5 + .../golang/dep/gps/_testdata/src/bad/bad.go | 6 + .../dep/gps/_testdata/src/buildtag/invalid.go | 17 + .../dep/gps/_testdata/src/canon_confl/a.go | 9 + .../dep/gps/_testdata/src/canon_confl/b.go | 9 + .../dep/gps/_testdata/src/canonical/main.go | 9 + .../gps/_testdata/src/canonical/sub/sub.go | 5 + .../golang/dep/gps/_testdata/src/cycle/a.go | 16 + .../dep/gps/_testdata/src/cycle/one/a.go | 16 + .../dep/gps/_testdata/src/cycle/two/a.go | 16 + .../dep/gps/_testdata/src/disallow/a.go | 18 + .../src/disallow/testdata/another.go | 11 + .../gps/_testdata/src/dotgodir/.go/.gitkeep | 0 .../dep/gps/_testdata/src/dotgodir/.go/dot.go | 7 + .../dep/gps/_testdata/src/dotgodir/.m1p/a.go | 16 + .../dep/gps/_testdata/src/dotgodir/.m1p/b.go | 15 + .../_testdata/src/dotgodir/foo.go/.gitkeep | 0 .../gps/_testdata/src/dotgodir/foo.go/foo.go | 12 + .../dep/gps/_testdata/src/doublenest/a.go | 16 + .../src/doublenest/namemismatch/m1p/a.go | 16 + .../src/doublenest/namemismatch/m1p/b.go | 15 + .../src/doublenest/namemismatch/nm.go | 16 + .../dep/gps/_testdata/src/empty/.gitkeep | 0 .../src/github.com/example/varied/locals.go | 17 + .../src/github.com/example/varied/m1p/a.go | 16 + .../src/github.com/example/varied/m1p/b.go | 15 + .../src/github.com/example/varied/main.go | 13 + .../example/varied/namemismatch/nm.go | 16 + .../varied/otherpath/otherpath_test.go | 9 + .../example/varied/simple/another/another.go | 11 + .../varied/simple/another/another_test.go | 11 + .../example/varied/simple/another/locals.go | 9 + .../example/varied/simple/locals.go | 11 + .../example/varied/simple/simple.go | 16 + .../golang/dep/gps/_testdata/src/igmain/a.go | 16 + .../dep/gps/_testdata/src/igmain/igmain.go | 11 + .../gps/_testdata/src/igmainfirst/igmain.go | 11 + .../dep/gps/_testdata/src/igmainfirst/z.go | 16 + .../dep/gps/_testdata/src/igmainlong/a.go | 16 + .../gps/_testdata/src/igmainlong/igmain.go | 13 + .../golang/dep/gps/_testdata/src/igmaint/a.go | 16 + .../dep/gps/_testdata/src/igmaint/igmain.go | 11 + .../dep/gps/_testdata/src/igmaint/t_test.go | 15 + .../golang/dep/gps/_testdata/src/m1p/a.go | 16 + .../golang/dep/gps/_testdata/src/m1p/b.go | 15 + .../golang/dep/gps/_testdata/src/missing/a.go | 19 + .../dep/gps/_testdata/src/missing/m1p/a.go | 16 + .../dep/gps/_testdata/src/missing/m1p/b.go | 15 + .../golang/dep/gps/_testdata/src/nest/a.go | 16 + .../dep/gps/_testdata/src/nest/m1p/a.go | 16 + .../dep/gps/_testdata/src/nest/m1p/b.go | 15 + .../dep/gps/_testdata/src/relimport/a.go | 13 + .../dep/gps/_testdata/src/relimport/dot/a.go | 14 + .../gps/_testdata/src/relimport/dotdot/a.go | 13 + .../_testdata/src/relimport/dotdotslash/a.go | 13 + .../gps/_testdata/src/relimport/dotslash/a.go | 13 + .../golang/dep/gps/_testdata/src/ren/m1p/a.go | 16 + .../golang/dep/gps/_testdata/src/ren/m1p/b.go | 15 + .../dep/gps/_testdata/src/ren/simple/a.go | 16 + .../golang/dep/gps/_testdata/src/simple/a.go | 16 + .../dep/gps/_testdata/src/simpleallt/a.go | 16 + .../gps/_testdata/src/simpleallt/a_test.go | 15 + .../gps/_testdata/src/simpleallt/t_test.go | 15 + .../golang/dep/gps/_testdata/src/simplet/a.go | 16 + .../dep/gps/_testdata/src/simplet/t_test.go | 15 + .../dep/gps/_testdata/src/simplext/a.go | 16 + .../dep/gps/_testdata/src/simplext/a_test.go | 15 + .../golang/dep/gps/_testdata/src/skip_/_a.go | 15 + .../golang/dep/gps/_testdata/src/skip_/a.go | 16 + .../golang/dep/gps/_testdata/src/t/t_test.go | 15 + .../golang/dep/gps/_testdata/src/twopkgs/a.go | 16 + .../golang/dep/gps/_testdata/src/twopkgs/b.go | 15 + .../dep/gps/_testdata/src/varied/locals.go | 17 + .../dep/gps/_testdata/src/varied/m1p/a.go | 16 + .../dep/gps/_testdata/src/varied/m1p/b.go | 15 + .../dep/gps/_testdata/src/varied/main.go | 13 + .../_testdata/src/varied/namemismatch/nm.go | 16 + .../src/varied/otherpath/otherpath_test.go | 9 + .../src/varied/simple/another/another.go | 11 + .../src/varied/simple/another/another_test.go | 11 + .../src/varied/simple/another/locals.go | 9 + .../gps/_testdata/src/varied/simple/locals.go | 11 + .../gps/_testdata/src/varied/simple/simple.go | 16 + .../src/varied_hidden/.onlyfromtests/a.go | 18 + .../src/varied_hidden/.onlyfromtests/b.go | 15 + .../src/varied_hidden/_frommain/a.go | 16 + .../_testdata/src/varied_hidden/_never/a.go | 16 + .../varied_hidden/_secondorder/secondorder.go | 11 + .../src/varied_hidden/always/always_test.go | 7 + .../src/varied_hidden/dotdotslash/a.go | 13 + .../gps/_testdata/src/varied_hidden/locals.go | 14 + .../gps/_testdata/src/varied_hidden/main.go | 13 + .../src/varied_hidden/simple/locals.go | 11 + .../src/varied_hidden/simple/simple.go | 16 + .../varied_hidden/simple/testdata/another.go | 7 + .../golang/dep/gps/_testdata/src/xt/a_test.go | 15 + vendor/github.com/golang/dep/gps/bridge.go | 223 + vendor/github.com/golang/dep/gps/cmd.go | 17 + vendor/github.com/golang/dep/gps/cmd_unix.go | 82 + .../github.com/golang/dep/gps/cmd_windows.go | 18 + .../golang/dep/gps/constraint_test.go | 1007 ++++ .../github.com/golang/dep/gps/constraints.go | 453 ++ vendor/github.com/golang/dep/gps/deduce.go | 892 ++++ .../github.com/golang/dep/gps/deduce_test.go | 679 +++ vendor/github.com/golang/dep/gps/discovery.go | 83 + vendor/github.com/golang/dep/gps/example.go | 79 + .../github.com/golang/dep/gps/filesystem.go | 136 + .../golang/dep/gps/filesystem_test.go | 220 + vendor/github.com/golang/dep/gps/hash.go | 133 + vendor/github.com/golang/dep/gps/hash_test.go | 686 +++ .../github.com/golang/dep/gps/identifier.go | 226 + .../golang/dep/gps/internal/pb/pb.go | 8 + .../dep/gps/internal/pb/source_cache.pb.go | 199 + .../dep/gps/internal/pb/source_cache.proto | 36 + vendor/github.com/golang/dep/gps/lock.go | 235 + vendor/github.com/golang/dep/gps/lock_test.go | 184 + vendor/github.com/golang/dep/gps/lockdiff.go | 245 + .../golang/dep/gps/lockdiff_test.go | 501 ++ .../github.com/golang/dep/gps/manager_test.go | 1053 +++++ vendor/github.com/golang/dep/gps/manifest.go | 155 + .../golang/dep/gps/manifest_test.go | 29 + .../github.com/golang/dep/gps/maybe_source.go | 262 ++ vendor/github.com/golang/dep/gps/metrics.go | 84 + .../github.com/golang/dep/gps/paths/paths.go | 21 + .../golang/dep/gps/paths/paths_test.go | 37 + .../golang/dep/gps/pkgtree/digest.go | 472 ++ .../golang/dep/gps/pkgtree/digest_test.go | 220 + .../golang/dep/gps/pkgtree/dirwalk.go | 139 + .../golang/dep/gps/pkgtree/ignored_ruleset.go | 111 + .../dep/gps/pkgtree/ignored_ruleset_test.go | 204 + .../golang/dep/gps/pkgtree/pkgtree.go | 1108 +++++ .../golang/dep/gps/pkgtree/pkgtree_test.go | 2273 +++++++++ .../golang/dep/gps/pkgtree/reachmap.go | 65 + vendor/github.com/golang/dep/gps/prune.go | 382 ++ .../github.com/golang/dep/gps/prune_test.go | 790 ++++ vendor/github.com/golang/dep/gps/rootdata.go | 204 + .../golang/dep/gps/rootdata_test.go | 226 + vendor/github.com/golang/dep/gps/satisfy.go | 337 ++ vendor/github.com/golang/dep/gps/selection.go | 242 + .../golang/dep/gps/selection_test.go | 63 + vendor/github.com/golang/dep/gps/solution.go | 159 + .../golang/dep/gps/solution_test.go | 180 + .../golang/dep/gps/solve_basic_test.go | 1596 +++++++ .../golang/dep/gps/solve_bimodal_test.go | 1504 ++++++ .../golang/dep/gps/solve_failures.go | 572 +++ .../github.com/golang/dep/gps/solve_test.go | 259 + vendor/github.com/golang/dep/gps/solver.go | 1421 ++++++ .../golang/dep/gps/solver_inputs_test.go | 228 + vendor/github.com/golang/dep/gps/source.go | 638 +++ .../github.com/golang/dep/gps/source_cache.go | 226 + .../golang/dep/gps/source_cache_bolt.go | 515 ++ .../dep/gps/source_cache_bolt_encode.go | 465 ++ .../dep/gps/source_cache_bolt_encode_test.go | 78 + .../golang/dep/gps/source_cache_bolt_test.go | 298 ++ .../golang/dep/gps/source_cache_multi.go | 120 + .../golang/dep/gps/source_cache_test.go | 578 +++ .../golang/dep/gps/source_errors.go | 35 + .../golang/dep/gps/source_errors_test.go | 30 + .../golang/dep/gps/source_manager.go | 783 ++++ .../golang/dep/gps/source_manager_test.go | 114 + .../github.com/golang/dep/gps/source_test.go | 180 + vendor/github.com/golang/dep/gps/strings.go | 51 + vendor/github.com/golang/dep/gps/trace.go | 205 + .../github.com/golang/dep/gps/typed_radix.go | 92 + .../golang/dep/gps/typed_radix_test.go | 26 + vendor/github.com/golang/dep/gps/vcs_repo.go | 387 ++ .../golang/dep/gps/vcs_repo_test.go | 462 ++ .../github.com/golang/dep/gps/vcs_source.go | 690 +++ .../golang/dep/gps/vcs_source_test.go | 897 ++++ .../github.com/golang/dep/gps/vcs_version.go | 67 + .../golang/dep/gps/vcs_version_test.go | 59 + vendor/github.com/golang/dep/gps/version.go | 875 ++++ .../golang/dep/gps/version_queue.go | 158 + .../golang/dep/gps/version_queue_test.go | 259 + .../github.com/golang/dep/gps/version_test.go | 189 + .../golang/dep/gps/version_unifier.go | 302 ++ .../golang/dep/gps/version_unifier_test.go | 142 + .../github.com/golang/dep/hack/build-all.bash | 41 + .../github.com/golang/dep/hack/coverage.bash | 16 + .../golang/dep/hack/licenseok/main.go | 201 + vendor/github.com/golang/dep/hack/lint.bash | 12 + .../golang/dep/hack/validate-gofmt.bash | 38 + .../golang/dep/hack/validate-licence.bash | 12 + .../golang/dep/hack/validate-vendor.bash | 53 + .../golang/dep/internal/feedback/feedback.go | 117 + .../dep/internal/feedback/feedback_test.go | 95 + .../github.com/golang/dep/internal/fs/fs.go | 694 +++ .../golang/dep/internal/fs/fs_test.go | 1126 +++++ .../golang/dep/internal/fs/rename.go | 31 + .../golang/dep/internal/fs/rename_windows.go | 42 + .../internal/fs/testdata/symlinks/dir-symlink | 1 + .../fs/testdata/symlinks/file-symlink | 1 + .../fs/testdata/symlinks/invalid-symlink | 1 + .../fs/testdata/symlinks/windows-file-symlink | 1 + .../golang/dep/internal/fs/testdata/test.file | 0 .../dep/internal/importers/base/importer.go | 333 ++ .../internal/importers/base/importer_test.go | 443 ++ .../dep/internal/importers/glide/importer.go | 211 + .../internal/importers/glide/importer_test.go | 222 + .../importers/glide/testdata/glide.lock | 12 + .../importers/glide/testdata/glide.yaml | 20 + .../importers/glide/testdata/golden.txt | 7 + .../dep/internal/importers/glock/importer.go | 150 + .../internal/importers/glock/importer_test.go | 137 + .../importers/glock/testdata/GLOCKFILE | 3 + .../importers/glock/testdata/golden.txt | 6 + .../dep/internal/importers/godep/importer.go | 117 + .../internal/importers/godep/importer_test.go | 208 + .../importers/godep/testdata/Godeps.json | 16 + .../importers/godep/testdata/golden.txt | 6 + .../dep/internal/importers/govend/importer.go | 121 + .../importers/govend/importer_test.go | 191 + .../importers/govend/testdata/golden.txt | 6 + .../importers/govend/testdata/vendor.yml | 6 + .../internal/importers/govendor/importer.go | 151 + .../importers/govendor/importer_test.go | 155 + .../importers/govendor/testdata/golden.txt | 7 + .../importers/govendor/testdata/vendor.json | 22 + .../dep/internal/importers/gvt/importer.go | 130 + .../internal/importers/gvt/importer_test.go | 248 + .../importers/gvt/testdata/golden.txt | 7 + .../internal/importers/gvt/testdata/manifest | 19 + .../dep/internal/importers/importers.go | 45 + .../importers/importertest/testcase.go | 185 + .../importers/importertest/testdata.go | 67 + .../dep/internal/importers/vndr/importer.go | 149 + .../internal/importers/vndr/importer_test.go | 218 + .../importers/vndr/testdata/golden.txt | 6 + .../importers/vndr/testdata/vendor.conf | 4 + .../dep/internal/test/integration/testcase.go | 201 + .../dep/internal/test/integration/testproj.go | 310 ++ .../golang/dep/internal/test/test.go | 625 +++ .../golang/dep/internal/test/writer.go | 31 + vendor/github.com/golang/dep/lock.go | 203 + vendor/github.com/golang/dep/lock_test.go | 165 + vendor/github.com/golang/dep/manifest.go | 640 +++ vendor/github.com/golang/dep/manifest_test.go | 821 ++++ vendor/github.com/golang/dep/project.go | 276 ++ vendor/github.com/golang/dep/project_test.go | 222 + .../golang/dep/test_project_context_test.go | 168 + .../golang/dep/testdata/analyzer/Gopkg.toml | 8 + .../golang/dep/testdata/lock/error0.toml | 9 + .../golang/dep/testdata/lock/error1.toml | 8 + .../golang/dep/testdata/lock/error2.toml | 6 + .../golang/dep/testdata/lock/golden0.toml | 13 + .../golang/dep/testdata/lock/golden1.toml | 13 + .../golang/dep/testdata/manifest/error1.toml | 15 + .../golang/dep/testdata/manifest/error2.toml | 9 + .../golang/dep/testdata/manifest/error3.toml | 9 + .../golang/dep/testdata/manifest/golden.toml | 17 + .../golang/dep/testdata/rootfind/Gopkg.toml | 0 .../dep/testdata/rootfind/subdir/.gitkeep | 0 .../dep/testdata/txn_writer/badinput_fileroot | 0 .../txn_writer/expected_diff_output.txt | 31 + .../testdata/txn_writer/expected_lock.toml | 15 + .../txn_writer/expected_manifest.toml | 30 + .../testdata/txn_writer/original_lock.toml | 14 + .../dep/testdata/txn_writer/updated_lock.toml | 21 + vendor/github.com/golang/dep/txn_writer.go | 481 ++ .../github.com/golang/dep/txn_writer_test.go | 601 +++ .../github.com/golang/dep/website/.gitignore | 11 + .../blog/2018-01-23-announce-v0.4.0.md | 41 + .../golang/dep/website/core/Footer.js | 29 + .../golang/dep/website/i18n/en.json | 30 + .../golang/dep/website/package.json | 14 + .../golang/dep/website/pages/en/help.js | 43 + .../golang/dep/website/pages/en/index.js | 92 + .../golang/dep/website/pages/en/users.js | 40 + .../golang/dep/website/sidebars.json | 6 + .../golang/dep/website/siteConfig.js | 46 + .../golang/dep/website/static/css/custom.css | 52 + .../github.com/golang/dep/website/yarn.lock | 1739 +++++++ vendor/github.com/golang/protobuf/.gitignore | 16 + vendor/github.com/golang/protobuf/.travis.yml | 18 + vendor/github.com/golang/protobuf/AUTHORS | 3 + .../github.com/golang/protobuf/CONTRIBUTORS | 3 + vendor/github.com/golang/protobuf/LICENSE | 31 + .../github.com/golang/protobuf/Make.protobuf | 40 + vendor/github.com/golang/protobuf/Makefile | 55 + vendor/github.com/golang/protobuf/README.md | 244 + .../golang/protobuf/_conformance/Makefile | 33 + .../protobuf/_conformance/conformance.go | 161 + .../conformance_proto/conformance.pb.go | 1885 ++++++++ .../conformance_proto/conformance.proto | 285 ++ .../golang/protobuf/descriptor/descriptor.go | 93 + .../protobuf/descriptor/descriptor_test.go | 32 + .../golang/protobuf/jsonpb/jsonpb.go | 1083 +++++ .../golang/protobuf/jsonpb/jsonpb_test.go | 896 ++++ .../jsonpb/jsonpb_test_proto/Makefile | 33 + .../jsonpb_test_proto/more_test_objects.pb.go | 266 ++ .../jsonpb_test_proto/more_test_objects.proto | 69 + .../jsonpb_test_proto/test_objects.pb.go | 852 ++++ .../jsonpb_test_proto/test_objects.proto | 147 + .../github.com/golang/protobuf/proto/Makefile | 43 + .../golang/protobuf/proto/all_test.go | 2278 +++++++++ .../golang/protobuf/proto/any_test.go | 300 ++ .../github.com/golang/protobuf/proto/clone.go | 229 + .../golang/protobuf/proto/clone_test.go | 300 ++ .../golang/protobuf/proto/decode.go | 970 ++++ .../golang/protobuf/proto/decode_test.go | 258 + .../golang/protobuf/proto/discard.go | 151 + .../golang/protobuf/proto/encode.go | 1362 ++++++ .../golang/protobuf/proto/encode_test.go | 85 + .../github.com/golang/protobuf/proto/equal.go | 300 ++ .../golang/protobuf/proto/equal_test.go | 224 + .../golang/protobuf/proto/extensions.go | 587 +++ .../golang/protobuf/proto/extensions_test.go | 536 +++ .../github.com/golang/protobuf/proto/lib.go | 897 ++++ .../golang/protobuf/proto/map_test.go | 46 + .../golang/protobuf/proto/message_set.go | 311 ++ .../golang/protobuf/proto/message_set_test.go | 66 + .../golang/protobuf/proto/pointer_reflect.go | 484 ++ .../golang/protobuf/proto/pointer_unsafe.go | 270 ++ .../golang/protobuf/proto/properties.go | 872 ++++ .../protobuf/proto/proto3_proto/proto3.pb.go | 347 ++ .../protobuf/proto/proto3_proto/proto3.proto | 87 + .../golang/protobuf/proto/proto3_test.go | 135 + .../golang/protobuf/proto/size2_test.go | 63 + .../golang/protobuf/proto/size_test.go | 164 + .../golang/protobuf/proto/testdata/Makefile | 50 + .../protobuf/proto/testdata/golden_test.go | 86 + .../golang/protobuf/proto/testdata/test.pb.go | 4147 +++++++++++++++++ .../golang/protobuf/proto/testdata/test.proto | 548 +++ .../github.com/golang/protobuf/proto/text.go | 854 ++++ .../golang/protobuf/proto/text_parser.go | 895 ++++ .../golang/protobuf/proto/text_parser_test.go | 673 +++ .../golang/protobuf/proto/text_test.go | 474 ++ .../golang/protobuf/protoc-gen-go/Makefile | 33 + .../protoc-gen-go/descriptor/Makefile | 37 + .../protoc-gen-go/descriptor/descriptor.pb.go | 2215 +++++++++ .../protoc-gen-go/descriptor/descriptor.proto | 849 ++++ .../golang/protobuf/protoc-gen-go/doc.go | 51 + .../protobuf/protoc-gen-go/generator/Makefile | 40 + .../protoc-gen-go/generator/generator.go | 2866 ++++++++++++ .../protoc-gen-go/generator/name_test.go | 114 + .../protobuf/protoc-gen-go/grpc/grpc.go | 463 ++ .../protobuf/protoc-gen-go/link_grpc.go | 34 + .../golang/protobuf/protoc-gen-go/main.go | 98 + .../protobuf/protoc-gen-go/plugin/Makefile | 45 + .../protoc-gen-go/plugin/plugin.pb.go | 293 ++ .../protoc-gen-go/plugin/plugin.pb.golden | 83 + .../protoc-gen-go/plugin/plugin.proto | 167 + .../protobuf/protoc-gen-go/testdata/Makefile | 73 + .../testdata/extension_base.proto | 46 + .../testdata/extension_extra.proto | 38 + .../protoc-gen-go/testdata/extension_test.go | 210 + .../testdata/extension_user.proto | 100 + .../protoc-gen-go/testdata/grpc.proto | 59 + .../protoc-gen-go/testdata/imp.pb.go.golden | 113 + .../protobuf/protoc-gen-go/testdata/imp.proto | 70 + .../protoc-gen-go/testdata/imp2.proto | 43 + .../protoc-gen-go/testdata/imp3.proto | 38 + .../protoc-gen-go/testdata/main_test.go | 46 + .../protoc-gen-go/testdata/multi/multi1.proto | 44 + .../protoc-gen-go/testdata/multi/multi2.proto | 46 + .../protoc-gen-go/testdata/multi/multi3.proto | 43 + .../protoc-gen-go/testdata/my_test/test.pb.go | 870 ++++ .../testdata/my_test/test.pb.go.golden | 870 ++++ .../protoc-gen-go/testdata/my_test/test.proto | 156 + .../protoc-gen-go/testdata/proto3.proto | 53 + .../github.com/golang/protobuf/ptypes/any.go | 139 + .../golang/protobuf/ptypes/any/any.pb.go | 178 + .../golang/protobuf/ptypes/any/any.proto | 149 + .../golang/protobuf/ptypes/any_test.go | 113 + .../github.com/golang/protobuf/ptypes/doc.go | 35 + .../golang/protobuf/ptypes/duration.go | 102 + .../protobuf/ptypes/duration/duration.pb.go | 144 + .../protobuf/ptypes/duration/duration.proto | 117 + .../golang/protobuf/ptypes/duration_test.go | 121 + .../golang/protobuf/ptypes/empty/empty.pb.go | 66 + .../golang/protobuf/ptypes/empty/empty.proto | 52 + .../golang/protobuf/ptypes/regen.sh | 43 + .../protobuf/ptypes/struct/struct.pb.go | 380 ++ .../protobuf/ptypes/struct/struct.proto | 96 + .../golang/protobuf/ptypes/timestamp.go | 134 + .../protobuf/ptypes/timestamp/timestamp.pb.go | 160 + .../protobuf/ptypes/timestamp/timestamp.proto | 133 + .../golang/protobuf/ptypes/timestamp_test.go | 153 + .../protobuf/ptypes/wrappers/wrappers.pb.go | 260 ++ .../protobuf/ptypes/wrappers/wrappers.proto | 118 + vendor/github.com/jmank88/nuts/.gitignore | 3 + vendor/github.com/jmank88/nuts/.travis.yml | 9 + vendor/github.com/jmank88/nuts/Gopkg.lock | 21 + vendor/github.com/jmank88/nuts/Gopkg.toml | 3 + vendor/github.com/jmank88/nuts/LICENSE | 21 + vendor/github.com/jmank88/nuts/README.md | 53 + .../jmank88/nuts/cmd/testdb/main.go | 89 + .../jmank88/nuts/cmd/testpaths/main.go | 156 + .../github.com/jmank88/nuts/example_test.go | 22 + vendor/github.com/jmank88/nuts/key.go | 39 + vendor/github.com/jmank88/nuts/key_test.go | 114 + vendor/github.com/jmank88/nuts/nuts.go | 2 + vendor/github.com/jmank88/nuts/paths.go | 260 ++ vendor/github.com/jmank88/nuts/paths_test.go | 338 ++ vendor/github.com/jmank88/nuts/types.go | 16 + .../github.com/nightlyone/lockfile/.gitignore | 27 + .../nightlyone/lockfile/.gitmodules | 3 + .../nightlyone/lockfile/.travis.yml | 14 + vendor/github.com/nightlyone/lockfile/LICENSE | 19 + .../github.com/nightlyone/lockfile/README.md | 52 + .../nightlyone/lockfile/appveyor.yml | 12 + .../nightlyone/lockfile/lockfile.go | 211 + .../nightlyone/lockfile/lockfile_test.go | 308 ++ .../nightlyone/lockfile/lockfile_unix.go | 20 + .../nightlyone/lockfile/lockfile_windows.go | 30 + .../github.com/pelletier/go-toml/.gitignore | 2 + .../github.com/pelletier/go-toml/.travis.yml | 22 + vendor/github.com/pelletier/go-toml/LICENSE | 21 + vendor/github.com/pelletier/go-toml/README.md | 131 + .../pelletier/go-toml/benchmark.json | 164 + .../github.com/pelletier/go-toml/benchmark.sh | 32 + .../pelletier/go-toml/benchmark.toml | 244 + .../pelletier/go-toml/benchmark.yml | 121 + .../pelletier/go-toml/benchmark_test.go | 192 + .../pelletier/go-toml/cmd/test_program.go | 91 + .../pelletier/go-toml/cmd/tomljson/main.go | 72 + .../go-toml/cmd/tomljson/main_test.go | 82 + .../pelletier/go-toml/cmd/tomll/main.go | 66 + vendor/github.com/pelletier/go-toml/doc.go | 23 + .../github.com/pelletier/go-toml/doc_test.go | 105 + .../pelletier/go-toml/example-crlf.toml | 29 + .../github.com/pelletier/go-toml/example.toml | 29 + vendor/github.com/pelletier/go-toml/fuzz.go | 31 + vendor/github.com/pelletier/go-toml/fuzz.sh | 15 + .../pelletier/go-toml/keysparsing.go | 85 + .../pelletier/go-toml/keysparsing_test.go | 63 + vendor/github.com/pelletier/go-toml/lexer.go | 750 +++ .../pelletier/go-toml/lexer_test.go | 750 +++ .../github.com/pelletier/go-toml/marshal.go | 600 +++ .../pelletier/go-toml/marshal_test.go | 806 ++++ .../pelletier/go-toml/marshal_test.toml | 38 + vendor/github.com/pelletier/go-toml/parser.go | 430 ++ .../pelletier/go-toml/parser_test.go | 899 ++++ .../github.com/pelletier/go-toml/position.go | 29 + .../pelletier/go-toml/position_test.go | 29 + .../github.com/pelletier/go-toml/query/doc.go | 175 + .../pelletier/go-toml/query/lexer.go | 357 ++ .../pelletier/go-toml/query/lexer_test.go | 179 + .../pelletier/go-toml/query/match.go | 232 + .../pelletier/go-toml/query/match_test.go | 202 + .../pelletier/go-toml/query/parser.go | 275 ++ .../pelletier/go-toml/query/parser_test.go | 482 ++ .../pelletier/go-toml/query/query.go | 158 + .../pelletier/go-toml/query/query_test.go | 157 + .../pelletier/go-toml/query/tokens.go | 106 + vendor/github.com/pelletier/go-toml/test.sh | 91 + vendor/github.com/pelletier/go-toml/token.go | 144 + .../pelletier/go-toml/token_test.go | 67 + vendor/github.com/pelletier/go-toml/toml.go | 309 ++ .../github.com/pelletier/go-toml/toml_test.go | 106 + .../pelletier/go-toml/tomltree_create.go | 142 + .../pelletier/go-toml/tomltree_create_test.go | 126 + .../pelletier/go-toml/tomltree_write.go | 289 ++ .../pelletier/go-toml/tomltree_write_test.go | 376 ++ vendor/github.com/pkg/errors/.gitignore | 24 + vendor/github.com/pkg/errors/.travis.yml | 11 + vendor/github.com/pkg/errors/LICENSE | 23 + vendor/github.com/pkg/errors/README.md | 52 + vendor/github.com/pkg/errors/appveyor.yml | 32 + vendor/github.com/pkg/errors/bench_test.go | 59 + vendor/github.com/pkg/errors/errors.go | 269 ++ vendor/github.com/pkg/errors/errors_test.go | 226 + vendor/github.com/pkg/errors/example_test.go | 205 + vendor/github.com/pkg/errors/format_test.go | 535 +++ vendor/github.com/pkg/errors/stack.go | 178 + vendor/github.com/pkg/errors/stack_test.go | 292 ++ vendor/github.com/sdboyer/constext/LICENSE | 21 + vendor/github.com/sdboyer/constext/README.md | 78 + .../github.com/sdboyer/constext/constext.go | 123 + .../sdboyer/constext/constext_test.go | 156 + vendor/golang.org/x/sync/AUTHORS | 3 + vendor/golang.org/x/sync/CONTRIBUTING.md | 31 + vendor/golang.org/x/sync/CONTRIBUTORS | 3 + vendor/golang.org/x/sync/LICENSE | 27 + vendor/golang.org/x/sync/PATENTS | 22 + vendor/golang.org/x/sync/README.md | 18 + vendor/golang.org/x/sync/codereview.cfg | 1 + vendor/golang.org/x/sync/errgroup/errgroup.go | 67 + .../errgroup/errgroup_example_md5all_test.go | 101 + .../x/sync/errgroup/errgroup_test.go | 176 + .../golang.org/x/sync/semaphore/semaphore.go | 131 + .../x/sync/semaphore/semaphore_bench_test.go | 131 + .../sync/semaphore/semaphore_example_test.go | 84 + .../x/sync/semaphore/semaphore_test.go | 171 + .../x/sync/singleflight/singleflight.go | 111 + .../x/sync/singleflight/singleflight_test.go | 87 + vendor/golang.org/x/sync/syncmap/map.go | 372 ++ .../x/sync/syncmap/map_bench_test.go | 216 + .../x/sync/syncmap/map_reference_test.go | 151 + vendor/golang.org/x/sync/syncmap/map_test.go | 172 + 1061 files changed, 145965 insertions(+), 5 deletions(-) create mode 100644 vendor/github.com/Masterminds/semver/.travis.yml create mode 100644 vendor/github.com/Masterminds/semver/CHANGELOG.md create mode 100644 vendor/github.com/Masterminds/semver/LICENSE.txt create mode 100644 vendor/github.com/Masterminds/semver/Makefile create mode 100644 vendor/github.com/Masterminds/semver/README.md create mode 100644 vendor/github.com/Masterminds/semver/appveyor.yml create mode 100644 vendor/github.com/Masterminds/semver/benchmark_test.go create mode 100644 vendor/github.com/Masterminds/semver/collection.go create mode 100644 vendor/github.com/Masterminds/semver/collection_test.go create mode 100644 vendor/github.com/Masterminds/semver/constraints.go create mode 100644 vendor/github.com/Masterminds/semver/constraints_test.go create mode 100644 vendor/github.com/Masterminds/semver/doc.go create mode 100644 vendor/github.com/Masterminds/semver/error.go create mode 100644 vendor/github.com/Masterminds/semver/magic.go create mode 100644 vendor/github.com/Masterminds/semver/parse.go create mode 100644 vendor/github.com/Masterminds/semver/range.go create mode 100644 vendor/github.com/Masterminds/semver/set_ops_test.go create mode 100644 vendor/github.com/Masterminds/semver/union.go create mode 100644 vendor/github.com/Masterminds/semver/version.go create mode 100644 vendor/github.com/Masterminds/semver/version_test.go create mode 100644 vendor/github.com/Masterminds/vcs/.gitignore create mode 100644 vendor/github.com/Masterminds/vcs/.travis.yml create mode 100644 vendor/github.com/Masterminds/vcs/CHANGELOG.md create mode 100644 vendor/github.com/Masterminds/vcs/LICENSE.txt create mode 100644 vendor/github.com/Masterminds/vcs/Makefile create mode 100644 vendor/github.com/Masterminds/vcs/README.md create mode 100644 vendor/github.com/Masterminds/vcs/appveyor.yml create mode 100644 vendor/github.com/Masterminds/vcs/bzr.go create mode 100644 vendor/github.com/Masterminds/vcs/bzr_test.go create mode 100644 vendor/github.com/Masterminds/vcs/errors.go create mode 100644 vendor/github.com/Masterminds/vcs/errors_test.go create mode 100644 vendor/github.com/Masterminds/vcs/git.go create mode 100644 vendor/github.com/Masterminds/vcs/git_test.go create mode 100644 vendor/github.com/Masterminds/vcs/glide.yaml create mode 100644 vendor/github.com/Masterminds/vcs/hg.go create mode 100644 vendor/github.com/Masterminds/vcs/hg_test.go create mode 100644 vendor/github.com/Masterminds/vcs/repo.go create mode 100644 vendor/github.com/Masterminds/vcs/repo_test.go create mode 100644 vendor/github.com/Masterminds/vcs/svn.go create mode 100644 vendor/github.com/Masterminds/vcs/svn_test.go create mode 100644 vendor/github.com/Masterminds/vcs/vcs_local_lookup.go create mode 100644 vendor/github.com/Masterminds/vcs/vcs_remote_lookup.go create mode 100644 vendor/github.com/Masterminds/vcs/vcs_remote_lookup_test.go create mode 100644 vendor/github.com/armon/go-radix/.gitignore create mode 100644 vendor/github.com/armon/go-radix/.travis.yml create mode 100644 vendor/github.com/armon/go-radix/LICENSE create mode 100644 vendor/github.com/armon/go-radix/README.md create mode 100644 vendor/github.com/armon/go-radix/radix.go create mode 100644 vendor/github.com/armon/go-radix/radix_test.go create mode 100644 vendor/github.com/boltdb/bolt/.gitignore create mode 100644 vendor/github.com/boltdb/bolt/LICENSE create mode 100644 vendor/github.com/boltdb/bolt/Makefile create mode 100644 vendor/github.com/boltdb/bolt/README.md create mode 100644 vendor/github.com/boltdb/bolt/appveyor.yml create mode 100644 vendor/github.com/boltdb/bolt/bolt_386.go create mode 100644 vendor/github.com/boltdb/bolt/bolt_amd64.go create mode 100644 vendor/github.com/boltdb/bolt/bolt_arm.go create mode 100644 vendor/github.com/boltdb/bolt/bolt_arm64.go create mode 100644 vendor/github.com/boltdb/bolt/bolt_linux.go create mode 100644 vendor/github.com/boltdb/bolt/bolt_openbsd.go create mode 100644 vendor/github.com/boltdb/bolt/bolt_ppc.go create mode 100644 vendor/github.com/boltdb/bolt/bolt_ppc64.go create mode 100644 vendor/github.com/boltdb/bolt/bolt_ppc64le.go create mode 100644 vendor/github.com/boltdb/bolt/bolt_s390x.go create mode 100644 vendor/github.com/boltdb/bolt/bolt_unix.go create mode 100644 vendor/github.com/boltdb/bolt/bolt_unix_solaris.go create mode 100644 vendor/github.com/boltdb/bolt/bolt_windows.go create mode 100644 vendor/github.com/boltdb/bolt/boltsync_unix.go create mode 100644 vendor/github.com/boltdb/bolt/bucket.go create mode 100644 vendor/github.com/boltdb/bolt/bucket_test.go create mode 100644 vendor/github.com/boltdb/bolt/cmd/bolt/main.go create mode 100644 vendor/github.com/boltdb/bolt/cmd/bolt/main_test.go create mode 100644 vendor/github.com/boltdb/bolt/cursor.go create mode 100644 vendor/github.com/boltdb/bolt/cursor_test.go create mode 100644 vendor/github.com/boltdb/bolt/db.go create mode 100644 vendor/github.com/boltdb/bolt/db_test.go create mode 100644 vendor/github.com/boltdb/bolt/doc.go create mode 100644 vendor/github.com/boltdb/bolt/errors.go create mode 100644 vendor/github.com/boltdb/bolt/freelist.go create mode 100644 vendor/github.com/boltdb/bolt/freelist_test.go create mode 100644 vendor/github.com/boltdb/bolt/node.go create mode 100644 vendor/github.com/boltdb/bolt/node_test.go create mode 100644 vendor/github.com/boltdb/bolt/page.go create mode 100644 vendor/github.com/boltdb/bolt/page_test.go create mode 100644 vendor/github.com/boltdb/bolt/quick_test.go create mode 100644 vendor/github.com/boltdb/bolt/simulation_test.go create mode 100644 vendor/github.com/boltdb/bolt/tx.go create mode 100644 vendor/github.com/boltdb/bolt/tx_test.go create mode 100644 vendor/github.com/go-yaml/yaml/.travis.yml create mode 100644 vendor/github.com/go-yaml/yaml/LICENSE create mode 100644 vendor/github.com/go-yaml/yaml/LICENSE.libyaml create mode 100644 vendor/github.com/go-yaml/yaml/README.md create mode 100644 vendor/github.com/go-yaml/yaml/apic.go create mode 100644 vendor/github.com/go-yaml/yaml/decode.go create mode 100644 vendor/github.com/go-yaml/yaml/decode_test.go create mode 100644 vendor/github.com/go-yaml/yaml/emitterc.go create mode 100644 vendor/github.com/go-yaml/yaml/encode.go create mode 100644 vendor/github.com/go-yaml/yaml/encode_test.go create mode 100644 vendor/github.com/go-yaml/yaml/example_embedded_test.go create mode 100644 vendor/github.com/go-yaml/yaml/parserc.go create mode 100644 vendor/github.com/go-yaml/yaml/readerc.go create mode 100644 vendor/github.com/go-yaml/yaml/resolve.go create mode 100644 vendor/github.com/go-yaml/yaml/scannerc.go create mode 100644 vendor/github.com/go-yaml/yaml/sorter.go create mode 100644 vendor/github.com/go-yaml/yaml/suite_test.go create mode 100644 vendor/github.com/go-yaml/yaml/writerc.go create mode 100644 vendor/github.com/go-yaml/yaml/yaml.go create mode 100644 vendor/github.com/go-yaml/yaml/yamlh.go create mode 100644 vendor/github.com/go-yaml/yaml/yamlprivateh.go create mode 100644 vendor/github.com/golang/dep/.codeclimate.yml create mode 100644 vendor/github.com/golang/dep/.gitattributes create mode 100644 vendor/github.com/golang/dep/.github/CODEOWNERS create mode 100644 vendor/github.com/golang/dep/.github/ISSUE_TEMPLATE.md create mode 100644 vendor/github.com/golang/dep/.github/PULL_REQUEST_TEMPLATE.md create mode 100644 vendor/github.com/golang/dep/.gitignore create mode 100644 vendor/github.com/golang/dep/.travis.yml create mode 100644 vendor/github.com/golang/dep/AUTHORS create mode 100644 vendor/github.com/golang/dep/CHANGELOG.md create mode 100644 vendor/github.com/golang/dep/CODE_OF_CONDUCT.md create mode 100644 vendor/github.com/golang/dep/CONTRIBUTING.md create mode 100644 vendor/github.com/golang/dep/CONTRIBUTORS create mode 100644 vendor/github.com/golang/dep/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/LICENSE create mode 100644 vendor/github.com/golang/dep/MAINTAINERS.md create mode 100644 vendor/github.com/golang/dep/PATENTS create mode 100644 vendor/github.com/golang/dep/README.md create mode 100644 vendor/github.com/golang/dep/analyzer.go create mode 100644 vendor/github.com/golang/dep/analyzer_notwindows_test.go create mode 100644 vendor/github.com/golang/dep/analyzer_test.go create mode 100644 vendor/github.com/golang/dep/analyzer_windows_test.go create mode 100644 vendor/github.com/golang/dep/appveyor.yml create mode 100644 vendor/github.com/golang/dep/cmd/dep/dep_test.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/doc.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/ensure.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/ensure_test.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/failures.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/gopath_scanner.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/gopath_scanner_test.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/graphviz.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/graphviz_test.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/hash_in.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/init.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/integration_test.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/main.go create mode 100755 vendor/github.com/golang/dep/cmd/dep/mkdoc.sh create mode 100644 vendor/github.com/golang/dep/cmd/dep/prune.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/root_analyzer.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/status.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/status_test.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/cachedir/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/cachedir/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/cachedir/main.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/graphviz/case1.dot create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/graphviz/case2.dot create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/graphviz/empty.dot create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/README.md create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/all-new-double-spec/final/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/all-new-double-spec/final/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/all-new-double-spec/initial/main.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/all-new-double-spec/testcase.json create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/all-new-double/final/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/all-new-double/final/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/all-new-double/initial/main.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/all-new-double/testcase.json create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/all-new-spec/final/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/all-new-spec/final/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/all-new-spec/initial/main.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/all-new-spec/testcase.json create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/all-new/final/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/all-new/final/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/all-new/initial/main.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/all-new/testcase.json create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/desync/final/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/desync/final/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/desync/final/main.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/desync/initial/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/desync/initial/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/desync/initial/main.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/desync/stdout.txt create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/desync/testcase.json create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/double-diff-spec/final/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/double-diff-spec/final/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/double-diff-spec/initial/main.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/double-diff-spec/testcase.json create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/exists-manifest/final/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/exists-manifest/final/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/exists-manifest/initial/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/exists-manifest/initial/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/exists-manifest/initial/main.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/exists-manifest/testcase.json create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/exists/final/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/exists/final/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/exists/initial/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/exists/initial/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/exists/initial/main.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/exists/testcase.json create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/noarg/final/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/noarg/final/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/noarg/final/main.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/noarg/initial/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/noarg/initial/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/noarg/initial/main.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/noarg/testcase.json create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/self-add/case1/final/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/self-add/case1/final/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/self-add/case1/initial/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/self-add/case1/initial/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/self-add/case1/initial/main.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/self-add/case1/testcase.json create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/self-add/case2/final/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/self-add/case2/final/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/self-add/case2/initial/main.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/self-add/case2/testcase.json create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/exists-imports/final/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/exists-imports/final/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/exists-imports/initial/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/exists-imports/initial/main.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/exists-imports/testcase.json create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/exists-manifest-constraint/final/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/exists-manifest-constraint/final/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/exists-manifest-constraint/initial/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/exists-manifest-constraint/initial/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/exists-manifest-constraint/initial/main.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/exists-manifest-constraint/testcase.json create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/errs/lockless-vendoronly/final/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/errs/lockless-vendoronly/final/main.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/errs/lockless-vendoronly/initial/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/errs/lockless-vendoronly/initial/main.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/errs/lockless-vendoronly/testcase.json create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/errs/specargs/final/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/errs/specargs/final/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/errs/specargs/initial/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/errs/specargs/initial/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/errs/specargs/initial/main.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/errs/specargs/testcase.json create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-dry/final/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-dry/final/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-dry/initial/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-dry/initial/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-dry/initial/main.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-dry/testcase.json create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-novendor-dry/final/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-novendor-dry/final/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-novendor-dry/initial/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-novendor-dry/initial/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-novendor-dry/initial/main.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-novendor-dry/testcase.json create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-novendor/final/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-novendor/final/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-novendor/initial/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-novendor/initial/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-novendor/initial/main.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-novendor/testcase.json create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq/final/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq/final/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq/initial/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq/initial/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq/initial/main.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq/testcase.json create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hashneq-novendor-dry/final/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hashneq-novendor-dry/final/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hashneq-novendor-dry/initial/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hashneq-novendor-dry/initial/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hashneq-novendor-dry/initial/main.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hashneq-novendor-dry/testcase.json create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hashneq-vendoronly/final/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hashneq-vendoronly/final/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hashneq-vendoronly/initial/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hashneq-vendoronly/initial/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hashneq-vendoronly/initial/main.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hashneq-vendoronly/testcase.json create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/nocode-vendoronly/final/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/nocode-vendoronly/final/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/nocode-vendoronly/initial/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/nocode-vendoronly/initial/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/nocode-vendoronly/testcase.json create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/empty/case1/final/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/empty/case1/final/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/empty/case1/initial/main.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/empty/case1/testcase.json create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/empty/case2/final/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/empty/case2/final/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/empty/case2/initial/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/empty/case2/initial/main.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/empty/case2/testcase.json create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/empty/case3/README.md create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/empty/case3/final/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/empty/case3/final/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/empty/case3/initial/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/empty/case3/initial/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/empty/case3/initial/main.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/empty/case3/initial/samples/samples.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/empty/case3/testcase.json create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-errors/case1/final/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-errors/case1/final/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-errors/case1/testcase.json create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-errors/case2/final/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-errors/case2/initial/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-errors/case2/initial/bar/bar.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-errors/case2/initial/baz/.gitignore create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-errors/case2/testcase.json create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-ignore/final/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-ignore/final/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-ignore/initial/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-ignore/initial/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-ignore/initial/main.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-ignore/initial/samples/samples.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-ignore/initial/samples/subsamples/subsamples.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-ignore/stdout.txt create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-ignore/testcase.json create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-other-root/final/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-other-root/final/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-other-root/initial/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-other-root/initial/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-other-root/initial/main.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-other-root/initial/samples/samples.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-other-root/initial/samples/subsamples/subsamples.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-other-root/stdout.txt create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-other-root/testcase.json create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/case1/final/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/case1/final/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/case1/initial/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/case1/initial/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/case1/initial/main.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/case1/testcase.json create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/desync/final/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/desync/final/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/desync/final/main.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/desync/initial/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/desync/initial/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/desync/initial/main.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/desync/stdout.txt create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/desync/testcase.json create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/lockless/final/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/lockless/final/main.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/lockless/initial/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/lockless/initial/main.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/lockless/testcase.json create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/nonroot-arg/final/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/nonroot-arg/final/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/nonroot-arg/initial/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/nonroot-arg/initial/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/nonroot-arg/initial/main.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/nonroot-arg/testcase.json create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/not-in-lock/final/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/not-in-lock/final/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/not-in-lock/initial/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/not-in-lock/initial/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/not-in-lock/initial/main.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/not-in-lock/testcase.json create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/spec-with-constraint/final/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/spec-with-constraint/final/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/spec-with-constraint/initial/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/spec-with-constraint/initial/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/spec-with-constraint/initial/main.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/spec-with-constraint/testcase.json create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/spec-with-source/final/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/spec-with-source/final/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/spec-with-source/initial/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/spec-with-source/initial/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/spec-with-source/initial/main.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/spec-with-source/testcase.json create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/novendor/final/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/novendor/final/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/novendor/initial/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/novendor/initial/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/novendor/initial/main.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/novendor/testcase.json create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case1/final/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case1/final/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case1/initial/foo/bar.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case1/initial/main.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case1/testcase.json create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case2/final/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case2/final/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case2/initial/foo/bar.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case2/initial/main.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case2/testcase.json create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case3/final/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case3/final/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case3/initial/foo/bar.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case3/initial/main.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case3/testcase.json create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case4/final/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case4/final/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case4/initial/foo/bar.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case4/initial/main.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case4/testcase.json create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case1/README.md create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case1/final/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case1/final/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case1/initial/glide.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case1/initial/glide.yaml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case1/initial/main.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case1/initial/samples/samples.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case1/testcase.json create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case2/README.md create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case2/final/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case2/final/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case2/initial/glide.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case2/initial/glide.yaml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case2/initial/main.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case2/testcase.json create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case3/README.md create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case3/final/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case3/final/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case3/initial/main.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case3/testcase.json.ignore create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case4/README.md create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case4/final/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case4/final/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case4/initial/glide.yaml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case4/initial/main.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case4/testcase.json create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glock/case1/final/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glock/case1/final/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glock/case1/initial/GLOCKFILE create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glock/case1/initial/main.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glock/case1/testcase.json create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/godep/case1/final/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/godep/case1/final/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/godep/case1/initial/Godeps/Godeps.json create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/godep/case1/initial/main.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/godep/case1/testcase.json create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/govend/case1/final/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/govend/case1/final/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/govend/case1/initial/main.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/govend/case1/initial/vendor.yml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/govend/case1/testcase.json create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/govendor/case1/README.md create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/govendor/case1/final/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/govendor/case1/final/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/govendor/case1/initial/main.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/govendor/case1/initial/samples/samples.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/govendor/case1/testcase.json create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/gvt/case1/final/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/gvt/case1/final/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/gvt/case1/initial/main.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/gvt/case1/testcase.json create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/manifest-exists/final/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/manifest-exists/initial/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/manifest-exists/testcase.json create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/relative_path/final/project_dir/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/relative_path/final/project_dir/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/relative_path/initial/project_dir/foo/bar.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/relative_path/initial/project_dir/main.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/relative_path/testcase.json create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/skip-hidden/final/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/skip-hidden/final/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/skip-hidden/initial/.foo/main.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/skip-hidden/initial/_foo/main.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/skip-hidden/initial/lib.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/skip-hidden/initial/testdata/main.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/skip-hidden/testcase.json create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/usage/with_h_flag/testcase.json create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/usage/with_not_defined_flag/testcase.json create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/vndr/case1/final/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/vndr/case1/final/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/vndr/case1/initial/main.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/vndr/case1/initial/vendor.conf create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/vndr/case1/testcase.json create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/dot/final/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/dot/final/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/dot/initial/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/dot/initial/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/dot/initial/main.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/dot/stdout.txt create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/dot/testcase.json create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/json/final/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/json/final/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/json/initial/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/json/initial/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/json/initial/main.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/json/stdout.txt create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/json/testcase.json create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/table/final/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/table/final/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/table/initial/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/table/initial/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/table/initial/main.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/table/stdout.txt create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/table/testcase.json create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/template/final/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/template/final/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/template/initial/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/template/initial/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/template/initial/main.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/template/stdout.txt create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/template/testcase.json create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/ignore_lock_mismatch/final/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/ignore_lock_mismatch/final/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/ignore_lock_mismatch/initial/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/ignore_lock_mismatch/initial/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/ignore_lock_mismatch/initial/main.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/ignore_lock_mismatch/testcase.json create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/missing_pkgs_lock_mismatch/final/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/missing_pkgs_lock_mismatch/final/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/missing_pkgs_lock_mismatch/initial/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/missing_pkgs_lock_mismatch/initial/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/missing_pkgs_lock_mismatch/initial/main.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/missing_pkgs_lock_mismatch/testcase.json create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/override_constraint/final/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/override_constraint/final/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/override_constraint/initial/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/override_constraint/initial/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/override_constraint/initial/main.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/override_constraint/stdout.txt create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/override_constraint/testcase.json create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/revision_constraint/final/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/revision_constraint/final/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/revision_constraint/initial/Gopkg.lock create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/revision_constraint/initial/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/revision_constraint/initial/main.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/revision_constraint/stdout.txt create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/revision_constraint/testcase.json create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/without_lock/final/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/without_lock/initial/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/without_lock/testcase.json create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/init/directdeps/main.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/testdata/status/collect_constraints/main.go create mode 100644 vendor/github.com/golang/dep/cmd/dep/version.go create mode 100644 vendor/github.com/golang/dep/context.go create mode 100644 vendor/github.com/golang/dep/context_test.go create mode 100644 vendor/github.com/golang/dep/doc.go create mode 100644 vendor/github.com/golang/dep/docs/FAQ.md create mode 100644 vendor/github.com/golang/dep/docs/Gopkg.lock.md create mode 100644 vendor/github.com/golang/dep/docs/Gopkg.toml.md create mode 100644 vendor/github.com/golang/dep/docs/assets/DigbyFlat.png create mode 100644 vendor/github.com/golang/dep/docs/assets/DigbyFlat.svg create mode 100644 vendor/github.com/golang/dep/docs/assets/DigbyFlatScene2.png create mode 100644 vendor/github.com/golang/dep/docs/assets/DigbyFlatScene2.svg create mode 100644 vendor/github.com/golang/dep/docs/assets/DigbyScene2Flat.png create mode 100644 vendor/github.com/golang/dep/docs/assets/DigbyScene2Flat.svg create mode 100644 vendor/github.com/golang/dep/docs/assets/DigbyScene2Shadows.png create mode 100644 vendor/github.com/golang/dep/docs/assets/DigbyScene2Shadows.svg create mode 100644 vendor/github.com/golang/dep/docs/assets/DigbyShadows.png create mode 100644 vendor/github.com/golang/dep/docs/assets/DigbyShadows.svg create mode 100644 vendor/github.com/golang/dep/docs/assets/DigbyShadowsScene2.png create mode 100644 vendor/github.com/golang/dep/docs/assets/DigbyShadowsScene2.svg create mode 100644 vendor/github.com/golang/dep/docs/assets/StatusGraph.png create mode 100644 vendor/github.com/golang/dep/docs/assets/annotated-func-arrows.png create mode 100644 vendor/github.com/golang/dep/docs/assets/base-arrows.png create mode 100644 vendor/github.com/golang/dep/docs/assets/four-states.png create mode 100644 vendor/github.com/golang/dep/docs/assets/func-toggles.png create mode 100644 vendor/github.com/golang/dep/docs/assets/in-sync.png create mode 100644 vendor/github.com/golang/dep/docs/assets/lock-back.png create mode 100644 vendor/github.com/golang/dep/docs/assets/required-arrows.png create mode 100644 vendor/github.com/golang/dep/docs/daily-dep.md create mode 100644 vendor/github.com/golang/dep/docs/deduction.md create mode 100644 vendor/github.com/golang/dep/docs/ensure-mechanics.md create mode 100644 vendor/github.com/golang/dep/docs/failure-modes.md create mode 100644 vendor/github.com/golang/dep/docs/glossary.md create mode 100644 vendor/github.com/golang/dep/docs/installation.md create mode 100644 vendor/github.com/golang/dep/docs/introduction.md create mode 100644 vendor/github.com/golang/dep/docs/migrating.md create mode 100644 vendor/github.com/golang/dep/docs/new-project.md create mode 100644 vendor/github.com/golang/dep/docs/the-solver.md create mode 100644 vendor/github.com/golang/dep/gps/_testdata/badrepo/README.md create mode 100644 vendor/github.com/golang/dep/gps/_testdata/badrepo/corrupt_dot_git_directory.tar create mode 100644 vendor/github.com/golang/dep/gps/_testdata/cmd/echosleep/echosleep.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/cmd/stdout_stderr/stdout_stderr.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/digest/github.com/alice/match/match.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/digest/github.com/alice/mismatch/mismatch.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/digest/github.com/alice/notInLock/notInLock.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/digest/github.com/bob/emptyDigest/emptyDigest.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/digest/github.com/bob/match/match.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/digest/launchpad.net/match/match.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/bad/bad.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/buildtag/invalid.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/canon_confl/a.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/canon_confl/b.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/canonical/main.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/canonical/sub/sub.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/cycle/a.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/cycle/one/a.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/cycle/two/a.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/disallow/a.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/disallow/testdata/another.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/dotgodir/.go/.gitkeep create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/dotgodir/.go/dot.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/dotgodir/.m1p/a.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/dotgodir/.m1p/b.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/dotgodir/foo.go/.gitkeep create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/dotgodir/foo.go/foo.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/doublenest/a.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/doublenest/namemismatch/m1p/a.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/doublenest/namemismatch/m1p/b.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/doublenest/namemismatch/nm.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/empty/.gitkeep create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/github.com/example/varied/locals.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/github.com/example/varied/m1p/a.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/github.com/example/varied/m1p/b.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/github.com/example/varied/main.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/github.com/example/varied/namemismatch/nm.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/github.com/example/varied/otherpath/otherpath_test.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/github.com/example/varied/simple/another/another.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/github.com/example/varied/simple/another/another_test.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/github.com/example/varied/simple/another/locals.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/github.com/example/varied/simple/locals.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/github.com/example/varied/simple/simple.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/igmain/a.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/igmain/igmain.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/igmainfirst/igmain.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/igmainfirst/z.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/igmainlong/a.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/igmainlong/igmain.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/igmaint/a.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/igmaint/igmain.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/igmaint/t_test.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/m1p/a.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/m1p/b.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/missing/a.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/missing/m1p/a.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/missing/m1p/b.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/nest/a.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/nest/m1p/a.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/nest/m1p/b.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/relimport/a.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/relimport/dot/a.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/relimport/dotdot/a.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/relimport/dotdotslash/a.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/relimport/dotslash/a.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/ren/m1p/a.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/ren/m1p/b.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/ren/simple/a.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/simple/a.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/simpleallt/a.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/simpleallt/a_test.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/simpleallt/t_test.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/simplet/a.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/simplet/t_test.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/simplext/a.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/simplext/a_test.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/skip_/_a.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/skip_/a.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/t/t_test.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/twopkgs/a.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/twopkgs/b.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/varied/locals.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/varied/m1p/a.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/varied/m1p/b.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/varied/main.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/varied/namemismatch/nm.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/varied/otherpath/otherpath_test.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/varied/simple/another/another.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/varied/simple/another/another_test.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/varied/simple/another/locals.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/varied/simple/locals.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/varied/simple/simple.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/varied_hidden/.onlyfromtests/a.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/varied_hidden/.onlyfromtests/b.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/varied_hidden/_frommain/a.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/varied_hidden/_never/a.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/varied_hidden/_secondorder/secondorder.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/varied_hidden/always/always_test.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/varied_hidden/dotdotslash/a.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/varied_hidden/locals.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/varied_hidden/main.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/varied_hidden/simple/locals.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/varied_hidden/simple/simple.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/varied_hidden/simple/testdata/another.go create mode 100644 vendor/github.com/golang/dep/gps/_testdata/src/xt/a_test.go create mode 100644 vendor/github.com/golang/dep/gps/bridge.go create mode 100644 vendor/github.com/golang/dep/gps/cmd.go create mode 100644 vendor/github.com/golang/dep/gps/cmd_unix.go create mode 100644 vendor/github.com/golang/dep/gps/cmd_windows.go create mode 100644 vendor/github.com/golang/dep/gps/constraint_test.go create mode 100644 vendor/github.com/golang/dep/gps/constraints.go create mode 100644 vendor/github.com/golang/dep/gps/deduce.go create mode 100644 vendor/github.com/golang/dep/gps/deduce_test.go create mode 100644 vendor/github.com/golang/dep/gps/discovery.go create mode 100644 vendor/github.com/golang/dep/gps/example.go create mode 100644 vendor/github.com/golang/dep/gps/filesystem.go create mode 100644 vendor/github.com/golang/dep/gps/filesystem_test.go create mode 100644 vendor/github.com/golang/dep/gps/hash.go create mode 100644 vendor/github.com/golang/dep/gps/hash_test.go create mode 100644 vendor/github.com/golang/dep/gps/identifier.go create mode 100644 vendor/github.com/golang/dep/gps/internal/pb/pb.go create mode 100644 vendor/github.com/golang/dep/gps/internal/pb/source_cache.pb.go create mode 100644 vendor/github.com/golang/dep/gps/internal/pb/source_cache.proto create mode 100644 vendor/github.com/golang/dep/gps/lock.go create mode 100644 vendor/github.com/golang/dep/gps/lock_test.go create mode 100644 vendor/github.com/golang/dep/gps/lockdiff.go create mode 100644 vendor/github.com/golang/dep/gps/lockdiff_test.go create mode 100644 vendor/github.com/golang/dep/gps/manager_test.go create mode 100644 vendor/github.com/golang/dep/gps/manifest.go create mode 100644 vendor/github.com/golang/dep/gps/manifest_test.go create mode 100644 vendor/github.com/golang/dep/gps/maybe_source.go create mode 100644 vendor/github.com/golang/dep/gps/metrics.go create mode 100644 vendor/github.com/golang/dep/gps/paths/paths.go create mode 100644 vendor/github.com/golang/dep/gps/paths/paths_test.go create mode 100644 vendor/github.com/golang/dep/gps/pkgtree/digest.go create mode 100644 vendor/github.com/golang/dep/gps/pkgtree/digest_test.go create mode 100644 vendor/github.com/golang/dep/gps/pkgtree/dirwalk.go create mode 100644 vendor/github.com/golang/dep/gps/pkgtree/ignored_ruleset.go create mode 100644 vendor/github.com/golang/dep/gps/pkgtree/ignored_ruleset_test.go create mode 100644 vendor/github.com/golang/dep/gps/pkgtree/pkgtree.go create mode 100644 vendor/github.com/golang/dep/gps/pkgtree/pkgtree_test.go create mode 100644 vendor/github.com/golang/dep/gps/pkgtree/reachmap.go create mode 100644 vendor/github.com/golang/dep/gps/prune.go create mode 100644 vendor/github.com/golang/dep/gps/prune_test.go create mode 100644 vendor/github.com/golang/dep/gps/rootdata.go create mode 100644 vendor/github.com/golang/dep/gps/rootdata_test.go create mode 100644 vendor/github.com/golang/dep/gps/satisfy.go create mode 100644 vendor/github.com/golang/dep/gps/selection.go create mode 100644 vendor/github.com/golang/dep/gps/selection_test.go create mode 100644 vendor/github.com/golang/dep/gps/solution.go create mode 100644 vendor/github.com/golang/dep/gps/solution_test.go create mode 100644 vendor/github.com/golang/dep/gps/solve_basic_test.go create mode 100644 vendor/github.com/golang/dep/gps/solve_bimodal_test.go create mode 100644 vendor/github.com/golang/dep/gps/solve_failures.go create mode 100644 vendor/github.com/golang/dep/gps/solve_test.go create mode 100644 vendor/github.com/golang/dep/gps/solver.go create mode 100644 vendor/github.com/golang/dep/gps/solver_inputs_test.go create mode 100644 vendor/github.com/golang/dep/gps/source.go create mode 100644 vendor/github.com/golang/dep/gps/source_cache.go create mode 100644 vendor/github.com/golang/dep/gps/source_cache_bolt.go create mode 100644 vendor/github.com/golang/dep/gps/source_cache_bolt_encode.go create mode 100644 vendor/github.com/golang/dep/gps/source_cache_bolt_encode_test.go create mode 100644 vendor/github.com/golang/dep/gps/source_cache_bolt_test.go create mode 100644 vendor/github.com/golang/dep/gps/source_cache_multi.go create mode 100644 vendor/github.com/golang/dep/gps/source_cache_test.go create mode 100644 vendor/github.com/golang/dep/gps/source_errors.go create mode 100644 vendor/github.com/golang/dep/gps/source_errors_test.go create mode 100644 vendor/github.com/golang/dep/gps/source_manager.go create mode 100644 vendor/github.com/golang/dep/gps/source_manager_test.go create mode 100644 vendor/github.com/golang/dep/gps/source_test.go create mode 100644 vendor/github.com/golang/dep/gps/strings.go create mode 100644 vendor/github.com/golang/dep/gps/trace.go create mode 100644 vendor/github.com/golang/dep/gps/typed_radix.go create mode 100644 vendor/github.com/golang/dep/gps/typed_radix_test.go create mode 100644 vendor/github.com/golang/dep/gps/vcs_repo.go create mode 100644 vendor/github.com/golang/dep/gps/vcs_repo_test.go create mode 100644 vendor/github.com/golang/dep/gps/vcs_source.go create mode 100644 vendor/github.com/golang/dep/gps/vcs_source_test.go create mode 100644 vendor/github.com/golang/dep/gps/vcs_version.go create mode 100644 vendor/github.com/golang/dep/gps/vcs_version_test.go create mode 100644 vendor/github.com/golang/dep/gps/version.go create mode 100644 vendor/github.com/golang/dep/gps/version_queue.go create mode 100644 vendor/github.com/golang/dep/gps/version_queue_test.go create mode 100644 vendor/github.com/golang/dep/gps/version_test.go create mode 100644 vendor/github.com/golang/dep/gps/version_unifier.go create mode 100644 vendor/github.com/golang/dep/gps/version_unifier_test.go create mode 100755 vendor/github.com/golang/dep/hack/build-all.bash create mode 100755 vendor/github.com/golang/dep/hack/coverage.bash create mode 100644 vendor/github.com/golang/dep/hack/licenseok/main.go create mode 100755 vendor/github.com/golang/dep/hack/lint.bash create mode 100755 vendor/github.com/golang/dep/hack/validate-gofmt.bash create mode 100755 vendor/github.com/golang/dep/hack/validate-licence.bash create mode 100755 vendor/github.com/golang/dep/hack/validate-vendor.bash create mode 100644 vendor/github.com/golang/dep/internal/feedback/feedback.go create mode 100644 vendor/github.com/golang/dep/internal/feedback/feedback_test.go create mode 100644 vendor/github.com/golang/dep/internal/fs/fs.go create mode 100644 vendor/github.com/golang/dep/internal/fs/fs_test.go create mode 100644 vendor/github.com/golang/dep/internal/fs/rename.go create mode 100644 vendor/github.com/golang/dep/internal/fs/rename_windows.go create mode 120000 vendor/github.com/golang/dep/internal/fs/testdata/symlinks/dir-symlink create mode 120000 vendor/github.com/golang/dep/internal/fs/testdata/symlinks/file-symlink create mode 120000 vendor/github.com/golang/dep/internal/fs/testdata/symlinks/invalid-symlink create mode 120000 vendor/github.com/golang/dep/internal/fs/testdata/symlinks/windows-file-symlink create mode 100644 vendor/github.com/golang/dep/internal/fs/testdata/test.file create mode 100644 vendor/github.com/golang/dep/internal/importers/base/importer.go create mode 100644 vendor/github.com/golang/dep/internal/importers/base/importer_test.go create mode 100644 vendor/github.com/golang/dep/internal/importers/glide/importer.go create mode 100644 vendor/github.com/golang/dep/internal/importers/glide/importer_test.go create mode 100644 vendor/github.com/golang/dep/internal/importers/glide/testdata/glide.lock create mode 100644 vendor/github.com/golang/dep/internal/importers/glide/testdata/glide.yaml create mode 100644 vendor/github.com/golang/dep/internal/importers/glide/testdata/golden.txt create mode 100644 vendor/github.com/golang/dep/internal/importers/glock/importer.go create mode 100644 vendor/github.com/golang/dep/internal/importers/glock/importer_test.go create mode 100644 vendor/github.com/golang/dep/internal/importers/glock/testdata/GLOCKFILE create mode 100644 vendor/github.com/golang/dep/internal/importers/glock/testdata/golden.txt create mode 100644 vendor/github.com/golang/dep/internal/importers/godep/importer.go create mode 100644 vendor/github.com/golang/dep/internal/importers/godep/importer_test.go create mode 100644 vendor/github.com/golang/dep/internal/importers/godep/testdata/Godeps.json create mode 100644 vendor/github.com/golang/dep/internal/importers/godep/testdata/golden.txt create mode 100644 vendor/github.com/golang/dep/internal/importers/govend/importer.go create mode 100644 vendor/github.com/golang/dep/internal/importers/govend/importer_test.go create mode 100644 vendor/github.com/golang/dep/internal/importers/govend/testdata/golden.txt create mode 100644 vendor/github.com/golang/dep/internal/importers/govend/testdata/vendor.yml create mode 100644 vendor/github.com/golang/dep/internal/importers/govendor/importer.go create mode 100644 vendor/github.com/golang/dep/internal/importers/govendor/importer_test.go create mode 100644 vendor/github.com/golang/dep/internal/importers/govendor/testdata/golden.txt create mode 100644 vendor/github.com/golang/dep/internal/importers/govendor/testdata/vendor.json create mode 100644 vendor/github.com/golang/dep/internal/importers/gvt/importer.go create mode 100644 vendor/github.com/golang/dep/internal/importers/gvt/importer_test.go create mode 100644 vendor/github.com/golang/dep/internal/importers/gvt/testdata/golden.txt create mode 100644 vendor/github.com/golang/dep/internal/importers/gvt/testdata/manifest create mode 100644 vendor/github.com/golang/dep/internal/importers/importers.go create mode 100644 vendor/github.com/golang/dep/internal/importers/importertest/testcase.go create mode 100644 vendor/github.com/golang/dep/internal/importers/importertest/testdata.go create mode 100644 vendor/github.com/golang/dep/internal/importers/vndr/importer.go create mode 100644 vendor/github.com/golang/dep/internal/importers/vndr/importer_test.go create mode 100644 vendor/github.com/golang/dep/internal/importers/vndr/testdata/golden.txt create mode 100644 vendor/github.com/golang/dep/internal/importers/vndr/testdata/vendor.conf create mode 100644 vendor/github.com/golang/dep/internal/test/integration/testcase.go create mode 100644 vendor/github.com/golang/dep/internal/test/integration/testproj.go create mode 100644 vendor/github.com/golang/dep/internal/test/test.go create mode 100644 vendor/github.com/golang/dep/internal/test/writer.go create mode 100644 vendor/github.com/golang/dep/lock.go create mode 100644 vendor/github.com/golang/dep/lock_test.go create mode 100644 vendor/github.com/golang/dep/manifest.go create mode 100644 vendor/github.com/golang/dep/manifest_test.go create mode 100644 vendor/github.com/golang/dep/project.go create mode 100644 vendor/github.com/golang/dep/project_test.go create mode 100644 vendor/github.com/golang/dep/test_project_context_test.go create mode 100644 vendor/github.com/golang/dep/testdata/analyzer/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/testdata/lock/error0.toml create mode 100644 vendor/github.com/golang/dep/testdata/lock/error1.toml create mode 100644 vendor/github.com/golang/dep/testdata/lock/error2.toml create mode 100644 vendor/github.com/golang/dep/testdata/lock/golden0.toml create mode 100644 vendor/github.com/golang/dep/testdata/lock/golden1.toml create mode 100644 vendor/github.com/golang/dep/testdata/manifest/error1.toml create mode 100644 vendor/github.com/golang/dep/testdata/manifest/error2.toml create mode 100644 vendor/github.com/golang/dep/testdata/manifest/error3.toml create mode 100644 vendor/github.com/golang/dep/testdata/manifest/golden.toml create mode 100644 vendor/github.com/golang/dep/testdata/rootfind/Gopkg.toml create mode 100644 vendor/github.com/golang/dep/testdata/rootfind/subdir/.gitkeep create mode 100644 vendor/github.com/golang/dep/testdata/txn_writer/badinput_fileroot create mode 100644 vendor/github.com/golang/dep/testdata/txn_writer/expected_diff_output.txt create mode 100644 vendor/github.com/golang/dep/testdata/txn_writer/expected_lock.toml create mode 100644 vendor/github.com/golang/dep/testdata/txn_writer/expected_manifest.toml create mode 100644 vendor/github.com/golang/dep/testdata/txn_writer/original_lock.toml create mode 100644 vendor/github.com/golang/dep/testdata/txn_writer/updated_lock.toml create mode 100644 vendor/github.com/golang/dep/txn_writer.go create mode 100644 vendor/github.com/golang/dep/txn_writer_test.go create mode 100644 vendor/github.com/golang/dep/website/.gitignore create mode 100644 vendor/github.com/golang/dep/website/blog/2018-01-23-announce-v0.4.0.md create mode 100644 vendor/github.com/golang/dep/website/core/Footer.js create mode 100644 vendor/github.com/golang/dep/website/i18n/en.json create mode 100644 vendor/github.com/golang/dep/website/package.json create mode 100755 vendor/github.com/golang/dep/website/pages/en/help.js create mode 100755 vendor/github.com/golang/dep/website/pages/en/index.js create mode 100644 vendor/github.com/golang/dep/website/pages/en/users.js create mode 100644 vendor/github.com/golang/dep/website/sidebars.json create mode 100644 vendor/github.com/golang/dep/website/siteConfig.js create mode 100644 vendor/github.com/golang/dep/website/static/css/custom.css create mode 100644 vendor/github.com/golang/dep/website/yarn.lock create mode 100644 vendor/github.com/golang/protobuf/.gitignore create mode 100644 vendor/github.com/golang/protobuf/.travis.yml create mode 100644 vendor/github.com/golang/protobuf/AUTHORS create mode 100644 vendor/github.com/golang/protobuf/CONTRIBUTORS create mode 100644 vendor/github.com/golang/protobuf/LICENSE create mode 100644 vendor/github.com/golang/protobuf/Make.protobuf create mode 100644 vendor/github.com/golang/protobuf/Makefile create mode 100644 vendor/github.com/golang/protobuf/README.md create mode 100644 vendor/github.com/golang/protobuf/_conformance/Makefile create mode 100644 vendor/github.com/golang/protobuf/_conformance/conformance.go create mode 100644 vendor/github.com/golang/protobuf/_conformance/conformance_proto/conformance.pb.go create mode 100644 vendor/github.com/golang/protobuf/_conformance/conformance_proto/conformance.proto create mode 100644 vendor/github.com/golang/protobuf/descriptor/descriptor.go create mode 100644 vendor/github.com/golang/protobuf/descriptor/descriptor_test.go create mode 100644 vendor/github.com/golang/protobuf/jsonpb/jsonpb.go create mode 100644 vendor/github.com/golang/protobuf/jsonpb/jsonpb_test.go create mode 100644 vendor/github.com/golang/protobuf/jsonpb/jsonpb_test_proto/Makefile create mode 100644 vendor/github.com/golang/protobuf/jsonpb/jsonpb_test_proto/more_test_objects.pb.go create mode 100644 vendor/github.com/golang/protobuf/jsonpb/jsonpb_test_proto/more_test_objects.proto create mode 100644 vendor/github.com/golang/protobuf/jsonpb/jsonpb_test_proto/test_objects.pb.go create mode 100644 vendor/github.com/golang/protobuf/jsonpb/jsonpb_test_proto/test_objects.proto create mode 100644 vendor/github.com/golang/protobuf/proto/Makefile create mode 100644 vendor/github.com/golang/protobuf/proto/all_test.go create mode 100644 vendor/github.com/golang/protobuf/proto/any_test.go create mode 100644 vendor/github.com/golang/protobuf/proto/clone.go create mode 100644 vendor/github.com/golang/protobuf/proto/clone_test.go create mode 100644 vendor/github.com/golang/protobuf/proto/decode.go create mode 100644 vendor/github.com/golang/protobuf/proto/decode_test.go create mode 100644 vendor/github.com/golang/protobuf/proto/discard.go create mode 100644 vendor/github.com/golang/protobuf/proto/encode.go create mode 100644 vendor/github.com/golang/protobuf/proto/encode_test.go create mode 100644 vendor/github.com/golang/protobuf/proto/equal.go create mode 100644 vendor/github.com/golang/protobuf/proto/equal_test.go create mode 100644 vendor/github.com/golang/protobuf/proto/extensions.go create mode 100644 vendor/github.com/golang/protobuf/proto/extensions_test.go create mode 100644 vendor/github.com/golang/protobuf/proto/lib.go create mode 100644 vendor/github.com/golang/protobuf/proto/map_test.go create mode 100644 vendor/github.com/golang/protobuf/proto/message_set.go create mode 100644 vendor/github.com/golang/protobuf/proto/message_set_test.go create mode 100644 vendor/github.com/golang/protobuf/proto/pointer_reflect.go create mode 100644 vendor/github.com/golang/protobuf/proto/pointer_unsafe.go create mode 100644 vendor/github.com/golang/protobuf/proto/properties.go create mode 100644 vendor/github.com/golang/protobuf/proto/proto3_proto/proto3.pb.go create mode 100644 vendor/github.com/golang/protobuf/proto/proto3_proto/proto3.proto create mode 100644 vendor/github.com/golang/protobuf/proto/proto3_test.go create mode 100644 vendor/github.com/golang/protobuf/proto/size2_test.go create mode 100644 vendor/github.com/golang/protobuf/proto/size_test.go create mode 100644 vendor/github.com/golang/protobuf/proto/testdata/Makefile create mode 100644 vendor/github.com/golang/protobuf/proto/testdata/golden_test.go create mode 100644 vendor/github.com/golang/protobuf/proto/testdata/test.pb.go create mode 100644 vendor/github.com/golang/protobuf/proto/testdata/test.proto create mode 100644 vendor/github.com/golang/protobuf/proto/text.go create mode 100644 vendor/github.com/golang/protobuf/proto/text_parser.go create mode 100644 vendor/github.com/golang/protobuf/proto/text_parser_test.go create mode 100644 vendor/github.com/golang/protobuf/proto/text_test.go create mode 100644 vendor/github.com/golang/protobuf/protoc-gen-go/Makefile create mode 100644 vendor/github.com/golang/protobuf/protoc-gen-go/descriptor/Makefile create mode 100644 vendor/github.com/golang/protobuf/protoc-gen-go/descriptor/descriptor.pb.go create mode 100644 vendor/github.com/golang/protobuf/protoc-gen-go/descriptor/descriptor.proto create mode 100644 vendor/github.com/golang/protobuf/protoc-gen-go/doc.go create mode 100644 vendor/github.com/golang/protobuf/protoc-gen-go/generator/Makefile create mode 100644 vendor/github.com/golang/protobuf/protoc-gen-go/generator/generator.go create mode 100644 vendor/github.com/golang/protobuf/protoc-gen-go/generator/name_test.go create mode 100644 vendor/github.com/golang/protobuf/protoc-gen-go/grpc/grpc.go create mode 100644 vendor/github.com/golang/protobuf/protoc-gen-go/link_grpc.go create mode 100644 vendor/github.com/golang/protobuf/protoc-gen-go/main.go create mode 100644 vendor/github.com/golang/protobuf/protoc-gen-go/plugin/Makefile create mode 100644 vendor/github.com/golang/protobuf/protoc-gen-go/plugin/plugin.pb.go create mode 100644 vendor/github.com/golang/protobuf/protoc-gen-go/plugin/plugin.pb.golden create mode 100644 vendor/github.com/golang/protobuf/protoc-gen-go/plugin/plugin.proto create mode 100644 vendor/github.com/golang/protobuf/protoc-gen-go/testdata/Makefile create mode 100644 vendor/github.com/golang/protobuf/protoc-gen-go/testdata/extension_base.proto create mode 100644 vendor/github.com/golang/protobuf/protoc-gen-go/testdata/extension_extra.proto create mode 100644 vendor/github.com/golang/protobuf/protoc-gen-go/testdata/extension_test.go create mode 100644 vendor/github.com/golang/protobuf/protoc-gen-go/testdata/extension_user.proto create mode 100644 vendor/github.com/golang/protobuf/protoc-gen-go/testdata/grpc.proto create mode 100644 vendor/github.com/golang/protobuf/protoc-gen-go/testdata/imp.pb.go.golden create mode 100644 vendor/github.com/golang/protobuf/protoc-gen-go/testdata/imp.proto create mode 100644 vendor/github.com/golang/protobuf/protoc-gen-go/testdata/imp2.proto create mode 100644 vendor/github.com/golang/protobuf/protoc-gen-go/testdata/imp3.proto create mode 100644 vendor/github.com/golang/protobuf/protoc-gen-go/testdata/main_test.go create mode 100644 vendor/github.com/golang/protobuf/protoc-gen-go/testdata/multi/multi1.proto create mode 100644 vendor/github.com/golang/protobuf/protoc-gen-go/testdata/multi/multi2.proto create mode 100644 vendor/github.com/golang/protobuf/protoc-gen-go/testdata/multi/multi3.proto create mode 100644 vendor/github.com/golang/protobuf/protoc-gen-go/testdata/my_test/test.pb.go create mode 100644 vendor/github.com/golang/protobuf/protoc-gen-go/testdata/my_test/test.pb.go.golden create mode 100644 vendor/github.com/golang/protobuf/protoc-gen-go/testdata/my_test/test.proto create mode 100644 vendor/github.com/golang/protobuf/protoc-gen-go/testdata/proto3.proto create mode 100644 vendor/github.com/golang/protobuf/ptypes/any.go create mode 100644 vendor/github.com/golang/protobuf/ptypes/any/any.pb.go create mode 100644 vendor/github.com/golang/protobuf/ptypes/any/any.proto create mode 100644 vendor/github.com/golang/protobuf/ptypes/any_test.go create mode 100644 vendor/github.com/golang/protobuf/ptypes/doc.go create mode 100644 vendor/github.com/golang/protobuf/ptypes/duration.go create mode 100644 vendor/github.com/golang/protobuf/ptypes/duration/duration.pb.go create mode 100644 vendor/github.com/golang/protobuf/ptypes/duration/duration.proto create mode 100644 vendor/github.com/golang/protobuf/ptypes/duration_test.go create mode 100644 vendor/github.com/golang/protobuf/ptypes/empty/empty.pb.go create mode 100644 vendor/github.com/golang/protobuf/ptypes/empty/empty.proto create mode 100755 vendor/github.com/golang/protobuf/ptypes/regen.sh create mode 100644 vendor/github.com/golang/protobuf/ptypes/struct/struct.pb.go create mode 100644 vendor/github.com/golang/protobuf/ptypes/struct/struct.proto create mode 100644 vendor/github.com/golang/protobuf/ptypes/timestamp.go create mode 100644 vendor/github.com/golang/protobuf/ptypes/timestamp/timestamp.pb.go create mode 100644 vendor/github.com/golang/protobuf/ptypes/timestamp/timestamp.proto create mode 100644 vendor/github.com/golang/protobuf/ptypes/timestamp_test.go create mode 100644 vendor/github.com/golang/protobuf/ptypes/wrappers/wrappers.pb.go create mode 100644 vendor/github.com/golang/protobuf/ptypes/wrappers/wrappers.proto create mode 100644 vendor/github.com/jmank88/nuts/.gitignore create mode 100644 vendor/github.com/jmank88/nuts/.travis.yml create mode 100644 vendor/github.com/jmank88/nuts/Gopkg.lock create mode 100644 vendor/github.com/jmank88/nuts/Gopkg.toml create mode 100644 vendor/github.com/jmank88/nuts/LICENSE create mode 100644 vendor/github.com/jmank88/nuts/README.md create mode 100644 vendor/github.com/jmank88/nuts/cmd/testdb/main.go create mode 100644 vendor/github.com/jmank88/nuts/cmd/testpaths/main.go create mode 100644 vendor/github.com/jmank88/nuts/example_test.go create mode 100644 vendor/github.com/jmank88/nuts/key.go create mode 100644 vendor/github.com/jmank88/nuts/key_test.go create mode 100644 vendor/github.com/jmank88/nuts/nuts.go create mode 100644 vendor/github.com/jmank88/nuts/paths.go create mode 100644 vendor/github.com/jmank88/nuts/paths_test.go create mode 100644 vendor/github.com/jmank88/nuts/types.go create mode 100644 vendor/github.com/nightlyone/lockfile/.gitignore create mode 100644 vendor/github.com/nightlyone/lockfile/.gitmodules create mode 100644 vendor/github.com/nightlyone/lockfile/.travis.yml create mode 100644 vendor/github.com/nightlyone/lockfile/LICENSE create mode 100644 vendor/github.com/nightlyone/lockfile/README.md create mode 100644 vendor/github.com/nightlyone/lockfile/appveyor.yml create mode 100644 vendor/github.com/nightlyone/lockfile/lockfile.go create mode 100644 vendor/github.com/nightlyone/lockfile/lockfile_test.go create mode 100644 vendor/github.com/nightlyone/lockfile/lockfile_unix.go create mode 100644 vendor/github.com/nightlyone/lockfile/lockfile_windows.go create mode 100644 vendor/github.com/pelletier/go-toml/.gitignore create mode 100644 vendor/github.com/pelletier/go-toml/.travis.yml create mode 100644 vendor/github.com/pelletier/go-toml/LICENSE create mode 100644 vendor/github.com/pelletier/go-toml/README.md create mode 100644 vendor/github.com/pelletier/go-toml/benchmark.json create mode 100755 vendor/github.com/pelletier/go-toml/benchmark.sh create mode 100644 vendor/github.com/pelletier/go-toml/benchmark.toml create mode 100644 vendor/github.com/pelletier/go-toml/benchmark.yml create mode 100644 vendor/github.com/pelletier/go-toml/benchmark_test.go create mode 100644 vendor/github.com/pelletier/go-toml/cmd/test_program.go create mode 100644 vendor/github.com/pelletier/go-toml/cmd/tomljson/main.go create mode 100644 vendor/github.com/pelletier/go-toml/cmd/tomljson/main_test.go create mode 100644 vendor/github.com/pelletier/go-toml/cmd/tomll/main.go create mode 100644 vendor/github.com/pelletier/go-toml/doc.go create mode 100644 vendor/github.com/pelletier/go-toml/doc_test.go create mode 100644 vendor/github.com/pelletier/go-toml/example-crlf.toml create mode 100644 vendor/github.com/pelletier/go-toml/example.toml create mode 100644 vendor/github.com/pelletier/go-toml/fuzz.go create mode 100755 vendor/github.com/pelletier/go-toml/fuzz.sh create mode 100644 vendor/github.com/pelletier/go-toml/keysparsing.go create mode 100644 vendor/github.com/pelletier/go-toml/keysparsing_test.go create mode 100644 vendor/github.com/pelletier/go-toml/lexer.go create mode 100644 vendor/github.com/pelletier/go-toml/lexer_test.go create mode 100644 vendor/github.com/pelletier/go-toml/marshal.go create mode 100644 vendor/github.com/pelletier/go-toml/marshal_test.go create mode 100644 vendor/github.com/pelletier/go-toml/marshal_test.toml create mode 100644 vendor/github.com/pelletier/go-toml/parser.go create mode 100644 vendor/github.com/pelletier/go-toml/parser_test.go create mode 100644 vendor/github.com/pelletier/go-toml/position.go create mode 100644 vendor/github.com/pelletier/go-toml/position_test.go create mode 100644 vendor/github.com/pelletier/go-toml/query/doc.go create mode 100644 vendor/github.com/pelletier/go-toml/query/lexer.go create mode 100644 vendor/github.com/pelletier/go-toml/query/lexer_test.go create mode 100644 vendor/github.com/pelletier/go-toml/query/match.go create mode 100644 vendor/github.com/pelletier/go-toml/query/match_test.go create mode 100644 vendor/github.com/pelletier/go-toml/query/parser.go create mode 100644 vendor/github.com/pelletier/go-toml/query/parser_test.go create mode 100644 vendor/github.com/pelletier/go-toml/query/query.go create mode 100644 vendor/github.com/pelletier/go-toml/query/query_test.go create mode 100644 vendor/github.com/pelletier/go-toml/query/tokens.go create mode 100755 vendor/github.com/pelletier/go-toml/test.sh create mode 100644 vendor/github.com/pelletier/go-toml/token.go create mode 100644 vendor/github.com/pelletier/go-toml/token_test.go create mode 100644 vendor/github.com/pelletier/go-toml/toml.go create mode 100644 vendor/github.com/pelletier/go-toml/toml_test.go create mode 100644 vendor/github.com/pelletier/go-toml/tomltree_create.go create mode 100644 vendor/github.com/pelletier/go-toml/tomltree_create_test.go create mode 100644 vendor/github.com/pelletier/go-toml/tomltree_write.go create mode 100644 vendor/github.com/pelletier/go-toml/tomltree_write_test.go create mode 100644 vendor/github.com/pkg/errors/.gitignore create mode 100644 vendor/github.com/pkg/errors/.travis.yml create mode 100644 vendor/github.com/pkg/errors/LICENSE create mode 100644 vendor/github.com/pkg/errors/README.md create mode 100644 vendor/github.com/pkg/errors/appveyor.yml create mode 100644 vendor/github.com/pkg/errors/bench_test.go create mode 100644 vendor/github.com/pkg/errors/errors.go create mode 100644 vendor/github.com/pkg/errors/errors_test.go create mode 100644 vendor/github.com/pkg/errors/example_test.go create mode 100644 vendor/github.com/pkg/errors/format_test.go create mode 100644 vendor/github.com/pkg/errors/stack.go create mode 100644 vendor/github.com/pkg/errors/stack_test.go create mode 100644 vendor/github.com/sdboyer/constext/LICENSE create mode 100644 vendor/github.com/sdboyer/constext/README.md create mode 100644 vendor/github.com/sdboyer/constext/constext.go create mode 100644 vendor/github.com/sdboyer/constext/constext_test.go create mode 100644 vendor/golang.org/x/sync/AUTHORS create mode 100644 vendor/golang.org/x/sync/CONTRIBUTING.md create mode 100644 vendor/golang.org/x/sync/CONTRIBUTORS create mode 100644 vendor/golang.org/x/sync/LICENSE create mode 100644 vendor/golang.org/x/sync/PATENTS create mode 100644 vendor/golang.org/x/sync/README.md create mode 100644 vendor/golang.org/x/sync/codereview.cfg create mode 100644 vendor/golang.org/x/sync/errgroup/errgroup.go create mode 100644 vendor/golang.org/x/sync/errgroup/errgroup_example_md5all_test.go create mode 100644 vendor/golang.org/x/sync/errgroup/errgroup_test.go create mode 100644 vendor/golang.org/x/sync/semaphore/semaphore.go create mode 100644 vendor/golang.org/x/sync/semaphore/semaphore_bench_test.go create mode 100644 vendor/golang.org/x/sync/semaphore/semaphore_example_test.go create mode 100644 vendor/golang.org/x/sync/semaphore/semaphore_test.go create mode 100644 vendor/golang.org/x/sync/singleflight/singleflight.go create mode 100644 vendor/golang.org/x/sync/singleflight/singleflight_test.go create mode 100644 vendor/golang.org/x/sync/syncmap/map.go create mode 100644 vendor/golang.org/x/sync/syncmap/map_bench_test.go create mode 100644 vendor/golang.org/x/sync/syncmap/map_reference_test.go create mode 100644 vendor/golang.org/x/sync/syncmap/map_test.go diff --git a/.gitattributes b/.gitattributes index 6c052cd3..add9d89b 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1 +1,2 @@ +Gopkg.lock -diff /vendor/** -diff diff --git a/Gopkg.lock b/Gopkg.lock index 2b8f38ec..cd49a93c 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -7,12 +7,73 @@ revision = "b26d9c308763d68093482582cea63d69be07a0f0" version = "v0.3.0" +[[projects]] + branch = "parse-constraints-with-dash-in-pre" + name = "github.com/Masterminds/semver" + packages = ["."] + revision = "a93e51b5a57ef416dac8bb02d11407b6f55d8929" + source = "https://github.com/carolynvs/semver.git" + +[[projects]] + name = "github.com/Masterminds/vcs" + packages = ["."] + revision = "6f1c6d150500e452704e9863f68c2559f58616bf" + version = "v1.12.0" + +[[projects]] + branch = "master" + name = "github.com/armon/go-radix" + packages = ["."] + revision = "1fca145dffbcaa8fe914309b1ec0cfc67500fe61" + +[[projects]] + name = "github.com/boltdb/bolt" + packages = ["."] + revision = "2f1ce7a837dcb8da3ec595b1dac9d0632f0f99e8" + version = "v1.3.1" + [[projects]] name = "github.com/fatih/color" packages = ["."] revision = "570b54cabe6b8eb0bc2dfce68d964677d63b5260" version = "v1.5.0" +[[projects]] + branch = "v2" + name = "github.com/go-yaml/yaml" + packages = ["."] + revision = "d670f9405373e636a5a2765eea47fac0c9bc91a4" + +[[projects]] + name = "github.com/golang/dep" + packages = [ + ".", + "cmd/dep", + "gps", + "gps/internal/pb", + "gps/paths", + "gps/pkgtree", + "internal/feedback", + "internal/fs", + "internal/importers", + "internal/importers/base", + "internal/importers/glide", + "internal/importers/glock", + "internal/importers/godep", + "internal/importers/govend", + "internal/importers/govendor", + "internal/importers/gvt", + "internal/importers/vndr" + ] + revision = "37d9ea0ac16f0e0a05afc3b60e1ac8c364b6c329" + version = "v0.4.1" + +[[projects]] + branch = "master" + name = "github.com/golang/protobuf" + packages = ["proto"] + revision = "925541529c1fa6821df4e44ce2723319eb2be768" + [[projects]] branch = "master" name = "github.com/hashicorp/errwrap" @@ -42,6 +103,12 @@ packages = ["io"] revision = "d14ea06fba99483203c19d92cfcd13ebe73135f4" +[[projects]] + name = "github.com/jmank88/nuts" + packages = ["."] + revision = "8b28145dffc87104e66d074f62ea8080edfad7c8" + version = "v0.3.0" + [[projects]] name = "github.com/mattn/go-colorable" packages = ["."] @@ -60,6 +127,30 @@ packages = ["."] revision = "b8bc1bf767474819792c23f32d8286a45736f1c6" +[[projects]] + branch = "master" + name = "github.com/nightlyone/lockfile" + packages = ["."] + revision = "6a197d5ea61168f2ac821de2b7f011b250904900" + +[[projects]] + name = "github.com/pelletier/go-toml" + packages = ["."] + revision = "acdc4509485b587f5e675510c4f2c63e90ff68a8" + version = "v1.1.0" + +[[projects]] + name = "github.com/pkg/errors" + packages = ["."] + revision = "645ef00459ed84a119197bfb8d8205042c6df63d" + version = "v0.8.0" + +[[projects]] + branch = "master" + name = "github.com/sdboyer/constext" + packages = ["."] + revision = "836a144573533ea4da4e6929c235fd348aed1c80" + [[projects]] branch = "master" name = "github.com/sergi/go-diff" @@ -102,6 +193,12 @@ packages = ["context"] revision = "a8b9294777976932365dabb6640cf1468d95c70f" +[[projects]] + branch = "master" + name = "golang.org/x/sync" + packages = ["errgroup"] + revision = "fd80eb99c8f653c847d294a001bdf2a3a6f768f5" + [[projects]] branch = "master" name = "golang.org/x/sys" @@ -189,6 +286,6 @@ [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "c73c50e46f797bc801b24bb8ce24ab7554830a798f454d723fecc531ff11c3b9" + inputs-digest = "38b127558fd27179e9ffb6983c26bdf5ae3de419a6b26443c1d0625fcf0a755d" solver-name = "gps-cdcl" solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml index a3e25655..b7450597 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -21,6 +21,8 @@ # version = "2.4.0" +required = ["github.com/golang/dep/cmd/dep"] + [[constraint]] name = "gopkg.in/src-d/go-git.v4" version = "=v4.0.0-rc15" diff --git a/Makefile b/Makefile index fc388db9..cb57ca6d 100644 --- a/Makefile +++ b/Makefile @@ -19,9 +19,10 @@ precompile: rm $(BIN_DIR)/$(NAME) install-dep: - curl -L -o bin/dep https://github.com/golang/dep/releases/download/v0.3.2/dep-linux-amd64 - chmod +x bin/dep - echo 'Installed dep v0.3.2 to bin/dep' + [ -x bin/dep ] || go build -o bin/dep github.com/golang/dep/cmd/dep + +dep-ensure: install-dep + bin/dep ensure -v test: make @@ -45,4 +46,4 @@ update-doc: all go run _scripts/update-readme.go README.md go run _scripts/update-cmdref.go CMDREF.md -.PHONY: all precompile install-dep test release update-doc +.PHONY: all precompile install-dep dep-ensure test release update-doc diff --git a/vendor/github.com/Masterminds/semver/.travis.yml b/vendor/github.com/Masterminds/semver/.travis.yml new file mode 100644 index 00000000..fa92a5a3 --- /dev/null +++ b/vendor/github.com/Masterminds/semver/.travis.yml @@ -0,0 +1,24 @@ +language: go + +go: + - 1.6 + - 1.7 + - tip + +# Setting sudo access to false will let Travis CI use containers rather than +# VMs to run the tests. For more details see: +# - http://docs.travis-ci.com/user/workers/container-based-infrastructure/ +# - http://docs.travis-ci.com/user/workers/standard-infrastructure/ +sudo: false + +script: + - make setup + - make test + +notifications: + webhooks: + urls: + - https://webhooks.gitter.im/e/06e3328629952dabe3e0 + on_success: change # options: [always|never|change] default: always + on_failure: always # options: [always|never|change] default: always + on_start: never # options: [always|never|change] default: always diff --git a/vendor/github.com/Masterminds/semver/CHANGELOG.md b/vendor/github.com/Masterminds/semver/CHANGELOG.md new file mode 100644 index 00000000..25550675 --- /dev/null +++ b/vendor/github.com/Masterminds/semver/CHANGELOG.md @@ -0,0 +1,17 @@ +# Release 1.x.x (xxxx-xx-xx) + +- Issue #9: Speed up version comparison performance (thanks @sdboyer) +- Issue #8: Added benchmarks (thanks @sdboyer) + +# Release 1.1.0 (2015-03-11) + +- Issue #2: Implemented validation to provide reasons a versions failed a + constraint. + +# Release 1.0.1 (2015-12-31) + +- Fixed #1: * constraint failing on valid versions. + +# Release 1.0.0 (2015-10-20) + +- Initial release diff --git a/vendor/github.com/Masterminds/semver/LICENSE.txt b/vendor/github.com/Masterminds/semver/LICENSE.txt new file mode 100644 index 00000000..0da4aead --- /dev/null +++ b/vendor/github.com/Masterminds/semver/LICENSE.txt @@ -0,0 +1,20 @@ +The Masterminds +Copyright (C) 2014-2015, Matt Butcher and Matt Farina + +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/Masterminds/semver/Makefile b/vendor/github.com/Masterminds/semver/Makefile new file mode 100644 index 00000000..a7a1b4e3 --- /dev/null +++ b/vendor/github.com/Masterminds/semver/Makefile @@ -0,0 +1,36 @@ +.PHONY: setup +setup: + go get -u gopkg.in/alecthomas/gometalinter.v1 + gometalinter.v1 --install + +.PHONY: test +test: validate lint + @echo "==> Running tests" + go test -v + +.PHONY: validate +validate: + @echo "==> Running static validations" + @gometalinter.v1 \ + --disable-all \ + --enable deadcode \ + --severity deadcode:error \ + --enable gofmt \ + --enable gosimple \ + --enable ineffassign \ + --enable misspell \ + --enable vet \ + --tests \ + --vendor \ + --deadline 60s \ + ./... || exit_code=1 + +.PHONY: lint +lint: + @echo "==> Running linters" + @gometalinter.v1 \ + --disable-all \ + --enable golint \ + --vendor \ + --deadline 60s \ + ./... || : diff --git a/vendor/github.com/Masterminds/semver/README.md b/vendor/github.com/Masterminds/semver/README.md new file mode 100644 index 00000000..aa133eac --- /dev/null +++ b/vendor/github.com/Masterminds/semver/README.md @@ -0,0 +1,146 @@ +# SemVer + +The `semver` package provides the ability to work with [Semantic Versions](http://semver.org) in Go. Specifically it provides the ability to: + +* Parse semantic versions +* Sort semantic versions +* Check if a semantic version fits within a set of constraints +* Optionally work with a `v` prefix + +[![Build Status](https://travis-ci.org/Masterminds/semver.svg)](https://travis-ci.org/Masterminds/semver) [![Build status](https://ci.appveyor.com/api/projects/status/jfk66lib7hb985k8/branch/master?svg=true&passingText=windows%20build%20passing&failingText=windows%20build%20failing)](https://ci.appveyor.com/project/mattfarina/semver/branch/master) [![GoDoc](https://godoc.org/github.com/Masterminds/semver?status.png)](https://godoc.org/github.com/Masterminds/semver) [![Go Report Card](http://goreportcard.com/badge/Masterminds/semver)](http://goreportcard.com/report/Masterminds/semver) + +## Parsing Semantic Versions + +To parse a semantic version use the `NewVersion` function. For example, + + v, err := semver.NewVersion("1.2.3-beta.1+build345") + +If there is an error the version wasn't parseable. The version object has methods +to get the parts of the version, compare it to other versions, convert the +version back into a string, and get the original string. For more details +please see the [documentation](https://godoc.org/github.com/Masterminds/semver). + +## Sorting Semantic Versions + +A set of versions can be sorted using the [`sort`](https://golang.org/pkg/sort/) +package from the standard library. For example, + + raw := []string{"1.2.3", "1.0", "1.3", "2", "0.4.2",} + vs := make([]*semver.Version, len(raw)) + for i, r := range raw { + v, err := semver.NewVersion(r) + if err != nil { + t.Errorf("Error parsing version: %s", err) + } + + vs[i] = v + } + + sort.Sort(semver.Collection(vs)) + +## Checking Version Constraints + +Checking a version against version constraints is one of the most featureful +parts of the package. + + c, err := semver.NewConstraint(">= 1.2.3") + if err != nil { + // Handle constraint not being parseable. + } + + v, _ := semver.NewVersion("1.3") + if err != nil { + // Handle version not being parseable. + } + // Check if the version meets the constraints. The a variable will be true. + a := c.Check(v) + +## Basic Comparisons + +There are two elements to the comparisons. First, a comparison string is a list +of comma separated and comparisons. These are then separated by || separated or +comparisons. For example, `">= 1.2, < 3.0.0 || >= 4.2.3"` is looking for a +comparison that's greater than or equal to 1.2 and less than 3.0.0 or is +greater than or equal to 4.2.3. + +The basic comparisons are: + +* `=`: equal (aliased to no operator) +* `!=`: not equal +* `>`: greater than +* `<`: less than +* `>=`: greater than or equal to +* `<=`: less than or equal to + +## Hyphen Range Comparisons + +There are multiple methods to handle ranges and the first is hyphens ranges. +These look like: + +* `1.2 - 1.4.5` which is equivalent to `>= 1.2, <= 1.4.5` +* `2.3.4 - 4.5` which is equivalent to `>= 2.3.4, <= 4.5` + +## Wildcards In Comparisons + +The `x`, `X`, and `*` characters can be used as a wildcard character. This works +for all comparison operators. When used on the `=` operator it falls +back to the pack level comparison (see tilde below). For example, + +* `1.2.x` is equivalent to `>= 1.2.0, < 1.3.0` +* `>= 1.2.x` is equivalent to `>= 1.2.0` +* `<= 2.x` is equivalent to `<= 3` +* `*` is equivalent to `>= 0.0.0` + +## Tilde Range Comparisons (Patch) + +The tilde (`~`) comparison operator is for patch level ranges when a minor +version is specified and major level changes when the minor number is missing. +For example, + +* `~1.2.3` is equivalent to `>= 1.2.3, < 1.3.0` +* `~1` is equivalent to `>= 1, < 2` +* `~2.3` is equivalent to `>= 2.3, < 2.4` +* `~1.2.x` is equivalent to `>= 1.2.0, < 1.3.0` +* `~1.x` is equivalent to `>= 1, < 2` + +## Caret Range Comparisons (Major) + +The caret (`^`) comparison operator is for major level changes. This is useful +when comparisons of API versions as a major change is API breaking. For example, + +* `^1.2.3` is equivalent to `>= 1.2.3, < 2.0.0` +* `^1.2.x` is equivalent to `>= 1.2.0, < 2.0.0` +* `^2.3` is equivalent to `>= 2.3, < 3` +* `^2.x` is equivalent to `>= 2.0.0, < 3` + +# Validation + +In addition to testing a version against a constraint, a version can be validated +against a constraint. When validation fails a slice of errors containing why a +version didn't meet the constraint is returned. For example, + + c, err := semver.NewConstraint("<= 1.2.3, >= 1.4") + if err != nil { + // Handle constraint not being parseable. + } + + v, _ := semver.NewVersion("1.3") + if err != nil { + // Handle version not being parseable. + } + + // Validate a version against a constraint. + a, msgs := c.Validate(v) + // a is false + for _, m := range msgs { + fmt.Println(m) + + // Loops over the errors which would read + // "1.3 is greater than 1.2.3" + // "1.3 is less than 1.4" + } + +# Contribute + +If you find an issue or want to contribute please file an [issue](https://github.com/Masterminds/semver/issues) +or [create a pull request](https://github.com/Masterminds/semver/pulls). diff --git a/vendor/github.com/Masterminds/semver/appveyor.yml b/vendor/github.com/Masterminds/semver/appveyor.yml new file mode 100644 index 00000000..08d60708 --- /dev/null +++ b/vendor/github.com/Masterminds/semver/appveyor.yml @@ -0,0 +1,44 @@ +version: build-{build}.{branch} + +clone_folder: C:\gopath\src\github.com\Masterminds\semver +shallow_clone: true + +environment: + GOPATH: C:\gopath + +platform: + - x64 + +install: + - go version + - go env + - go get -u gopkg.in/alecthomas/gometalinter.v1 + - set PATH=%PATH%;%GOPATH%\bin + - gometalinter.v1.exe --install + +build_script: + - go install -v ./... + +test_script: + - "gometalinter.v1 \ + --disable-all \ + --enable deadcode \ + --severity deadcode:error \ + --enable gofmt \ + --enable gosimple \ + --enable ineffassign \ + --enable misspell \ + --enable vet \ + --tests \ + --vendor \ + --deadline 60s \ + ./... || cmd /C EXIT 0" + - "gometalinter.v1 \ + --disable-all \ + --enable golint \ + --vendor \ + --deadline 60s \ + ./... || cmd /C EXIT 0" + - go test -v + +deploy: off diff --git a/vendor/github.com/Masterminds/semver/benchmark_test.go b/vendor/github.com/Masterminds/semver/benchmark_test.go new file mode 100644 index 00000000..5a76f6a9 --- /dev/null +++ b/vendor/github.com/Masterminds/semver/benchmark_test.go @@ -0,0 +1,259 @@ +package semver + +import "testing" + +func init() { + // disable constraint and version creation caching + CacheConstraints = false + CacheVersions = false +} + +var ( + rc1 = rangeConstraint{ + min: newV(1, 5, 0), + max: newV(2, 0, 0), + includeMax: true, + } + rc2 = rangeConstraint{ + min: newV(2, 0, 0), + max: newV(3, 0, 0), + } + rc3 = rangeConstraint{ + min: newV(1, 5, 0), + max: newV(2, 0, 0), + } + rc4 = rangeConstraint{ + min: newV(1, 7, 0), + max: newV(4, 0, 0), + } + rc5 = rangeConstraint{ + min: newV(2, 7, 0), + max: newV(3, 0, 0), + } + rc6 = rangeConstraint{ + min: newV(3, 0, 1), + max: newV(3, 0, 4), + } + rc7 = rangeConstraint{ + min: newV(1, 0, 0), + max: newV(1, 2, 0), + } + // Two fully non-overlapping unions + u1 = rc1.Union(rc7) + u2 = rc5.Union(rc6) +) + +/* Constraint creation benchmarks */ + +func benchNewConstraint(c string, b *testing.B) { + for i := 0; i < b.N; i++ { + NewConstraint(c) + } +} + +func BenchmarkNewConstraintUnary(b *testing.B) { + benchNewConstraint("=2.0", b) +} + +func BenchmarkNewConstraintTilde(b *testing.B) { + benchNewConstraint("~2.0.0", b) +} + +func BenchmarkNewConstraintCaret(b *testing.B) { + benchNewConstraint("^2.0.0", b) +} + +func BenchmarkNewConstraintWildcard(b *testing.B) { + benchNewConstraint("1.x", b) +} + +func BenchmarkNewConstraintRange(b *testing.B) { + benchNewConstraint(">=2.1.x, <3.1.0", b) +} + +func BenchmarkNewConstraintUnion(b *testing.B) { + benchNewConstraint("~2.0.0 || =3.1.0", b) +} + +/* Validate benchmarks, including fails */ + +func benchValidateVersion(c, v string, b *testing.B) { + version, _ := NewVersion(v) + constraint, _ := NewConstraint(c) + + for i := 0; i < b.N; i++ { + constraint.Matches(version) + } +} + +func BenchmarkValidateVersionUnary(b *testing.B) { + benchValidateVersion("=2.0", "2.0.0", b) +} + +func BenchmarkValidateVersionUnaryFail(b *testing.B) { + benchValidateVersion("=2.0", "2.0.1", b) +} + +func BenchmarkValidateVersionTilde(b *testing.B) { + benchValidateVersion("~2.0.0", "2.0.5", b) +} + +func BenchmarkValidateVersionTildeFail(b *testing.B) { + benchValidateVersion("~2.0.0", "1.0.5", b) +} + +func BenchmarkValidateVersionCaret(b *testing.B) { + benchValidateVersion("^2.0.0", "2.1.0", b) +} + +func BenchmarkValidateVersionCaretFail(b *testing.B) { + benchValidateVersion("^2.0.0", "4.1.0", b) +} + +func BenchmarkValidateVersionWildcard(b *testing.B) { + benchValidateVersion("1.x", "1.4.0", b) +} + +func BenchmarkValidateVersionWildcardFail(b *testing.B) { + benchValidateVersion("1.x", "2.4.0", b) +} + +func BenchmarkValidateVersionRange(b *testing.B) { + benchValidateVersion(">=2.1.x, <3.1.0", "2.4.5", b) +} + +func BenchmarkValidateVersionRangeFail(b *testing.B) { + benchValidateVersion(">=2.1.x, <3.1.0", "1.4.5", b) +} + +func BenchmarkValidateVersionUnion(b *testing.B) { + benchValidateVersion("~2.0.0 || =3.1.0", "3.1.0", b) +} + +func BenchmarkValidateVersionUnionFail(b *testing.B) { + benchValidateVersion("~2.0.0 || =3.1.0", "3.1.1", b) +} + +/* Version creation benchmarks */ + +func benchNewVersion(v string, b *testing.B) { + for i := 0; i < b.N; i++ { + NewVersion(v) + } +} + +func BenchmarkNewVersionSimple(b *testing.B) { + benchNewVersion("1.0.0", b) +} + +func BenchmarkNewVersionPre(b *testing.B) { + benchNewVersion("1.0.0-alpha", b) +} + +func BenchmarkNewVersionMeta(b *testing.B) { + benchNewVersion("1.0.0+metadata", b) +} + +func BenchmarkNewVersionMetaDash(b *testing.B) { + benchNewVersion("1.0.0+metadata-dash", b) +} + +/* Union benchmarks */ + +func BenchmarkAdjacentRangeUnion(b *testing.B) { + for i := 0; i < b.N; i++ { + Union(rc1, rc2) + } +} + +func BenchmarkAdjacentRangeUnionMethod(b *testing.B) { + for i := 0; i < b.N; i++ { + rc1.Union(rc2) + } +} + +func BenchmarkDisjointRangeUnion(b *testing.B) { + for i := 0; i < b.N; i++ { + Union(rc2, rc3) + } +} + +func BenchmarkDisjointRangeUnionMethod(b *testing.B) { + for i := 0; i < b.N; i++ { + rc2.Union(rc3) + } +} + +func BenchmarkOverlappingRangeUnion(b *testing.B) { + for i := 0; i < b.N; i++ { + Union(rc1, rc4) + } +} + +func BenchmarkOverlappingRangeUnionMethod(b *testing.B) { + for i := 0; i < b.N; i++ { + rc1.Union(rc4) + } +} + +func BenchmarkUnionUnion(b *testing.B) { + for i := 0; i < b.N; i++ { + Union(u1, u2) + } +} + +func BenchmarkUnionUnionMethod(b *testing.B) { + for i := 0; i < b.N; i++ { + u1.Union(u2) + } +} + +/* Intersection benchmarks */ + +func BenchmarkSubsetRangeIntersection(b *testing.B) { + for i := 0; i < b.N; i++ { + Intersection(rc2, rc4) + } +} + +func BenchmarkSubsetRangeIntersectionMethod(b *testing.B) { + for i := 0; i < b.N; i++ { + rc2.Intersect(rc4) + } +} + +func BenchmarkDisjointRangeIntersection(b *testing.B) { + for i := 0; i < b.N; i++ { + Intersection(rc2, rc3) + } +} + +func BenchmarkDisjointRangeIntersectionMethod(b *testing.B) { + for i := 0; i < b.N; i++ { + rc2.Intersect(rc3) + } +} + +func BenchmarkOverlappingRangeIntersection(b *testing.B) { + for i := 0; i < b.N; i++ { + Intersection(rc1, rc4) + } +} + +func BenchmarkOverlappingRangeIntersectionMethod(b *testing.B) { + for i := 0; i < b.N; i++ { + rc1.Intersect(rc4) + } +} + +func BenchmarkUnionIntersection(b *testing.B) { + for i := 0; i < b.N; i++ { + Intersection(u1, u2) + } +} + +func BenchmarkUnionIntersectionMethod(b *testing.B) { + for i := 0; i < b.N; i++ { + u1.Intersect(u2) + } +} diff --git a/vendor/github.com/Masterminds/semver/collection.go b/vendor/github.com/Masterminds/semver/collection.go new file mode 100644 index 00000000..459fbe0e --- /dev/null +++ b/vendor/github.com/Masterminds/semver/collection.go @@ -0,0 +1,24 @@ +package semver + +// Collection is a collection of Version instances and implements the sort +// interface. See the sort package for more details. +// https://golang.org/pkg/sort/ +type Collection []Version + +// Len returns the length of a collection. The number of Version instances +// on the slice. +func (c Collection) Len() int { + return len(c) +} + +// Less is needed for the sort interface to compare two Version objects on the +// slice. If checks if one is less than the other. +func (c Collection) Less(i, j int) bool { + return c[i].LessThan(c[j]) +} + +// Swap is needed for the sort interface to replace the Version objects +// at two different positions in the slice. +func (c Collection) Swap(i, j int) { + c[i], c[j] = c[j], c[i] +} diff --git a/vendor/github.com/Masterminds/semver/collection_test.go b/vendor/github.com/Masterminds/semver/collection_test.go new file mode 100644 index 00000000..a1d745f4 --- /dev/null +++ b/vendor/github.com/Masterminds/semver/collection_test.go @@ -0,0 +1,46 @@ +package semver + +import ( + "reflect" + "sort" + "testing" +) + +func TestCollection(t *testing.T) { + raw := []string{ + "1.2.3", + "1.0", + "1.3", + "2", + "0.4.2", + } + + vs := make([]Version, len(raw)) + for i, r := range raw { + v, err := NewVersion(r) + if err != nil { + t.Errorf("Error parsing version: %s", err) + } + + vs[i] = v + } + + sort.Sort(Collection(vs)) + + e := []string{ + "0.4.2", + "1.0.0", + "1.2.3", + "1.3.0", + "2.0.0", + } + + a := make([]string, len(vs)) + for i, v := range vs { + a[i] = v.String() + } + + if !reflect.DeepEqual(a, e) { + t.Error("Sorting Collection failed") + } +} diff --git a/vendor/github.com/Masterminds/semver/constraints.go b/vendor/github.com/Masterminds/semver/constraints.go new file mode 100644 index 00000000..164c0116 --- /dev/null +++ b/vendor/github.com/Masterminds/semver/constraints.go @@ -0,0 +1,315 @@ +package semver + +import ( + "fmt" + "regexp" + "sort" + "strings" + "sync" +) + +var constraintRegex *regexp.Regexp +var constraintRangeRegex *regexp.Regexp + +const cvRegex string = `v?([0-9|x|X|\*]+)(\.[0-9|x|X|\*]+)?(\.[0-9|x|X|\*]+)?` + + `(-([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?` + + `(\+([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?` + +func init() { + constraintOps := []string{ + "", + "=", + "!=", + ">", + "<", + ">=", + "=>", + "<=", + "=<", + "~", + "~>", + "^", + } + + ops := make([]string, 0, len(constraintOps)) + for _, op := range constraintOps { + ops = append(ops, regexp.QuoteMeta(op)) + } + + constraintRegex = regexp.MustCompile(fmt.Sprintf( + `^\s*(%s)\s*(%s)\s*$`, + strings.Join(ops, "|"), + cvRegex)) + + constraintRangeRegex = regexp.MustCompile(fmt.Sprintf( + `\s*(%s)\s*-\s*(%s)\s*`, + cvRegex, cvRegex)) +} + +// Constraint is the interface that wraps checking a semantic version against +// one or more constraints to find a match. +type Constraint interface { + // Constraints compose the fmt.Stringer interface. This method is the + // bijective inverse of NewConstraint(): if a string yielded from this + // method is passed to NewConstraint(), a byte-identical instance of the + // original Constraint will be returend. + fmt.Stringer + + // ImpliedCaretString converts the Constraint to a string in the same manner + // as String(), but treats the empty operator as equivalent to ^, rather + // than =. + // + // In the same way that String() is the inverse of NewConstraint(), this + // method is the inverse of to NewConstraintIC(). + ImpliedCaretString() string + + // Matches checks that a version satisfies the constraint. If it does not, + // an error is returned indcating the problem; if it does, the error is nil. + Matches(v Version) error + + // Intersect computes the intersection between the receiving Constraint and + // passed Constraint, and returns a new Constraint representing the result. + Intersect(Constraint) Constraint + + // Union computes the union between the receiving Constraint and the passed + // Constraint, and returns a new Constraint representing the result. + Union(Constraint) Constraint + + // MatchesAny returns a bool indicating whether there exists any version that + // satisfies both the receiver constraint, and the passed Constraint. + // + // In other words, this reports whether an intersection would be non-empty. + MatchesAny(Constraint) bool + + // Restrict implementation of this interface to this package. We need the + // flexibility of an interface, but we cover all possibilities here; closing + // off the interface to external implementation lets us safely do tricks + // with types for magic types (none and any) + _private() +} + +// realConstraint is used internally to differentiate between any, none, and +// unionConstraints, vs. Version and rangeConstraints. +type realConstraint interface { + Constraint + _real() +} + +// CacheConstraints controls whether or not parsed constraints are cached +var CacheConstraints = true +var constraintCache = make(map[string]ccache) +var constraintCacheIC = make(map[string]ccache) +var constraintCacheLock sync.RWMutex + +type ccache struct { + c Constraint + err error +} + +// NewConstraint takes a string representing a set of semver constraints, and +// returns a corresponding Constraint object. Constraints are suitable +// for checking Versions for admissibility, or combining with other Constraint +// objects. +// +// If an invalid constraint string is passed, more information is provided in +// the returned error string. +func NewConstraint(in string) (Constraint, error) { + return newConstraint(in, false, constraintCache) +} + +// NewConstraintIC ("Implied Caret") is the same as NewConstraint, except that +// it treats an absent operator as being equivalent to ^ instead of =. +func NewConstraintIC(in string) (Constraint, error) { + return newConstraint(in, true, constraintCacheIC) +} + +func newConstraint(in string, ic bool, cache map[string]ccache) (Constraint, error) { + if CacheConstraints { + constraintCacheLock.RLock() + if final, exists := cache[in]; exists { + constraintCacheLock.RUnlock() + return final.c, final.err + } + constraintCacheLock.RUnlock() + } + + // Rewrite - ranges into a comparison operation. + c := rewriteRange(in) + + ors := strings.Split(c, "||") + or := make([]Constraint, len(ors)) + for k, v := range ors { + cs := strings.Split(v, ",") + result := make([]Constraint, len(cs)) + for i, s := range cs { + pc, err := parseConstraint(s, ic) + if err != nil { + if CacheConstraints { + constraintCacheLock.Lock() + cache[in] = ccache{err: err} + constraintCacheLock.Unlock() + } + return nil, err + } + + result[i] = pc + } + or[k] = Intersection(result...) + } + + final := Union(or...) + + if CacheConstraints { + constraintCacheLock.Lock() + cache[in] = ccache{c: final} + constraintCacheLock.Unlock() + } + + return final, nil +} + +// Intersection computes the intersection between N Constraints, returning as +// compact a representation of the intersection as possible. +// +// No error is indicated if all the sets are collectively disjoint; you must inspect the +// return value to see if the result is the empty set (by calling IsNone() on +// it). +func Intersection(cg ...Constraint) Constraint { + // If there's zero or one constraints in the group, we can quit fast + switch len(cg) { + case 0: + // Zero members, only sane thing to do is return none + return None() + case 1: + // Just one member means that's our final constraint + return cg[0] + } + + car, cdr := cg[0], cg[1:] + for _, c := range cdr { + if IsNone(car) { + return None() + } + car = car.Intersect(c) + } + + return car +} + +// Union takes a variable number of constraints, and returns the most compact +// possible representation of those constraints. +// +// This effectively ORs together all the provided constraints. If any of the +// included constraints are the set of all versions (any), that supercedes +// everything else. +func Union(cg ...Constraint) Constraint { + // If there's zero or one constraints in the group, we can quit fast + switch len(cg) { + case 0: + // Zero members, only sane thing to do is return none + return None() + case 1: + // One member, so the result will just be that + return cg[0] + } + + // Preliminary pass to look for 'any' in the current set (and bail out early + // if found), but also construct a []realConstraint for everything else + var real constraintList + + for _, c := range cg { + switch tc := c.(type) { + case any: + return c + case none: + continue + case Version: + //heap.Push(&real, tc) + real = append(real, tc) + case rangeConstraint: + //heap.Push(&real, tc) + real = append(real, tc) + case unionConstraint: + real = append(real, tc...) + //for _, c2 := range tc { + //heap.Push(&real, c2) + //} + default: + panic("unknown constraint type") + } + } + // TODO wtf why isn't heap working...so, ugh, have to do this + + // Sort both the versions and ranges into ascending order + sort.Sort(real) + + // Iteratively merge the constraintList elements + var nuc unionConstraint + for _, c := range real { + if len(nuc) == 0 { + nuc = append(nuc, c) + continue + } + + last := nuc[len(nuc)-1] + switch lt := last.(type) { + case Version: + switch ct := c.(type) { + case Version: + // Two versions in a row; only append if they're not equal + if !lt.Equal(ct) { + nuc = append(nuc, ct) + } + case rangeConstraint: + // Last was version, current is range. constraintList sorts by + // min version, so it's guaranteed that the version will be less + // than the range's min, guaranteeing that these are disjoint. + // + // ...almost. If the min of the range is the same as the + // version, then a union should merge the two by making the + // range inclusive at the bottom. + if lt.Equal(ct.min) { + ct.includeMin = true + nuc[len(nuc)-1] = ct + } else { + nuc = append(nuc, c) + } + } + case rangeConstraint: + switch ct := c.(type) { + case Version: + // Last was range, current is version. constraintList sort invariants guarantee + // that the version will be greater than the min, so we have to + // determine if the version is less than the max. If it is, we + // subsume it into the range with a Union call. + // + // Lazy version: just union them and let rangeConstraint figure + // it out, then switch on the result type. + c2 := lt.Union(ct) + if crc, ok := c2.(realConstraint); ok { + nuc[len(nuc)-1] = crc + } else { + // Otherwise, all it can be is a union constraint. First + // item in the union will be the same range, second will be the + // version, so append onto nuc from one back from the end + nuc = append(nuc[:len(nuc)-1], c2.(unionConstraint)...) + } + case rangeConstraint: + if lt.MatchesAny(ct) || areAdjacent(lt, ct) { + // If the previous range overlaps or is adjacent to the + // current range, we know they'll be able to merge together, + // so overwrite the last item in nuc with the result of that + // merge (which is what Union will produce) + nuc[len(nuc)-1] = lt.Union(ct).(realConstraint) + } else { + nuc = append(nuc, c) + } + } + } + } + + if len(nuc) == 1 { + return nuc[0] + } + return nuc +} diff --git a/vendor/github.com/Masterminds/semver/constraints_test.go b/vendor/github.com/Masterminds/semver/constraints_test.go new file mode 100644 index 00000000..cb77c89d --- /dev/null +++ b/vendor/github.com/Masterminds/semver/constraints_test.go @@ -0,0 +1,712 @@ +package semver + +import "testing" + +func TestParseConstraint(t *testing.T) { + tests := []struct { + in string + c Constraint + err bool + }{ + {"*", Any(), false}, + {">= 1.2", rangeConstraint{ + min: newV(1, 2, 0), + max: Version{special: infiniteVersion}, + includeMin: true, + }, false}, + {"1.0", newV(1, 0, 0), false}, + {"foo", nil, true}, + {"<= 1.2", rangeConstraint{ + min: Version{special: zeroVersion}, + max: newV(1, 2, 0), + includeMax: true, + }, false}, + {"=< 1.2", rangeConstraint{ + min: Version{special: zeroVersion}, + max: newV(1, 2, 0), + includeMax: true, + }, false}, + {"=> 1.2", rangeConstraint{ + min: newV(1, 2, 0), + max: Version{special: infiniteVersion}, + includeMin: true, + }, false}, + {"v1.2", newV(1, 2, 0), false}, + {"=1.5", newV(1, 5, 0), false}, + {"> 1.3", rangeConstraint{ + min: newV(1, 3, 0), + max: Version{special: infiniteVersion}, + }, false}, + {"< 1.4.1", rangeConstraint{ + min: Version{special: zeroVersion}, + max: newV(1, 4, 1), + }, false}, + {"~1.1.0", rangeConstraint{ + min: newV(1, 1, 0), + max: newV(1, 2, 0), + includeMin: true, + includeMax: false, + }, false}, + {"^1.1.0", rangeConstraint{ + min: newV(1, 1, 0), + max: newV(2, 0, 0), + includeMin: true, + includeMax: false, + }, false}, + {"^1.1.0-12-abc123", rangeConstraint{ + min: Version{major: 1, minor: 1, patch: 0, pre: "12-abc123"}, + max: newV(2, 0, 0), + includeMin: true, + includeMax: false, + }, false}, + } + + for _, tc := range tests { + c, err := parseConstraint(tc.in, false) + if tc.err && err == nil { + t.Errorf("Expected error for %s didn't occur", tc.in) + } else if !tc.err && err != nil { + t.Errorf("Unexpected error %q for %s", err, tc.in) + } + + // If an error was expected continue the loop and don't try the other + // tests as they will cause errors. + if tc.err { + continue + } + + if !constraintEq(tc.c, c) { + t.Errorf("%q produced constraint %q, but expected %q", tc.in, c, tc.c) + } + } +} + +func constraintEq(c1, c2 Constraint) bool { + switch tc1 := c1.(type) { + case any: + if _, ok := c2.(any); !ok { + return false + } + return true + case none: + if _, ok := c2.(none); !ok { + return false + } + return true + case Version: + if tc2, ok := c2.(Version); ok { + return tc1.Equal(tc2) + } + return false + case rangeConstraint: + if tc2, ok := c2.(rangeConstraint); ok { + if len(tc1.excl) != len(tc2.excl) { + return false + } + + if !tc1.minIsZero() { + if !(tc1.includeMin == tc2.includeMin && tc1.min.Equal(tc2.min)) { + return false + } + } else if !tc2.minIsZero() { + return false + } + + if !tc1.maxIsInf() { + if !(tc1.includeMax == tc2.includeMax && tc1.max.Equal(tc2.max)) { + return false + } + } else if !tc2.maxIsInf() { + return false + } + + for k, e := range tc1.excl { + if !e.Equal(tc2.excl[k]) { + return false + } + } + return true + } + return false + case unionConstraint: + if tc2, ok := c2.(unionConstraint); ok { + if len(tc1) != len(tc2) { + return false + } + + for k, c := range tc1 { + if !constraintEq(c, tc2[k]) { + return false + } + } + return true + } + return false + } + + panic("unknown type") +} + +// newV is a helper to create a new Version object. +func newV(major, minor, patch uint64) Version { + return Version{ + major: major, + minor: minor, + patch: patch, + } +} + +func TestConstraintCheck(t *testing.T) { + tests := []struct { + constraint string + version string + check bool + }{ + {"= 2.0", "1.2.3", false}, + {"= 2.0", "2.0.0", true}, + {"4.1", "4.1.0", true}, + {"!=4.1", "4.1.0", false}, + {"!=4.1", "5.1.0", true}, + {">1.1", "4.1.0", true}, + {">1.1", "1.1.0", false}, + {"<1.1", "0.1.0", true}, + {"<1.1", "1.1.0", false}, + {"<1.1", "1.1.1", false}, + {">=1.1", "4.1.0", true}, + {">=1.1", "1.1.0", true}, + {">=1.1", "0.0.9", false}, + {"<=1.1", "0.1.0", true}, + {"<=1.1", "1.1.0", true}, + {"<=1.1", "1.1.1", false}, + {"<=1.1-alpha1", "1.1", false}, + {"<=2.x", "3.0.0", false}, + {"<=2.x", "2.9.9", true}, + {"<2.x", "2.0.0", false}, + {"<2.x", "1.9.9", true}, + {">=2.x", "3.0.0", true}, + {">=2.x", "2.9.9", true}, + {">=2.x", "1.9.9", false}, + {">2.x", "3.0.0", true}, + {">2.x", "2.9.9", false}, + {">2.x", "1.9.9", false}, + {"<=2.x-alpha2", "3.0.0-alpha3", false}, + {"<=2.0.0", "2.0.0-alpha1", false}, + {">2.x-beta1", "3.0.0-alpha2", false}, + {"^2.0.0", "3.0.0-alpha2", false}, + {"^2.0.0", "2.0.0-alpha1", false}, + {"^2.1.0-alpha1", "2.1.0-alpha2", true}, // allow prerelease match within same major/minor/patch + {"^2.1.0-alpha1", "2.1.1-alpha2", false}, // but ONLY within same major/minor/patch + {"^2.1.0-alpha3", "2.1.0-alpha2", false}, // still respect prerelease ordering + {"^2.0.0", "2.0.0-alpha2", false}, // and only if the min has a prerelease + } + + for _, tc := range tests { + if testing.Verbose() { + t.Logf("Testing if %q allows %q", tc.constraint, tc.version) + } + c, err := parseConstraint(tc.constraint, false) + if err != nil { + t.Errorf("err: %s", err) + continue + } + + v, err := NewVersion(tc.version) + if err != nil { + t.Errorf("err: %s", err) + continue + } + + a := c.Matches(v) == nil + if a != tc.check { + if tc.check { + t.Errorf("%q should have matched %q", tc.constraint, tc.version) + } else { + t.Errorf("%q should not have matched %q", tc.constraint, tc.version) + } + } + } +} + +func TestNewConstraint(t *testing.T) { + tests := []struct { + input string + c Constraint + err bool + }{ + {">= 1.1", rangeConstraint{ + min: newV(1, 1, 0), + max: Version{special: infiniteVersion}, + includeMin: true, + }, false}, + {"2.0", newV(2, 0, 0), false}, + {">= bar", nil, true}, + {"^1.1.0", rangeConstraint{ + min: newV(1, 1, 0), + max: newV(2, 0, 0), + includeMin: true, + }, false}, + {">= 1.2.3, < 2.0 || => 3.0, < 4", unionConstraint{ + rangeConstraint{ + min: newV(1, 2, 3), + max: newV(2, 0, 0), + includeMin: true, + }, + rangeConstraint{ + min: newV(3, 0, 0), + max: newV(4, 0, 0), + includeMin: true, + }, + }, false}, + {"3-4 || => 1.0, < 2", Union( + rangeConstraint{ + min: newV(3, 0, 0), + max: newV(4, 0, 0), + includeMin: true, + includeMax: true, + }, + rangeConstraint{ + min: newV(1, 0, 0), + max: newV(2, 0, 0), + includeMin: true, + }, + ), false}, + // demonstrates union compression + {"3-4 || => 3.0, < 4", rangeConstraint{ + min: newV(3, 0, 0), + max: newV(4, 0, 0), + includeMin: true, + includeMax: true, + }, false}, + {">=1.1.0, <2.0.0", rangeConstraint{ + min: newV(1, 1, 0), + max: newV(2, 0, 0), + includeMin: true, + includeMax: false, + }, false}, + {"!=1.4.0", rangeConstraint{ + min: Version{special: zeroVersion}, + max: Version{special: infiniteVersion}, + excl: []Version{ + newV(1, 4, 0), + }, + }, false}, + {">=1.1.0, !=1.4.0", rangeConstraint{ + min: newV(1, 1, 0), + max: Version{special: infiniteVersion}, + includeMin: true, + excl: []Version{ + newV(1, 4, 0), + }, + }, false}, + } + + for _, tc := range tests { + c, err := NewConstraint(tc.input) + if tc.err && err == nil { + t.Errorf("expected but did not get error for: %s", tc.input) + continue + } else if !tc.err && err != nil { + t.Errorf("unexpectederror for input %s: %s", tc.input, err) + continue + } + if tc.err { + continue + } + + if !constraintEq(tc.c, c) { + t.Errorf("%q produced constraint %q, but expected %q", tc.input, c, tc.c) + } + } +} + +func TestNewConstraintIC(t *testing.T) { + tests := []struct { + input string + c Constraint + err bool + }{ + {"=2.0", newV(2, 0, 0), false}, + {"= 2.0", newV(2, 0, 0), false}, + {"1.1.0", rangeConstraint{ + min: newV(1, 1, 0), + max: newV(2, 0, 0), + includeMin: true, + }, false}, + {"1.1", rangeConstraint{ + min: newV(1, 1, 0), + max: newV(2, 0, 0), + includeMin: true, + }, false}, + {"v1.1.0-12-abc123", rangeConstraint{ + min: Version{major: 1, minor: 1, patch: 0, pre: "12-abc123"}, + max: newV(2, 0, 0), + includeMin: true, + includeMax: false, + }, false}, + } + + for _, tc := range tests { + c, err := NewConstraintIC(tc.input) + if tc.err && err == nil { + t.Errorf("expected but did not get error for: %s", tc.input) + continue + } else if !tc.err && err != nil { + t.Errorf("unexpectederror for input %s: %s", tc.input, err) + continue + } + if tc.err { + continue + } + + if !constraintEq(tc.c, c) { + t.Errorf("%q produced constraint %q, but expected %q", tc.input, c, tc.c) + } + } +} + +func TestConstraintsCheck(t *testing.T) { + tests := []struct { + constraint string + version string + check bool + }{ + {"*", "1.2.3", true}, + {"~0.0.0", "1.2.3", false}, + {"0.x.x", "1.2.3", false}, + {"0.0.x", "1.2.3", false}, + {"~0.0.0", "0.1.9", false}, + {"~0.0.0", "0.0.9", true}, + {"^0.0.0", "0.0.9", true}, + {"^0.0.0", "0.1.9", false}, // caret behaves like tilde below 1.0.0 + {"= 2.0", "1.2.3", false}, + {"= 2.0", "2.0.0", true}, + {"4.1", "4.1.0", true}, + {"4.1.x", "4.1.3", true}, + {"1.x", "1.4", true}, + {"!=4.1", "4.1.0", false}, + {"!=4.1", "5.1.0", true}, + {"!=4.x", "5.1.0", true}, + {"!=4.x", "4.1.0", false}, + {"!=4.1.x", "4.2.0", true}, + {"!=4.2.x", "4.2.3", false}, + {">1.1", "4.1.0", true}, + {">1.1", "1.1.0", false}, + {"<1.1", "0.1.0", true}, + {"<1.1", "1.1.0", false}, + {"<1.1", "1.1.1", false}, + {"<1.x", "1.1.1", false}, + {"<1.x", "0.9.1", true}, + {"<1.x", "2.1.1", false}, + {"<1.1.x", "1.2.1", false}, + {"<1.1.x", "1.1.500", false}, + {"<1.1.x", "1.0.500", true}, + {"<1.2.x", "1.1.1", true}, + {">=1.1", "4.1.0", true}, + {">=1.1", "1.1.0", true}, + {">=1.1", "0.0.9", false}, + {"<=1.1", "0.1.0", true}, + {"<=1.1", "1.1.0", true}, + {"<=1.x", "1.1.0", true}, + {"<=2.x", "3.1.0", false}, + {"<=1.1", "1.1.1", false}, + {"<=1.1.x", "1.2.500", false}, + {">1.1, <2", "1.1.1", true}, + {">1.1, <3", "4.3.2", false}, + {">=1.1, <2, !=1.2.3", "1.2.3", false}, + {">=1.1, <2, !=1.2.3 || > 3", "3.1.2", true}, + {">=1.1, <2, !=1.2.3 || >= 3", "3.0.0", true}, + {">=1.1, <2, !=1.2.3 || > 3", "3.0.0", false}, + {">=1.1, <2, !=1.2.3 || > 3", "1.2.3", false}, + {"1.1 - 2", "1.1.1", true}, + {"1.1-3", "4.3.2", false}, + {"^1.1", "1.1.1", true}, + {"^1.1", "4.3.2", false}, + {"^1.x", "1.1.1", true}, + {"^2.x", "1.1.1", false}, + {"^1.x", "2.1.1", false}, + {"~*", "2.1.1", true}, + {"~1.x", "2.1.1", false}, + {"~1.x", "1.3.5", true}, + {"~1.x", "1.4", true}, + {"~1.1", "1.1.1", true}, + {"~1.2.3", "1.2.5", true}, + {"~1.2.3", "1.2.2", false}, + {"~1.2.3", "1.3.2", false}, + {"~1.1", "1.2.3", false}, + {"~1.3", "2.4.5", false}, + } + + for _, tc := range tests { + c, err := NewConstraint(tc.constraint) + if err != nil { + t.Errorf("err: %s", err) + continue + } + + v, err := NewVersion(tc.version) + if err != nil { + t.Errorf("err: %s", err) + continue + } + + a := c.Matches(v) == nil + if a != tc.check { + if a { + t.Errorf("Input %q produced constraint %q; should not have admitted %q, but did", tc.constraint, c, tc.version) + } else { + t.Errorf("Input %q produced constraint %q; should have admitted %q, but did not", tc.constraint, c, tc.version) + } + } + } +} + +func TestBidirectionalSerialization(t *testing.T) { + tests := []struct { + io string + eq bool + }{ + {"*", true}, // any + {"~0.0.0", false}, // tildes expand into ranges + {"=2.0", false}, // abbreviated versions print as full + {"4.1.x", false}, // wildcards expand into ranges + {">= 1.1.0", false}, // does not produce spaces on ranges + {"4.1.0", true}, + {"!=4.1.0", true}, + {">=1.1.0", true}, + {">1.0.0, <=1.1.0", true}, + {"<=1.1.0", true}, + {">=1.1.7, <1.3.0", true}, // tilde width + {">=1.1.0, <=2.0.0", true}, // no unary op on lte max + {">1.1.3, <2.0.0", true}, // no unary op on gt min + {">1.1.0, <=2.0.0", true}, // no unary op on gt min and lte max + {">=1.1.0, <=1.2.0", true}, // no unary op on lte max + {">1.1.1, <1.2.0", true}, // no unary op on gt min + {">1.1.7, <=2.0.0", true}, // no unary op on gt min and lte max + {">1.1.7, <=2.0.0", true}, // no unary op on gt min and lte max + {">=0.1.7, <1.0.0", true}, // caret shifting below 1.0.0 + {">=0.1.7, <0.3.0", true}, // caret shifting width below 1.0.0 + } + + for _, fix := range tests { + c, err := NewConstraint(fix.io) + if err != nil { + t.Errorf("Valid constraint string produced unexpected error: %s", err) + } + + eq := fix.io == c.String() + if eq != fix.eq { + if eq { + t.Errorf("Constraint %q should not have reproduced input string %q, but did", c, fix.io) + } else { + t.Errorf("Constraint should have reproduced input string %q, but instead produced %q", fix.io, c) + } + } + } +} + +func TestBidirectionalSerializationIC(t *testing.T) { + tests := []struct { + io string + eq bool + }{ + {"*", true}, // any + {"=2.0.0", true}, // versions retain leading = + {"2.0.0", true}, // (no) caret in, (no) caret out + } + + for _, fix := range tests { + c, err := NewConstraintIC(fix.io) + if err != nil { + t.Errorf("Valid constraint string produced unexpected error: %s", err) + } + + eq := fix.io == c.ImpliedCaretString() + if eq != fix.eq { + if eq { + t.Errorf("Constraint %q should not have reproduced input string %q, but did", c, fix.io) + } else { + t.Errorf("Constraint should have reproduced input string %q, but instead produced %q", fix.io, c) + } + } + } +} + +func TestPreferUnaryOpForm(t *testing.T) { + tests := []struct { + in, out string + }{ + {">=0.1.7, <0.2.0", "^0.1.7"}, // caret shifting below 1.0.0 + {">=1.1.0, <2.0.0", "^1.1.0"}, + {">=1.1.0, <2.0.0, !=1.2.3", "^1.1.0, !=1.2.3"}, + } + + for _, fix := range tests { + c, err := NewConstraint(fix.in) + if err != nil { + t.Errorf("Valid constraint string produced unexpected error: %s", err) + } + + if fix.out != c.String() { + t.Errorf("Constraint %q was not transformed into expected output string %q", fix.in, fix.out) + } + } +} + +func TestRewriteRange(t *testing.T) { + tests := []struct { + c string + nc string + }{ + {"2-3", ">= 2, <= 3"}, + {"2-3, 2-3", ">= 2, <= 3,>= 2, <= 3"}, + {"2-3, 4.0.0-5.1", ">= 2, <= 3,>= 4.0.0, <= 5.1"}, + {"v2-3, 2-3", "v2-3,>= 2, <= 3"}, + } + + for _, tc := range tests { + o := rewriteRange(tc.c) + + if o != tc.nc { + t.Errorf("Range %s rewritten incorrectly as '%s'", tc.c, o) + } + } +} + +func TestIsX(t *testing.T) { + tests := []struct { + t string + c bool + }{ + {"A", false}, + {"%", false}, + {"X", true}, + {"x", true}, + {"*", true}, + } + + for _, tc := range tests { + a := isX(tc.t) + if a != tc.c { + t.Errorf("Function isX error on %s", tc.t) + } + } +} + +func TestUnionErr(t *testing.T) { + u1 := Union( + rangeConstraint{ + min: newV(3, 0, 0), + max: newV(4, 0, 0), + includeMin: true, + includeMax: true, + }, + rangeConstraint{ + min: newV(1, 0, 0), + max: newV(2, 0, 0), + includeMin: true, + }, + ) + fail := u1.Matches(newV(2, 5, 0)) + failstr := `2.5.0 is greater than or equal to the maximum of ^1.0.0 +2.5.0 is less than the minimum of >=3.0.0, <=4.0.0` + if fail.Error() != failstr { + t.Errorf("Did not get expected failure message from union, got %q", fail) + } +} + +func TestIsSuperset(t *testing.T) { + rc := []rangeConstraint{ + { + min: newV(1, 2, 0), + max: newV(2, 0, 0), + includeMin: true, + }, + { + min: newV(1, 2, 0), + max: newV(2, 1, 0), + }, + { + min: Version{special: zeroVersion}, + max: newV(1, 10, 0), + }, + { + min: newV(2, 0, 0), + max: Version{special: infiniteVersion}, + }, + { + min: newV(1, 2, 0), + max: newV(2, 0, 0), + includeMax: true, + }, + } + + for _, c := range rc { + + // Superset comparison is not strict, so a range should always be a superset + // of itself. + if !c.isSupersetOf(c) { + t.Errorf("Ranges should be supersets of themselves; %s indicated it was not", c) + } + } + + pairs := []struct{ l, r rangeConstraint }{ + { + // ensures lte is handled correctly (min side) + l: rc[0], + r: rc[1], + }, + { + // ensures nil on min side works well + l: rc[0], + r: rc[2], + }, + { + // ensures nil on max side works well + l: rc[0], + r: rc[3], + }, + { + // ensures nils on both sides work well + l: rc[2], + r: rc[3], + }, + { + // ensures gte is handled correctly (max side) + l: rc[2], + r: rc[4], + }, + } + + for _, p := range pairs { + if p.l.isSupersetOf(p.r) { + t.Errorf("%s is not a superset of %s", p.l, p.r) + } + if p.r.isSupersetOf(p.l) { + t.Errorf("%s is not a superset of %s", p.r, p.l) + } + } + + rc[1].max.minor = 0 + + if !rc[0].isSupersetOf(rc[1]) { + t.Errorf("%s is a superset of %s", rc[0], rc[1]) + } + rc[1].includeMax = true + if rc[1].isSupersetOf(rc[0]) { + t.Errorf("%s is not a superset of %s", rc[1], rc[0]) + } + rc[0].includeMin = false + if !rc[1].isSupersetOf(rc[0]) { + t.Errorf("%s is a superset of %s", rc[1], rc[0]) + } + + // isSupersetOf ignores excludes, so even though this would make rc[1] not a + // superset of rc[0] anymore, it should still say it is. + rc[1].excl = []Version{ + newV(1, 5, 0), + } + + if !rc[1].isSupersetOf(rc[0]) { + t.Errorf("%s is still a superset of %s, because isSupersetOf is supposed to ignore excluded versions", rc[1], rc[0]) + } +} diff --git a/vendor/github.com/Masterminds/semver/doc.go b/vendor/github.com/Masterminds/semver/doc.go new file mode 100644 index 00000000..e00f65eb --- /dev/null +++ b/vendor/github.com/Masterminds/semver/doc.go @@ -0,0 +1,115 @@ +/* +Package semver provides the ability to work with Semantic Versions (http://semver.org) in Go. + +Specifically it provides the ability to: + + * Parse semantic versions + * Sort semantic versions + * Check if a semantic version fits within a set of constraints + * Optionally work with a `v` prefix + +Parsing Semantic Versions + +To parse a semantic version use the `NewVersion` function. For example, + + v, err := semver.NewVersion("1.2.3-beta.1+build345") + +If there is an error the version wasn't parseable. The version object has methods +to get the parts of the version, compare it to other versions, convert the +version back into a string, and get the original string. For more details +please see the documentation at https://godoc.org/github.com/Masterminds/semver. + +Sorting Semantic Versions + +A set of versions can be sorted using the `sort` package from the standard library. +For example, + + raw := []string{"1.2.3", "1.0", "1.3", "2", "0.4.2",} + vs := make([]*semver.Version, len(raw)) + for i, r := range raw { + v, err := semver.NewVersion(r) + if err != nil { + t.Errorf("Error parsing version: %s", err) + } + + vs[i] = v + } + + sort.Sort(semver.Collection(vs)) + +Checking Version Constraints + +Checking a version against version constraints is one of the most featureful +parts of the package. + + c, err := semver.NewConstraint(">= 1.2.3") + if err != nil { + // Handle constraint not being parseable. + } + + v, _ := semver.NewVersion("1.3") + if err != nil { + // Handle version not being parseable. + } + // Check if the version meets the constraints. The a variable will be true. + a := c.Check(v) + +Basic Comparisons + +There are two elements to the comparisons. First, a comparison string is a list +of comma separated and comparisons. These are then separated by || separated or +comparisons. For example, `">= 1.2, < 3.0.0 || >= 4.2.3"` is looking for a +comparison that's greater than or equal to 1.2 and less than 3.0.0 or is +greater than or equal to 4.2.3. + +The basic comparisons are: + + * `=`: equal (aliased to no operator) + * `!=`: not equal + * `>`: greater than + * `<`: less than + * `>=`: greater than or equal to + * `<=`: less than or equal to + +Hyphen Range Comparisons + +There are multiple methods to handle ranges and the first is hyphens ranges. +These look like: + + * `1.2 - 1.4.5` which is equivalent to `>= 1.2, <= 1.4.5` + * `2.3.4 - 4.5` which is equivalent to `>= 2.3.4, <= 4.5` + +Wildcards In Comparisons + +The `x`, `X`, and `*` characters can be used as a wildcard character. This works +for all comparison operators. When used on the `=` operator it falls +back to the pack level comparison (see tilde below). For example, + + * `1.2.x` is equivalent to `>= 1.2.0, < 1.3.0` + * `>= 1.2.x` is equivalent to `>= 1.2.0` + * `<= 2.x` is equivalent to `<= 3` + * `*` is equivalent to `>= 0.0.0` + +Tilde Range Comparisons (Patch) + +The tilde (`~`) comparison operator is for patch level ranges when a minor +version is specified and major level changes when the minor number is missing. +For example, + + * `~1.2.3` is equivalent to `>= 1.2.3, < 1.3.0` + * `~1` is equivalent to `>= 1, < 2` + * `~2.3` is equivalent to `>= 2.3, < 2.4` + * `~1.2.x` is equivalent to `>= 1.2.0, < 1.3.0` + * `~1.x` is equivalent to `>= 1, < 2` + +Caret Range Comparisons (Major) + +The caret (`^`) comparison operator is for major level changes. This is useful +when comparisons of API versions as a major change is API breaking. For example, + + * `^1.2.3` is equivalent to `>= 1.2.3, < 2.0.0` + * `^1.2.x` is equivalent to `>= 1.2.0, < 2.0.0` + * `^2.3` is equivalent to `>= 2.3, < 3` + * `^2.x` is equivalent to `>= 2.0.0, < 3` +*/ +package semver diff --git a/vendor/github.com/Masterminds/semver/error.go b/vendor/github.com/Masterminds/semver/error.go new file mode 100644 index 00000000..9eb33b39 --- /dev/null +++ b/vendor/github.com/Masterminds/semver/error.go @@ -0,0 +1,83 @@ +package semver + +import ( + "bytes" + "fmt" +) + +var rangeErrs = [...]string{ + "%s is less than the minimum of %s", + "%s is less than or equal to the minimum of %s", + "%s is greater than the maximum of %s", + "%s is greater than or equal to the maximum of %s", + "%s is specifically disallowed in %s", + "%s has prerelease data, so is omitted by the range %s", +} + +const ( + rerrLT = iota + rerrLTE + rerrGT + rerrGTE + rerrNE + rerrPre +) + +// MatchFailure is an interface for failures to find a Constraint match. +type MatchFailure interface { + error + + // Pair returns the version and constraint that did not match prompting + // the error. + Pair() (v Version, c Constraint) +} + +// RangeMatchFailure occurs when a version is not within a constraint range. +type RangeMatchFailure struct { + v Version + rc rangeConstraint + typ int8 +} + +func (rce RangeMatchFailure) Error() string { + return fmt.Sprintf(rangeErrs[rce.typ], rce.v, rce.rc) +} + +// Pair returns the version and constraint that did not match. Part of the +// MatchFailure interface. +func (rce RangeMatchFailure) Pair() (v Version, r Constraint) { + return rce.v, rce.rc +} + +// VersionMatchFailure occurs when two versions do not match each other. +type VersionMatchFailure struct { + v, other Version +} + +func (vce VersionMatchFailure) Error() string { + return fmt.Sprintf("%s is not equal to %s", vce.v, vce.other) +} + +// Pair returns the two versions that did not match. Part of the +// MatchFailure interface. +func (vce VersionMatchFailure) Pair() (v Version, r Constraint) { + return vce.v, vce.other +} + +// MultiMatchFailure errors occur when there are multiple constraints a version +// is being checked against and there are failures. +type MultiMatchFailure []MatchFailure + +func (mmf MultiMatchFailure) Error() string { + var buf bytes.Buffer + + for k, e := range mmf { + if k < len(mmf)-1 { + fmt.Fprintf(&buf, "%s\n", e) + } else { + fmt.Fprintf(&buf, e.Error()) + } + } + + return buf.String() +} diff --git a/vendor/github.com/Masterminds/semver/magic.go b/vendor/github.com/Masterminds/semver/magic.go new file mode 100644 index 00000000..7eee64f1 --- /dev/null +++ b/vendor/github.com/Masterminds/semver/magic.go @@ -0,0 +1,107 @@ +package semver + +import "errors" + +var errNone = errors.New("The 'None' constraint admits no versions.") + +// Any is a constraint that is satisfied by any valid semantic version. +type any struct{} + +// Any creates a constraint that will match any version. +func Any() Constraint { + return any{} +} + +func (any) String() string { + return "*" +} + +func (any) ImpliedCaretString() string { + return "*" +} + +// Matches checks that a version satisfies the constraint. As all versions +// satisfy Any, this always returns nil. +func (any) Matches(v Version) error { + return nil +} + +// Intersect computes the intersection between two constraints. +// +// As Any is the set of all possible versions, any intersection with that +// infinite set will necessarily be the entirety of the second set. Thus, this +// simply returns the passed constraint. +func (any) Intersect(c Constraint) Constraint { + return c +} + +// MatchesAny indicates whether there exists any version that can satisfy both +// this constraint, and the passed constraint. As all versions +// satisfy Any, this is always true - unless none is passed. +func (any) MatchesAny(c Constraint) bool { + if _, ok := c.(none); ok { + return false + } + return true +} + +func (any) Union(c Constraint) Constraint { + return Any() +} + +func (any) _private() {} + +// None is an unsatisfiable constraint - it represents the empty set. +type none struct{} + +// None creates a constraint that matches no versions (the empty set). +func None() Constraint { + return none{} +} + +func (none) String() string { + return "" +} + +func (none) ImpliedCaretString() string { + return "" +} + +// Matches checks that a version satisfies the constraint. As no version can +// satisfy None, this always fails (returns an error). +func (none) Matches(v Version) error { + return errNone +} + +// Intersect computes the intersection between two constraints. +// +// None is the empty set of versions, and any intersection with the empty set is +// necessarily the empty set. Thus, this always returns None. +func (none) Intersect(Constraint) Constraint { + return None() +} + +func (none) Union(c Constraint) Constraint { + return c +} + +// MatchesAny indicates whether there exists any version that can satisfy the +// constraint. As no versions satisfy None, this is always false. +func (none) MatchesAny(c Constraint) bool { + return false +} + +func (none) _private() {} + +// IsNone indicates if a constraint will match no versions - that is, the +// constraint represents the empty set. +func IsNone(c Constraint) bool { + _, ok := c.(none) + return ok +} + +// IsAny indicates if a constraint will match any and all versions. +func IsAny(c Constraint) bool { + _, ok := c.(any) + return ok +} diff --git a/vendor/github.com/Masterminds/semver/parse.go b/vendor/github.com/Masterminds/semver/parse.go new file mode 100644 index 00000000..d4ec22f2 --- /dev/null +++ b/vendor/github.com/Masterminds/semver/parse.go @@ -0,0 +1,240 @@ +package semver + +import ( + "errors" + "fmt" + "strings" +) + +func rewriteRange(i string) string { + m := constraintRangeRegex.FindAllStringSubmatch(i, -1) + if m == nil { + return i + } + o := i + for _, v := range m { + if strings.HasPrefix(v[0], "v") && versionRegex.MatchString(v[0]) { + continue + } + t := fmt.Sprintf(">= %s, <= %s", v[1], v[11]) + o = strings.Replace(o, v[0], t, 1) + } + + return o +} + +func parseConstraint(c string, cbd bool) (Constraint, error) { + m := constraintRegex.FindStringSubmatch(c) + if m == nil { + return nil, fmt.Errorf("Malformed constraint: %s", c) + } + + // Handle the full wildcard case first - easy! + if isX(m[3]) { + return any{}, nil + } + + ver := m[2] + var wildPatch, wildMinor bool + if isX(strings.TrimPrefix(m[4], ".")) { + wildPatch = true + wildMinor = true + ver = fmt.Sprintf("%s.0.0%s", m[3], m[6]) + } else if isX(strings.TrimPrefix(m[5], ".")) { + wildPatch = true + ver = fmt.Sprintf("%s%s.0%s", m[3], m[4], m[6]) + } + + v, err := NewVersion(ver) + if err != nil { + // The constraintRegex should catch any regex parsing errors. So, + // we should never get here. + return nil, errors.New("constraint Parser Error") + } + + // We never want to keep the "original" data in a constraint, and keeping it + // around can disrupt simple equality comparisons. So, strip it out. + v.original = "" + + // If caret-by-default flag is on and there's no operator, convert the + // operator to a caret. + if cbd && m[1] == "" { + m[1] = "^" + } + + switch m[1] { + case "^": + // Caret always expands to a range + return expandCaret(v), nil + case "~": + // Tilde always expands to a range + return expandTilde(v, wildMinor), nil + case "!=": + // Not equals expands to a range if no element isX(); otherwise expands + // to a union of ranges + return expandNeq(v, wildMinor, wildPatch), nil + case "", "=": + if wildPatch || wildMinor { + // Equalling a wildcard has the same behavior as expanding tilde + return expandTilde(v, wildMinor), nil + } + return v, nil + case ">": + return expandGreater(v, wildMinor, wildPatch, false), nil + case ">=", "=>": + return expandGreater(v, wildMinor, wildPatch, true), nil + case "<": + return expandLess(v, wildMinor, wildPatch, false), nil + case "<=", "=<": + return expandLess(v, wildMinor, wildPatch, true), nil + default: + // Shouldn't be possible to get here, unless the regex is allowing + // predicate we don't know about... + return nil, fmt.Errorf("Unrecognized predicate %q", m[1]) + } +} + +func expandCaret(v Version) Constraint { + var maxv Version + // Caret behaves like tilde below 1.0.0 + if v.major == 0 { + maxv.minor = v.minor + 1 + } else { + maxv.major = v.major + 1 + } + + return rangeConstraint{ + min: v, + max: maxv, + includeMin: true, + includeMax: false, + } +} + +func expandTilde(v Version, wildMinor bool) Constraint { + if wildMinor { + // When minor is wild on a tilde, behavior is same as caret + return expandCaret(v) + } + + maxv := Version{ + major: v.major, + minor: v.minor + 1, + patch: 0, + } + + return rangeConstraint{ + min: v, + max: maxv, + includeMin: true, + includeMax: false, + } +} + +// expandNeq expands a "not-equals" constraint. +// +// If the constraint has any wildcards, it will expand into a unionConstraint +// (which is how we represent a disjoint set). If there are no wildcards, it +// will expand to a rangeConstraint with no min or max, but having the one +// exception. +func expandNeq(v Version, wildMinor, wildPatch bool) Constraint { + if !(wildMinor || wildPatch) { + return rangeConstraint{ + min: Version{special: zeroVersion}, + max: Version{special: infiniteVersion}, + excl: []Version{v}, + } + } + + // Create the low range with no min, and the max as the floor admitted by + // the wildcard + lr := rangeConstraint{ + min: Version{special: zeroVersion}, + max: v, + includeMax: false, + } + + // The high range uses the derived version (bumped depending on where the + // wildcards were) as the min, and is inclusive + minv := Version{ + major: v.major, + minor: v.minor, + patch: v.patch, + } + + if wildMinor { + minv.major++ + } else { + minv.minor++ + } + + hr := rangeConstraint{ + min: minv, + max: Version{special: infiniteVersion}, + includeMin: true, + } + + return Union(lr, hr) +} + +func expandGreater(v Version, wildMinor, wildPatch, eq bool) Constraint { + if (wildMinor || wildPatch) && !eq { + // wildcards negate the meaning of prerelease and other info + v = Version{ + major: v.major, + minor: v.minor, + patch: v.patch, + } + + // Not equal but with wildcards is the weird case - we have to bump up + // the next version AND make it equal + if wildMinor { + v.major++ + } else { + v.minor++ + } + return rangeConstraint{ + min: v, + max: Version{special: infiniteVersion}, + includeMin: true, + } + } + + return rangeConstraint{ + min: v, + max: Version{special: infiniteVersion}, + includeMin: eq, + } +} + +func expandLess(v Version, wildMinor, wildPatch, eq bool) Constraint { + if eq && (wildMinor || wildPatch) { + // wildcards negate the meaning of prerelease and other info + v = Version{ + major: v.major, + minor: v.minor, + patch: v.patch, + } + if wildMinor { + v.major++ + } else if wildPatch { + v.minor++ + } + return rangeConstraint{ + min: Version{special: zeroVersion}, + max: v, + includeMax: false, + } + } + + return rangeConstraint{ + min: Version{special: zeroVersion}, + max: v, + includeMax: eq, + } +} + +func isX(x string) bool { + l := strings.ToLower(x) + return l == "x" || l == "*" +} diff --git a/vendor/github.com/Masterminds/semver/range.go b/vendor/github.com/Masterminds/semver/range.go new file mode 100644 index 00000000..bcfdfcf9 --- /dev/null +++ b/vendor/github.com/Masterminds/semver/range.go @@ -0,0 +1,519 @@ +package semver + +import ( + "fmt" + "sort" + "strings" +) + +type rangeConstraint struct { + min, max Version + includeMin, includeMax bool + excl []Version +} + +func (rc rangeConstraint) Matches(v Version) error { + var fail bool + ispre := v.Prerelease() != "" + + rce := RangeMatchFailure{ + v: v, + rc: rc, + } + + if !rc.minIsZero() { + cmp := rc.min.Compare(v) + if rc.includeMin { + rce.typ = rerrLT + fail = cmp == 1 + } else { + rce.typ = rerrLTE + fail = cmp != -1 + } + + if fail { + return rce + } + } + + if !rc.maxIsInf() { + cmp := rc.max.Compare(v) + if rc.includeMax { + rce.typ = rerrGT + fail = cmp == -1 + } else { + rce.typ = rerrGTE + fail = cmp != 1 + + } + + if fail { + return rce + } + } + + for _, excl := range rc.excl { + if excl.Equal(v) { + rce.typ = rerrNE + return rce + } + } + + // If the incoming version has prerelease info, it's usually a match failure + // - unless all the numeric parts are equal between the incoming and the + // minimum. + if !fail && ispre && !numPartsEq(rc.min, v) { + rce.typ = rerrPre + return rce + } + + return nil +} + +func (rc rangeConstraint) dup() rangeConstraint { + // Only need to do anything if there are some excludes + if len(rc.excl) == 0 { + return rc + } + + var excl []Version + excl = make([]Version, len(rc.excl)) + copy(excl, rc.excl) + + return rangeConstraint{ + min: rc.min, + max: rc.max, + includeMin: rc.includeMin, + includeMax: rc.includeMax, + excl: excl, + } +} + +func (rc rangeConstraint) minIsZero() bool { + return rc.min.special == zeroVersion +} + +func (rc rangeConstraint) maxIsInf() bool { + return rc.max.special == infiniteVersion +} + +func (rc rangeConstraint) Intersect(c Constraint) Constraint { + switch oc := c.(type) { + case any: + return rc + case none: + return None() + case unionConstraint: + return oc.Intersect(rc) + case Version: + if err := rc.Matches(oc); err != nil { + return None() + } + return c + case rangeConstraint: + nr := rangeConstraint{ + min: rc.min, + max: rc.max, + includeMin: rc.includeMin, + includeMax: rc.includeMax, + } + + if !oc.minIsZero() { + if nr.minIsZero() || nr.min.LessThan(oc.min) { + nr.min = oc.min + nr.includeMin = oc.includeMin + } else if oc.min.Equal(nr.min) && !oc.includeMin { + // intersection means we must follow the least inclusive + nr.includeMin = false + } + } + + if !oc.maxIsInf() { + if nr.maxIsInf() || nr.max.GreaterThan(oc.max) { + nr.max = oc.max + nr.includeMax = oc.includeMax + } else if oc.max.Equal(nr.max) && !oc.includeMax { + // intersection means we must follow the least inclusive + nr.includeMax = false + } + } + + // Ensure any applicable excls from oc are included in nc + for _, e := range append(rc.excl, oc.excl...) { + if nr.Matches(e) == nil { + nr.excl = append(nr.excl, e) + } + } + + if nr.minIsZero() || nr.maxIsInf() { + return nr + } + + if nr.min.Equal(nr.max) { + // min and max are equal. if range is inclusive, return that + // version; otherwise, none + if nr.includeMin && nr.includeMax { + return nr.min + } + return None() + } + + if nr.min.GreaterThan(nr.max) { + // min is greater than max - not possible, so we return none + return None() + } + + // range now fully validated, return what we have + return nr + + default: + panic("unknown type") + } +} + +func (rc rangeConstraint) Union(c Constraint) Constraint { + switch oc := c.(type) { + case any: + return Any() + case none: + return rc + case unionConstraint: + return Union(rc, oc) + case Version: + if err := rc.Matches(oc); err == nil { + return rc + } else if len(rc.excl) > 0 { // TODO (re)checking like this is wasteful + // ensure we don't have an excl-specific mismatch; if we do, remove + // it and return that + for k, e := range rc.excl { + if e.Equal(oc) { + excl := make([]Version, len(rc.excl)-1) + + if k == len(rc.excl)-1 { + copy(excl, rc.excl[:k]) + } else { + copy(excl, append(rc.excl[:k], rc.excl[k+1:]...)) + } + + return rangeConstraint{ + min: rc.min, + max: rc.max, + includeMin: rc.includeMin, + includeMax: rc.includeMax, + excl: excl, + } + } + } + } + + if oc.LessThan(rc.min) { + return unionConstraint{oc, rc.dup()} + } + if oc.Equal(rc.min) { + ret := rc.dup() + ret.includeMin = true + return ret + } + if oc.Equal(rc.max) { + ret := rc.dup() + ret.includeMax = true + return ret + } + // Only possibility left is gt + return unionConstraint{rc.dup(), oc} + case rangeConstraint: + if (rc.minIsZero() && oc.maxIsInf()) || (rc.maxIsInf() && oc.minIsZero()) { + rcl, ocl := len(rc.excl), len(oc.excl) + // Quick check for open case + if rcl == 0 && ocl == 0 { + return Any() + } + + // This is inefficient, but it's such an absurdly corner case... + if len(dedupeExcls(rc.excl, oc.excl)) == rcl+ocl { + // If deduped excludes are the same length as the individual + // excludes, then they have no overlapping elements, so the + // union knocks out the excludes and we're back to Any. + return Any() + } + + // There's at least some dupes, which are all we need to include + nc := rangeConstraint{ + min: Version{special: zeroVersion}, + max: Version{special: infiniteVersion}, + } + for _, e1 := range rc.excl { + for _, e2 := range oc.excl { + if e1.Equal(e2) { + nc.excl = append(nc.excl, e1) + } + } + } + + return nc + } else if areAdjacent(rc, oc) { + // Receiver adjoins the input from below + nc := rc.dup() + + nc.max = oc.max + nc.includeMax = oc.includeMax + nc.excl = append(nc.excl, oc.excl...) + + return nc + } else if areAdjacent(oc, rc) { + // Input adjoins the receiver from below + nc := oc.dup() + + nc.max = rc.max + nc.includeMax = rc.includeMax + nc.excl = append(nc.excl, rc.excl...) + + return nc + + } else if rc.MatchesAny(oc) { + // Receiver and input overlap; form a new range accordingly. + nc := rangeConstraint{ + min: Version{special: zeroVersion}, + max: Version{special: infiniteVersion}, + } + + // For efficiency, we simultaneously determine if either of the + // ranges are supersets of the other, while also selecting the min + // and max of the new range + var info uint8 + + const ( + lminlt uint8 = 1 << iota // left (rc) min less than right + rminlt // right (oc) min less than left + lmaxgt // left max greater than right + rmaxgt // right max greater than left + lsupr = lminlt | lmaxgt // left is superset of right + rsupl = rminlt | rmaxgt // right is superset of left + ) + + // Pick the min + if !rc.minIsZero() { + if oc.minIsZero() || rc.min.GreaterThan(oc.min) || (rc.min.Equal(oc.min) && !rc.includeMin && oc.includeMin) { + info |= rminlt + nc.min = oc.min + nc.includeMin = oc.includeMin + } else { + info |= lminlt + nc.min = rc.min + nc.includeMin = rc.includeMin + } + } else if !oc.minIsZero() { + info |= lminlt + nc.min = rc.min + nc.includeMin = rc.includeMin + } + + // Pick the max + if !rc.maxIsInf() { + if oc.maxIsInf() || rc.max.LessThan(oc.max) || (rc.max.Equal(oc.max) && !rc.includeMax && oc.includeMax) { + info |= rmaxgt + nc.max = oc.max + nc.includeMax = oc.includeMax + } else { + info |= lmaxgt + nc.max = rc.max + nc.includeMax = rc.includeMax + } + } else if oc.maxIsInf() { + info |= lmaxgt + nc.max = rc.max + nc.includeMax = rc.includeMax + } + + // Reincorporate any excluded versions + if info&lsupr != lsupr { + // rc is not superset of oc, so must walk oc.excl + for _, e := range oc.excl { + if rc.Matches(e) != nil { + nc.excl = append(nc.excl, e) + } + } + } + + if info&rsupl != rsupl { + // oc is not superset of rc, so must walk rc.excl + for _, e := range rc.excl { + if oc.Matches(e) != nil { + nc.excl = append(nc.excl, e) + } + } + } + + return nc + } else { + // Don't call Union() here b/c it would duplicate work + uc := constraintList{rc, oc} + sort.Sort(uc) + return unionConstraint(uc) + } + } + + panic("unknown type") +} + +// isSupersetOf computes whether the receiver rangeConstraint is a superset of +// the passed rangeConstraint. +// +// This is NOT a strict superset comparison, so identical ranges will both +// report being supersets of each other. +// +// Note also that this does *not* compare excluded versions - it only compares +// range endpoints. +func (rc rangeConstraint) isSupersetOf(rc2 rangeConstraint) bool { + if !rc.minIsZero() { + if rc2.minIsZero() || rc.min.GreaterThan(rc2.min) || (rc.min.Equal(rc2.min) && !rc.includeMin && rc2.includeMin) { + return false + } + } + + if !rc.maxIsInf() { + if rc2.maxIsInf() || rc.max.LessThan(rc2.max) || (rc.max.Equal(rc2.max) && !rc.includeMax && rc2.includeMax) { + return false + } + } + + return true +} + +func (rc rangeConstraint) String() string { + return rc.toString(false) +} + +func (rc rangeConstraint) ImpliedCaretString() string { + return rc.toString(true) +} + +func (rc rangeConstraint) toString(impliedCaret bool) string { + var pieces []string + + // We need to trigger the standard verbose handling from various points, so + // wrap it in a function. + noshort := func() { + if !rc.minIsZero() { + if rc.includeMin { + pieces = append(pieces, fmt.Sprintf(">=%s", rc.min)) + } else { + pieces = append(pieces, fmt.Sprintf(">%s", rc.min)) + } + } + + if !rc.maxIsInf() { + if rc.includeMax { + pieces = append(pieces, fmt.Sprintf("<=%s", rc.max)) + } else { + pieces = append(pieces, fmt.Sprintf("<%s", rc.max)) + } + } + } + + // Handle the possibility that we might be able to express the range + // with a caret or tilde, as we prefer those forms. + var caretstr string + if impliedCaret { + caretstr = "%s" + } else { + caretstr = "^%s" + } + + switch { + case rc.minIsZero() && rc.maxIsInf(): + // This if is internal because it's useful to know for the other cases + // that we don't have special values at both bounds + if len(rc.excl) == 0 { + // Shouldn't be possible to reach from anything that can be done + // outside the package, but best to cover it and be safe + return "*" + } + case rc.minIsZero(), rc.includeMax, !rc.includeMin: + // tilde and caret could never apply here + noshort() + case !rc.maxIsInf() && rc.max.Minor() == 0 && rc.max.Patch() == 0: // basic caret + if rc.min.Major() == rc.max.Major()-1 && rc.min.Major() != 0 { + pieces = append(pieces, fmt.Sprintf(caretstr, rc.min)) + } else { + // range is too wide for caret, need standard operators + noshort() + } + case !rc.maxIsInf() && rc.max.Major() != 0 && rc.max.Patch() == 0: // basic tilde + if rc.min.Minor() == rc.max.Minor()-1 && rc.min.Major() == rc.max.Major() { + pieces = append(pieces, fmt.Sprintf("~%s", rc.min)) + } else { + // range is too wide for tilde, need standard operators + noshort() + } + case !rc.maxIsInf() && rc.max.Major() == 0 && rc.max.Patch() == 0 && rc.max.Minor() != 0: + // below 1.0.0, tilde is meaningless but caret is shifted to the + // right (so it basically behaves the same as tilde does above 1.0.0) + if rc.min.Minor() == rc.max.Minor()-1 { + pieces = append(pieces, fmt.Sprintf(caretstr, rc.min)) + } else { + noshort() + } + default: + noshort() + } + + for _, e := range rc.excl { + pieces = append(pieces, fmt.Sprintf("!=%s", e)) + } + + return strings.Join(pieces, ", ") +} + +// areAdjacent tests two constraints to determine if they are adjacent, +// but non-overlapping. +// +// If either constraint is not a range, returns false. We still allow it at the +// type level, however, to make the check convenient elsewhere. +// +// Assumes the first range is less than the second; it is incumbent on the +// caller to arrange the inputs appropriately. +func areAdjacent(c1, c2 Constraint) bool { + var rc1, rc2 rangeConstraint + var ok bool + if rc1, ok = c1.(rangeConstraint); !ok { + return false + } + if rc2, ok = c2.(rangeConstraint); !ok { + return false + } + + if !rc1.max.Equal(rc2.min) { + return false + } + + return (rc1.includeMax && !rc2.includeMin) || + (!rc1.includeMax && rc2.includeMin) +} + +func (rc rangeConstraint) MatchesAny(c Constraint) bool { + if _, ok := rc.Intersect(c).(none); ok { + return false + } + return true +} + +func dedupeExcls(ex1, ex2 []Version) []Version { + // TODO stupid inefficient, but these are really only ever going to be + // small, so not worth optimizing right now + var ret []Version +oloop: + for _, e1 := range ex1 { + for _, e2 := range ex2 { + if e1.Equal(e2) { + continue oloop + } + } + ret = append(ret, e1) + } + + return append(ret, ex2...) +} + +func (rangeConstraint) _private() {} +func (rangeConstraint) _real() {} diff --git a/vendor/github.com/Masterminds/semver/set_ops_test.go b/vendor/github.com/Masterminds/semver/set_ops_test.go new file mode 100644 index 00000000..c08f2761 --- /dev/null +++ b/vendor/github.com/Masterminds/semver/set_ops_test.go @@ -0,0 +1,932 @@ +package semver + +import "testing" + +func TestIntersection(t *testing.T) { + var actual Constraint + rc1 := rangeConstraint{ + min: newV(1, 0, 0), + max: newV(2, 0, 0), + } + + if actual = Intersection(); !IsNone(actual) { + t.Errorf("Intersection of nothing should always produce None; got %q", actual) + } + + if actual = Intersection(rc1); !constraintEq(actual, rc1) { + t.Errorf("Intersection of one item should always return that item; got %q", actual) + } + + if actual = Intersection(rc1, None()); !IsNone(actual) { + t.Errorf("Intersection of anything with None should always produce None; got %q", actual) + } + + if actual = Intersection(rc1, Any()); !constraintEq(actual, rc1) { + t.Errorf("Intersection of anything with Any should return self; got %q", actual) + } + + v1 := newV(1, 5, 0) + if actual = Intersection(rc1, v1); !constraintEq(actual, v1) { + t.Errorf("Got constraint %q, but expected %q", actual, v1) + } + + rc2 := rangeConstraint{ + min: newV(1, 2, 0), + max: newV(2, 2, 0), + } + result := rangeConstraint{ + min: newV(1, 2, 0), + max: newV(2, 0, 0), + } + + if actual = Intersection(rc1, rc2); !constraintEq(actual, result) { + t.Errorf("Got constraint %q, but expected %q", actual, result) + } + + u1 := unionConstraint{ + rangeConstraint{ + min: newV(1, 2, 0), + max: newV(3, 0, 0), + }, + newV(3, 1, 0), + } + + if actual = Intersection(u1, rc1); !constraintEq(actual, result) { + t.Errorf("Got constraint %q, but expected %q", actual, result) + } + if actual = Intersection(rc1, newV(2, 0, 5), u1); !IsNone(actual) { + t.Errorf("First two are disjoint, should have gotten None but got %q", actual) + } +} + +func TestRangeIntersection(t *testing.T) { + var actual Constraint + // Test magic cases + rc1 := rangeConstraint{ + min: newV(1, 0, 0), + max: newV(2, 0, 0), + } + if actual = rc1.Intersect(Any()); !constraintEq(actual, rc1) { + t.Errorf("Intersection of anything with Any should return self; got %q", actual) + } + if actual = rc1.Intersect(None()); !IsNone(actual) { + t.Errorf("Intersection of anything with None should always produce None; got %q", actual) + } + + // Test single version cases + + // single v, in range + v1 := newV(1, 5, 0) + + if actual = rc1.Intersect(v1); !constraintEq(actual, v1) { + t.Errorf("Intersection of version with matching range should return the version; got %q", actual) + } + + // now exclude just that version + rc1.excl = []Version{v1} + if actual = rc1.Intersect(v1); !IsNone(actual) { + t.Errorf("Intersection of version with range having specific exclude for that version should produce None; got %q", actual) + } + + // and, of course, none if the version is out of range + v2 := newV(0, 5, 0) + if actual = rc1.Intersect(v2); !IsNone(actual) { + t.Errorf("Intersection of version with non-matching range should produce None; got %q", actual) + } + + // Test basic overlap case + rc1 = rangeConstraint{ + min: newV(1, 0, 0), + max: newV(2, 0, 0), + } + rc2 := rangeConstraint{ + min: newV(1, 2, 0), + max: newV(2, 2, 0), + } + result := rangeConstraint{ + min: newV(1, 2, 0), + max: newV(2, 0, 0), + } + + if actual = rc1.Intersect(rc2); !constraintEq(actual, result) { + t.Errorf("Got constraint %q, but expected %q", actual, result) + } + if actual = rc2.Intersect(rc1); !constraintEq(actual, result) { + t.Errorf("Got constraint %q, but expected %q", actual, result) + } + + // And with includes + rc1.includeMin = true + rc1.includeMax = true + rc2.includeMin = true + rc2.includeMax = true + result.includeMin = true + result.includeMax = true + + if actual = rc1.Intersect(rc2); !constraintEq(actual, result) { + t.Errorf("Got constraint %q, but expected %q", actual, result) + } + if actual = rc2.Intersect(rc1); !constraintEq(actual, result) { + t.Errorf("Got constraint %q, but expected %q", actual, result) + } + + // Overlaps with nils + rc1 = rangeConstraint{ + min: newV(1, 0, 0), + max: Version{special: infiniteVersion}, + } + rc2 = rangeConstraint{ + min: Version{special: zeroVersion}, + max: newV(2, 2, 0), + } + result = rangeConstraint{ + min: newV(1, 0, 0), + max: newV(2, 2, 0), + } + + if actual = rc1.Intersect(rc2); !constraintEq(actual, result) { + t.Errorf("Got constraint %q, but expected %q", actual, result) + } + if actual = rc2.Intersect(rc1); !constraintEq(actual, result) { + t.Errorf("Got constraint %q, but expected %q", actual, result) + } + + // And with includes + rc1.includeMin = true + rc2.includeMax = true + result.includeMin = true + result.includeMax = true + + if actual = rc1.Intersect(rc2); !constraintEq(actual, result) { + t.Errorf("Got constraint %q, but expected %q", actual, result) + } + if actual = rc2.Intersect(rc1); !constraintEq(actual, result) { + t.Errorf("Got constraint %q, but expected %q", actual, result) + } + + // Test superset overlap case + rc1 = rangeConstraint{ + min: newV(1, 5, 0), + max: newV(2, 0, 0), + } + rc2 = rangeConstraint{ + min: newV(1, 0, 0), + max: newV(3, 0, 0), + } + result = rangeConstraint{ + min: newV(1, 5, 0), + max: newV(2, 0, 0), + } + + if actual = rc1.Intersect(rc2); !constraintEq(actual, result) { + t.Errorf("Got constraint %q, but expected %q", actual, result) + } + if actual = rc2.Intersect(rc1); !constraintEq(actual, result) { + t.Errorf("Got constraint %q, but expected %q", actual, result) + } + + // Make sure irrelevant includes don't leak in + rc2.includeMin = true + rc2.includeMax = true + + if actual = rc1.Intersect(rc2); !constraintEq(actual, result) { + t.Errorf("Got constraint %q, but expected %q", actual, result) + } + if actual = rc2.Intersect(rc1); !constraintEq(actual, result) { + t.Errorf("Got constraint %q, but expected %q", actual, result) + } + + // But relevant includes get used + rc1.includeMin = true + rc1.includeMax = true + result.includeMin = true + result.includeMax = true + + if actual = rc1.Intersect(rc2); !constraintEq(actual, result) { + t.Errorf("Got constraint %q, but expected %q", actual, result) + } + if actual = rc2.Intersect(rc1); !constraintEq(actual, result) { + t.Errorf("Got constraint %q, but expected %q", actual, result) + } + + // Test disjoint case + rc1 = rangeConstraint{ + min: newV(1, 5, 0), + max: newV(1, 6, 0), + } + rc2 = rangeConstraint{ + min: newV(2, 0, 0), + max: newV(3, 0, 0), + } + + if actual = rc1.Intersect(rc2); !constraintEq(actual, None()) { + t.Errorf("Got constraint %q, but expected %q", actual, None()) + } + if actual = rc2.Intersect(rc1); !constraintEq(actual, None()) { + t.Errorf("Got constraint %q, but expected %q", actual, None()) + } + + // Test disjoint at gt/lt boundary (non-adjacent) + rc1 = rangeConstraint{ + min: newV(1, 5, 0), + max: newV(2, 0, 0), + } + rc2 = rangeConstraint{ + min: newV(2, 0, 0), + max: newV(3, 0, 0), + } + + if actual = rc1.Intersect(rc2); !constraintEq(actual, None()) { + t.Errorf("Got constraint %q, but expected %q", actual, None()) + } + if actual = rc2.Intersect(rc1); !constraintEq(actual, None()) { + t.Errorf("Got constraint %q, but expected %q", actual, None()) + } + + // Now, just have them touch at a single version + rc1.includeMax = true + rc2.includeMin = true + + vresult := newV(2, 0, 0) + if actual = rc1.Intersect(rc2); !constraintEq(actual, vresult) { + t.Errorf("Got constraint %q, but expected %q", actual, vresult) + } + if actual = rc2.Intersect(rc1); !constraintEq(actual, vresult) { + t.Errorf("Got constraint %q, but expected %q", actual, vresult) + } + + // Test excludes in intersection range + rc1 = rangeConstraint{ + min: newV(1, 5, 0), + max: newV(2, 0, 0), + excl: []Version{ + newV(1, 6, 0), + }, + } + rc2 = rangeConstraint{ + min: newV(1, 0, 0), + max: newV(3, 0, 0), + } + + if actual = rc1.Intersect(rc2); !constraintEq(actual, rc1) { + t.Errorf("Got constraint %q, but expected %q", actual, rc1) + } + if actual = rc2.Intersect(rc1); !constraintEq(actual, rc1) { + t.Errorf("Got constraint %q, but expected %q", actual, rc1) + } + + // Test excludes not in intersection range + rc1 = rangeConstraint{ + min: newV(1, 5, 0), + max: newV(2, 0, 0), + } + rc2 = rangeConstraint{ + min: newV(1, 0, 0), + max: newV(3, 0, 0), + excl: []Version{ + newV(1, 1, 0), + }, + } + + if actual = rc1.Intersect(rc2); !constraintEq(actual, rc1) { + t.Errorf("Got constraint %q, but expected %q", actual, rc1) + } + if actual = rc2.Intersect(rc1); !constraintEq(actual, rc1) { + t.Errorf("Got constraint %q, but expected %q", actual, rc1) + } + + // Test min, and greater min + rc1 = rangeConstraint{ + min: newV(1, 0, 0), + max: Version{special: infiniteVersion}, + } + rc2 = rangeConstraint{ + min: newV(1, 5, 0), + max: Version{special: infiniteVersion}, + includeMin: true, + } + + if actual = rc1.Intersect(rc2); !constraintEq(actual, rc2) { + t.Errorf("Got constraint %q, but expected %q", actual, result) + } + if actual = rc2.Intersect(rc1); !constraintEq(actual, rc2) { + t.Errorf("Got constraint %q, but expected %q", actual, result) + } + + // Test max, and lesser max + rc1 = rangeConstraint{ + max: newV(1, 0, 0), + } + rc2 = rangeConstraint{ + max: newV(1, 5, 0), + } + result = rangeConstraint{ + max: newV(1, 0, 0), + } + + if actual = rc1.Intersect(rc2); !constraintEq(actual, result) { + t.Errorf("Got constraint %q, but expected %q", actual, result) + } + if actual = rc2.Intersect(rc1); !constraintEq(actual, result) { + t.Errorf("Got constraint %q, but expected %q", actual, result) + } + + // Ensure pure excludes come through as they should + rc1 = rangeConstraint{ + min: Version{special: zeroVersion}, + max: Version{special: infiniteVersion}, + excl: []Version{ + newV(1, 6, 0), + }, + } + + rc2 = rangeConstraint{ + min: Version{special: zeroVersion}, + max: Version{special: infiniteVersion}, + excl: []Version{ + newV(1, 6, 0), + newV(1, 7, 0), + }, + } + + if actual = Any().Intersect(rc1); !constraintEq(actual, rc1) { + t.Errorf("Got constraint %q, but expected %q", actual, rc1) + } + if actual = rc1.Intersect(Any()); !constraintEq(actual, rc1) { + t.Errorf("Got constraint %q, but expected %q", actual, rc1) + } + if actual = rc1.Intersect(rc2); !constraintEq(actual, rc2) { + t.Errorf("Got constraint %q, but expected %q", actual, rc2) + } + + // TODO test the pre-release special range stuff +} + +func TestRangeUnion(t *testing.T) { + var actual Constraint + // Test magic cases + rc1 := rangeConstraint{ + min: newV(1, 0, 0), + max: newV(2, 0, 0), + } + if actual = rc1.Union(Any()); !IsAny(actual) { + t.Errorf("Union of anything with Any should always produce Any; got %q", actual) + } + if actual = rc1.Union(None()); !constraintEq(actual, rc1) { + t.Errorf("Union of anything with None should return self; got %q", actual) + } + + // Test single version cases + + // single v, in range + v1 := newV(1, 5, 0) + + if actual = rc1.Union(v1); !constraintEq(actual, rc1) { + t.Errorf("Union of version with matching range should return the range; got %q", actual) + } + + // now exclude just that version + rc2 := rc1.dup() + rc2.excl = []Version{v1} + if actual = rc2.Union(v1); !constraintEq(actual, rc1) { + t.Errorf("Union of version with range having specific exclude for that version should produce the range without that exclude; got %q", actual) + } + + // and a union if the version is not within the range + v2 := newV(0, 5, 0) + uresult := unionConstraint{v2, rc1} + if actual = rc1.Union(v2); !constraintEq(actual, uresult) { + t.Errorf("Union of version with non-matching range should produce a unionConstraint with those two; got %q", actual) + } + + // union with version at the min should ensure "oreq" + v2 = newV(1, 0, 0) + rc3 := rc1 + rc3.includeMin = true + + if actual = rc1.Union(v2); !constraintEq(actual, rc3) { + t.Errorf("Union of range with version at min end should add includeMin (%q), but got %q", rc3, actual) + } + if actual = v2.Union(rc1); !constraintEq(actual, rc3) { + t.Errorf("Union of range with version at min end should add includeMin (%q), but got %q", rc3, actual) + } + + // same at max end + v2 = newV(2, 0, 0) + rc3.includeMin = false + rc3.includeMax = true + + if actual = rc1.Union(v2); !constraintEq(actual, rc3) { + t.Errorf("Union of range with version at max end should add includeMax (%q), but got %q", rc3, actual) + } + if actual = v2.Union(rc1); !constraintEq(actual, rc3) { + t.Errorf("Union of range with version at max end should add includeMax (%q), but got %q", rc3, actual) + } + + // Test basic overlap case + rc1 = rangeConstraint{ + min: newV(1, 0, 0), + max: newV(2, 0, 0), + } + rc2 = rangeConstraint{ + min: newV(1, 2, 0), + max: newV(2, 2, 0), + } + result := rangeConstraint{ + min: newV(1, 0, 0), + max: newV(2, 2, 0), + } + + if actual = rc1.Union(rc2); !constraintEq(actual, result) { + t.Errorf("Got constraint %q, but expected %q", actual, result) + } + if actual = rc2.Union(rc1); !constraintEq(actual, result) { + t.Errorf("Got constraint %q, but expected %q", actual, result) + } + + // And with includes + rc1.includeMin = true + rc1.includeMax = true + rc2.includeMin = true + rc2.includeMax = true + result.includeMin = true + result.includeMax = true + + if actual = rc1.Union(rc2); !constraintEq(actual, result) { + t.Errorf("Got constraint %q, but expected %q", actual, result) + } + if actual = rc2.Union(rc1); !constraintEq(actual, result) { + t.Errorf("Got constraint %q, but expected %q", actual, result) + } + + // Overlaps with nils + rc1 = rangeConstraint{ + min: newV(1, 0, 0), + max: Version{special: infiniteVersion}, + } + rc2 = rangeConstraint{ + min: Version{special: zeroVersion}, + max: newV(2, 2, 0), + } + + if actual = rc1.Union(rc2); !constraintEq(actual, Any()) { + t.Errorf("Got constraint %q, but expected %q", actual, Any()) + } + if actual = rc2.Union(rc1); !constraintEq(actual, Any()) { + t.Errorf("Got constraint %q, but expected %q", actual, Any()) + } + + // Just one nil in overlap + rc1.max = newV(2, 0, 0) + result = rangeConstraint{ + min: Version{special: zeroVersion}, + max: newV(2, 2, 0), + } + + if actual = rc1.Union(rc2); !constraintEq(actual, result) { + t.Errorf("Got constraint %q, but expected %q", actual, result) + } + if actual = rc2.Union(rc1); !constraintEq(actual, result) { + t.Errorf("Got constraint %q, but expected %q", actual, result) + } + + rc1.max = Version{special: infiniteVersion} + rc2.min = newV(1, 5, 0) + result = rangeConstraint{ + min: newV(1, 0, 0), + max: Version{special: infiniteVersion}, + } + + if actual = rc1.Union(rc2); !constraintEq(actual, result) { + t.Errorf("Got constraint %q, but expected %q", actual, result) + } + if actual = rc2.Union(rc1); !constraintEq(actual, result) { + t.Errorf("Got constraint %q, but expected %q", actual, result) + } + + // Test superset overlap case + rc1 = rangeConstraint{ + min: newV(1, 5, 0), + max: newV(2, 0, 0), + } + rc2 = rangeConstraint{ + min: newV(1, 0, 0), + max: newV(3, 0, 0), + } + + if actual = rc1.Union(rc2); !constraintEq(actual, rc2) { + t.Errorf("Got constraint %q, but expected %q", actual, rc2) + } + if actual = rc2.Union(rc1); !constraintEq(actual, rc2) { + t.Errorf("Got constraint %q, but expected %q", actual, rc2) + } + + // Test disjoint case + rc1 = rangeConstraint{ + min: newV(1, 5, 0), + max: newV(1, 6, 0), + } + rc2 = rangeConstraint{ + min: newV(2, 0, 0), + max: newV(3, 0, 0), + } + uresult = unionConstraint{rc1, rc2} + + if actual = rc1.Union(rc2); !constraintEq(actual, uresult) { + t.Errorf("Got constraint %q, but expected %q", actual, uresult) + } + if actual = rc2.Union(rc1); !constraintEq(actual, uresult) { + t.Errorf("Got constraint %q, but expected %q", actual, uresult) + } + + // Test disjoint at gt/lt boundary (non-adjacent) + rc1 = rangeConstraint{ + min: newV(1, 5, 0), + max: newV(2, 0, 0), + } + rc2 = rangeConstraint{ + min: newV(2, 0, 0), + max: newV(3, 0, 0), + } + uresult = unionConstraint{rc1, rc2} + + if actual = rc1.Union(rc2); !constraintEq(actual, uresult) { + t.Errorf("Got constraint %q, but expected %q", actual, uresult) + } + if actual = rc2.Union(rc1); !constraintEq(actual, uresult) { + t.Errorf("Got constraint %q, but expected %q", actual, uresult) + } + + // Now, just have them touch at a single version + rc1.includeMax = true + rc2.includeMin = true + result = rangeConstraint{ + min: newV(1, 5, 0), + max: newV(3, 0, 0), + } + + if actual = rc1.Union(rc2); !constraintEq(actual, result) { + t.Errorf("Got constraint %q, but expected %q", actual, result) + } + if actual = rc2.Union(rc1); !constraintEq(actual, result) { + t.Errorf("Got constraint %q, but expected %q", actual, result) + } + + // And top-adjacent at that version + rc2.includeMin = false + if actual = rc1.Union(rc2); !constraintEq(actual, result) { + t.Errorf("Got constraint %q, but expected %q", actual, result) + } + if actual = rc2.Union(rc1); !constraintEq(actual, result) { + t.Errorf("Got constraint %q, but expected %q", actual, result) + } + // And bottom-adjacent at that version + rc1.includeMax = false + rc2.includeMin = true + if actual = rc1.Union(rc2); !constraintEq(actual, result) { + t.Errorf("Got constraint %q, but expected %q", actual, result) + } + if actual = rc2.Union(rc1); !constraintEq(actual, result) { + t.Errorf("Got constraint %q, but expected %q", actual, result) + } + + // Test excludes in overlapping range + rc1 = rangeConstraint{ + min: newV(1, 5, 0), + max: newV(2, 0, 0), + excl: []Version{ + newV(1, 6, 0), + }, + } + rc2 = rangeConstraint{ + min: newV(1, 0, 0), + max: newV(3, 0, 0), + } + + if actual = rc1.Union(rc2); !constraintEq(actual, rc2) { + t.Errorf("Got constraint %q, but expected %q", actual, rc2) + } + if actual = rc2.Union(rc1); !constraintEq(actual, rc2) { + t.Errorf("Got constraint %q, but expected %q", actual, rc2) + } + + // Test excludes not in non-overlapping range + rc1 = rangeConstraint{ + min: newV(1, 5, 0), + max: newV(2, 0, 0), + } + rc2 = rangeConstraint{ + min: newV(1, 0, 0), + max: newV(3, 0, 0), + excl: []Version{ + newV(1, 1, 0), + }, + } + + if actual = rc1.Union(rc2); !constraintEq(actual, rc2) { + t.Errorf("Got constraint %q, but expected %q", actual, rc2) + } + if actual = rc2.Union(rc1); !constraintEq(actual, rc2) { + t.Errorf("Got constraint %q, but expected %q", actual, rc2) + } + + // Ensure pure excludes come through as they should + rc1 = rangeConstraint{ + min: Version{special: zeroVersion}, + max: Version{special: infiniteVersion}, + excl: []Version{ + newV(1, 6, 0), + }, + } + + rc2 = rangeConstraint{ + min: Version{special: zeroVersion}, + max: Version{special: infiniteVersion}, + excl: []Version{ + newV(1, 6, 0), + newV(1, 7, 0), + }, + } + + if actual = rc1.Union(rc2); !constraintEq(actual, rc1) { + t.Errorf("Got constraint %q, but expected %q", actual, rc1) + } + if actual = rc2.Union(rc1); !constraintEq(actual, rc1) { + t.Errorf("Got constraint %q, but expected %q", actual, rc1) + } + + rc1 = rangeConstraint{ + min: Version{special: zeroVersion}, + max: Version{special: infiniteVersion}, + excl: []Version{ + newV(1, 5, 0), + }, + } + + if actual = rc1.Union(rc2); !constraintEq(actual, Any()) { + t.Errorf("Got constraint %q, but expected %q", actual, Any()) + } + if actual = rc2.Union(rc1); !constraintEq(actual, Any()) { + t.Errorf("Got constraint %q, but expected %q", actual, Any()) + } + + // TODO test the pre-release special range stuff +} + +func TestUnionIntersection(t *testing.T) { + var actual Constraint + // magic first + u1 := unionConstraint{ + newV(1, 1, 0), + newV(1, 2, 0), + newV(1, 3, 0), + } + if actual = u1.Intersect(Any()); !constraintEq(actual, u1) { + t.Errorf("Intersection of anything with Any should return self; got %s", actual) + } + if actual = u1.Intersect(None()); !IsNone(actual) { + t.Errorf("Intersection of anything with None should always produce None; got %s", actual) + } + if u1.MatchesAny(None()) { + t.Errorf("Can't match any when intersected with None") + } + + // intersect of unions with single versions + v1 := newV(1, 1, 0) + if actual = u1.Intersect(v1); !constraintEq(actual, v1) { + t.Errorf("Got constraint %q, but expected %q", actual, v1) + } + if actual = v1.Intersect(u1); !constraintEq(actual, v1) { + t.Errorf("Got constraint %q, but expected %q", actual, v1) + } + + // intersect of range with union of versions + u1 = unionConstraint{ + newV(1, 1, 0), + newV(1, 2, 0), + newV(1, 3, 0), + } + rc1 := rangeConstraint{ + min: newV(1, 0, 0), + max: newV(2, 0, 0), + } + + if actual = u1.Intersect(rc1); !constraintEq(actual, u1) { + t.Errorf("Got constraint %q, but expected %q", actual, u1) + } + if actual = rc1.Intersect(u1); !constraintEq(actual, u1) { + t.Errorf("Got constraint %q, but expected %q", actual, u1) + } + + u2 := unionConstraint{ + newV(1, 1, 0), + newV(1, 2, 0), + } + + if actual = u1.Intersect(u2); !constraintEq(actual, u2) { + t.Errorf("Got constraint %q, but expected %q", actual, u2) + } + + // Overlapping sub/supersets + rc1 = rangeConstraint{ + min: newV(1, 5, 0), + max: newV(1, 6, 0), + } + rc2 := rangeConstraint{ + min: newV(2, 0, 0), + max: newV(3, 0, 0), + } + rc3 = rangeConstraint{ + min: newV(1, 0, 0), + max: newV(2, 0, 0), + } + rc4 := rangeConstraint{ + min: newV(2, 5, 0), + max: newV(2, 6, 0), + } + u1 = unionConstraint{rc1, rc2} + u2 = unionConstraint{rc3, rc4} + ur := unionConstraint{rc1, rc4} + + if actual = u1.Intersect(u2); !constraintEq(actual, ur) { + t.Errorf("Got constraint %q, but expected %q", actual, ur) + } + if actual = u2.Intersect(u1); !constraintEq(actual, ur) { + t.Errorf("Got constraint %q, but expected %q", actual, ur) + } + + // Ensure excludes carry as they should + rc1.excl = []Version{newV(1, 5, 5)} + u1 = unionConstraint{rc1, rc2} + ur = unionConstraint{rc1, rc4} + + if actual = u1.Intersect(u2); !constraintEq(actual, ur) { + t.Errorf("Got constraint %q, but expected %q", actual, ur) + } + if actual = u2.Intersect(u1); !constraintEq(actual, ur) { + t.Errorf("Got constraint %q, but expected %q", actual, ur) + } +} + +func TestUnionUnion(t *testing.T) { + var actual Constraint + // magic first + u1 := unionConstraint{ + newV(1, 1, 0), + newV(1, 2, 0), + newV(1, 3, 0), + } + if actual = u1.Union(Any()); !IsAny(actual) { + t.Errorf("Union of anything with Any should always return Any; got %s", actual) + } + if actual = u1.Union(None()); !constraintEq(actual, u1) { + t.Errorf("Union of anything with None should always return self; got %s", actual) + } + + // union of uc with single versions + // already present + v1 := newV(1, 2, 0) + if actual = u1.Union(v1); !constraintEq(actual, u1) { + t.Errorf("Got constraint %q, but expected %q", actual, u1) + } + if actual = v1.Union(u1); !constraintEq(actual, u1) { + t.Errorf("Got constraint %q, but expected %q", actual, u1) + } + + // not present + v2 := newV(1, 4, 0) + ur := append(u1, v2) + if actual = u1.Union(v2); !constraintEq(actual, ur) { + t.Errorf("Got constraint %q, but expected %q", actual, ur) + } + if actual = v2.Union(u1); !constraintEq(actual, ur) { + t.Errorf("Got constraint %q, but expected %q", actual, ur) + } + + // union of uc with uc, all versions + u2 := unionConstraint{ + newV(1, 3, 0), + newV(1, 4, 0), + newV(1, 5, 0), + } + ur = unionConstraint{ + newV(1, 1, 0), + newV(1, 2, 0), + newV(1, 3, 0), + newV(1, 4, 0), + newV(1, 5, 0), + } + + if actual = u1.Union(u2); !constraintEq(actual, ur) { + t.Errorf("Got constraint %q, but expected %q", actual, ur) + } + if actual = u2.Union(u1); !constraintEq(actual, ur) { + t.Errorf("Got constraint %q, but expected %q", actual, ur) + } + + // union that should compress versions into range + rc1 := rangeConstraint{ + min: newV(1, 0, 0), + max: newV(2, 0, 0), + } + + if actual = u1.Union(rc1); !constraintEq(actual, rc1) { + t.Errorf("Got constraint %q, but expected %q", actual, rc1) + } + if actual = rc1.Union(u1); !constraintEq(actual, rc1) { + t.Errorf("Got constraint %q, but expected %q", actual, rc1) + } + + rc1.max = newV(1, 4, 5) + u3 := append(u2, newV(1, 7, 0)) + ur = unionConstraint{ + rc1, + newV(1, 5, 0), + newV(1, 7, 0), + } + + if actual = u3.Union(rc1); !constraintEq(actual, ur) { + t.Errorf("Got constraint %q, but expected %q", actual, ur) + } + if actual = rc1.Union(u3); !constraintEq(actual, ur) { + t.Errorf("Got constraint %q, but expected %q", actual, ur) + } +} + +// Most version stuff got tested by range and/or union b/c most tests were +// repeated bidirectionally (set operations are commutative; testing in pairs +// helps us catch any situation where we fail to maintain that invariant) +func TestVersionSetOps(t *testing.T) { + var actual Constraint + + v1 := newV(1, 0, 0) + + if actual = v1.Intersect(v1); !constraintEq(actual, v1) { + t.Errorf("Version intersected with itself should be itself, got %q", actual) + } + if !v1.MatchesAny(v1) { + t.Errorf("MatchesAny should work with a version against itself") + } + + v2 := newV(2, 0, 0) + if actual = v1.Intersect(v2); !IsNone(actual) { + t.Errorf("Versions should only intersect with themselves, got %q", actual) + } + if v1.MatchesAny(v2) { + t.Errorf("MatchesAny should not work when combined with anything other than itself") + } + + result := unionConstraint{v1, v2} + + if actual = v1.Union(v1); !constraintEq(actual, v1) { + t.Errorf("Version union with itself should return self, got %q", actual) + } + + if actual = v1.Union(v2); !constraintEq(actual, result) { + t.Errorf("Got constraint %q, but expected %q", actual, result) + } + if actual = v1.Union(v2); !constraintEq(actual, result) { + // Duplicate just to make sure ordering works right + t.Errorf("Got constraint %q, but expected %q", actual, result) + } +} + +func TestAreAdjacent(t *testing.T) { + rc1 := rangeConstraint{ + min: newV(1, 0, 0), + max: newV(2, 0, 0), + } + rc2 := rangeConstraint{ + min: newV(1, 2, 0), + max: newV(2, 2, 0), + } + + if areAdjacent(rc1, rc2) { + t.Errorf("Ranges overlap, should not indicate as adjacent") + } + + rc2 = rangeConstraint{ + min: newV(2, 0, 0), + } + + if areAdjacent(rc1, rc2) { + t.Errorf("Ranges are non-overlapping and non-adjacent, but reported as adjacent") + } + + rc2.includeMin = true + + if !areAdjacent(rc1, rc2) { + t.Errorf("Ranges are non-overlapping and adjacent, but reported as non-adjacent") + } + + rc1.includeMax = true + + if areAdjacent(rc1, rc2) { + t.Errorf("Ranges are overlapping at a single version, but reported as adjacent") + } + + rc2.includeMin = false + if !areAdjacent(rc1, rc2) { + t.Errorf("Ranges are non-overlapping and adjacent, but reported as non-adjacent") + } +} diff --git a/vendor/github.com/Masterminds/semver/union.go b/vendor/github.com/Masterminds/semver/union.go new file mode 100644 index 00000000..bc794f88 --- /dev/null +++ b/vendor/github.com/Masterminds/semver/union.go @@ -0,0 +1,152 @@ +package semver + +import "strings" + +type unionConstraint []realConstraint + +func (uc unionConstraint) Matches(v Version) error { + var uce MultiMatchFailure + for _, c := range uc { + err := c.Matches(v) + if err == nil { + return nil + } + uce = append(uce, err.(MatchFailure)) + + } + + return uce +} + +func (uc unionConstraint) Intersect(c2 Constraint) Constraint { + var other []realConstraint + + switch tc2 := c2.(type) { + case none: + return None() + case any: + return uc + case Version: + return c2 + case rangeConstraint: + other = append(other, tc2) + case unionConstraint: + other = c2.(unionConstraint) + default: + panic("unknown type") + } + + var newc []Constraint + // TODO there's a smarter way to do this than NxN, but...worth it? + for _, c := range uc { + for _, oc := range other { + i := c.Intersect(oc) + if !IsNone(i) { + newc = append(newc, i) + } + } + } + + return Union(newc...) +} + +func (uc unionConstraint) MatchesAny(c Constraint) bool { + for _, ic := range uc { + if ic.MatchesAny(c) { + return true + } + } + return false +} + +func (uc unionConstraint) Union(c Constraint) Constraint { + return Union(uc, c) +} + +func (uc unionConstraint) String() string { + var pieces []string + for _, c := range uc { + pieces = append(pieces, c.String()) + } + + return strings.Join(pieces, " || ") +} + +func (uc unionConstraint) ImpliedCaretString() string { + var pieces []string + for _, c := range uc { + pieces = append(pieces, c.ImpliedCaretString()) + } + + return strings.Join(pieces, " || ") +} + +func (unionConstraint) _private() {} + +type constraintList []realConstraint + +func (cl constraintList) Len() int { + return len(cl) +} + +func (cl constraintList) Swap(i, j int) { + cl[i], cl[j] = cl[j], cl[i] +} + +func (cl constraintList) Less(i, j int) bool { + ic, jc := cl[i], cl[j] + + switch tic := ic.(type) { + case Version: + switch tjc := jc.(type) { + case Version: + return tic.LessThan(tjc) + case rangeConstraint: + if tjc.minIsZero() { + return false + } + + // Because we don't assume stable sort, always put versions ahead of + // range mins if they're equal and includeMin is on + if tjc.includeMin && tic.Equal(tjc.min) { + return false + } + return tic.LessThan(tjc.min) + } + case rangeConstraint: + switch tjc := jc.(type) { + case Version: + if tic.minIsZero() { + return true + } + + // Because we don't assume stable sort, always put versions ahead of + // range mins if they're equal and includeMin is on + if tic.includeMin && tjc.Equal(tic.min) { + return false + } + return tic.min.LessThan(tjc) + case rangeConstraint: + if tic.minIsZero() { + return true + } + if tjc.minIsZero() { + return false + } + return tic.min.LessThan(tjc.min) + } + } + + panic("unreachable") +} + +func (cl *constraintList) Push(x interface{}) { + *cl = append(*cl, x.(realConstraint)) +} + +func (cl *constraintList) Pop() interface{} { + o := *cl + c := o[len(o)-1] + *cl = o[:len(o)-1] + return c +} diff --git a/vendor/github.com/Masterminds/semver/version.go b/vendor/github.com/Masterminds/semver/version.go new file mode 100644 index 00000000..449b7540 --- /dev/null +++ b/vendor/github.com/Masterminds/semver/version.go @@ -0,0 +1,447 @@ +package semver + +import ( + "bytes" + "errors" + "fmt" + "regexp" + "strconv" + "strings" + "sync" +) + +// The compiled version of the regex created at init() is cached here so it +// only needs to be created once. +var versionRegex *regexp.Regexp + +var ( + // ErrInvalidSemVer is returned a version is found to be invalid when + // being parsed. + ErrInvalidSemVer = errors.New("Invalid Semantic Version") +) + +// Error type; lets us defer string interpolation +type badVersionSegment struct { + e error +} + +func (b badVersionSegment) Error() string { + return fmt.Sprintf("Error parsing version segment: %s", b.e) +} + +// CacheVersions controls whether or not parsed constraints are cached. Defaults +// to true. +var CacheVersions = true +var versionCache = make(map[string]vcache) +var versionCacheLock sync.RWMutex + +type vcache struct { + v Version + err error +} + +// SemVerRegex id the regular expression used to parse a semantic version. +const SemVerRegex string = `v?([0-9]+)(\.[0-9]+)?(\.[0-9]+)?` + + `(-([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?` + + `(\+([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?` + +type specialVersion uint8 + +const ( + notSpecial specialVersion = iota + zeroVersion + infiniteVersion +) + +// Version represents a single semantic version. +type Version struct { + major, minor, patch uint64 + pre string + metadata string + original string + special specialVersion +} + +func init() { + versionRegex = regexp.MustCompile("^" + SemVerRegex + "$") +} + +// NewVersion parses a given version and returns an instance of Version or +// an error if unable to parse the version. +func NewVersion(v string) (Version, error) { + if CacheVersions { + versionCacheLock.RLock() + if sv, exists := versionCache[v]; exists { + versionCacheLock.RUnlock() + return sv.v, sv.err + } + versionCacheLock.RUnlock() + } + + m := versionRegex.FindStringSubmatch(v) + if m == nil { + if CacheVersions { + versionCacheLock.Lock() + versionCache[v] = vcache{err: ErrInvalidSemVer} + versionCacheLock.Unlock() + } + return Version{}, ErrInvalidSemVer + } + + sv := Version{ + metadata: m[8], + pre: m[5], + original: v, + } + + var temp uint64 + temp, err := strconv.ParseUint(m[1], 10, 32) + if err != nil { + bvs := badVersionSegment{e: err} + if CacheVersions { + versionCacheLock.Lock() + versionCache[v] = vcache{err: bvs} + versionCacheLock.Unlock() + } + + return Version{}, bvs + } + sv.major = temp + + if m[2] != "" { + temp, err = strconv.ParseUint(strings.TrimPrefix(m[2], "."), 10, 32) + if err != nil { + bvs := badVersionSegment{e: err} + if CacheVersions { + versionCacheLock.Lock() + versionCache[v] = vcache{err: bvs} + versionCacheLock.Unlock() + } + + return Version{}, bvs + } + sv.minor = temp + } else { + sv.minor = 0 + } + + if m[3] != "" { + temp, err = strconv.ParseUint(strings.TrimPrefix(m[3], "."), 10, 32) + if err != nil { + bvs := badVersionSegment{e: err} + if CacheVersions { + versionCacheLock.Lock() + versionCache[v] = vcache{err: bvs} + versionCacheLock.Unlock() + } + + return Version{}, bvs + } + sv.patch = temp + } else { + sv.patch = 0 + } + + if CacheVersions { + versionCacheLock.Lock() + versionCache[v] = vcache{v: sv} + versionCacheLock.Unlock() + } + + return sv, nil +} + +// String converts a Version object to a string. +// Note, if the original version contained a leading v this version will not. +// See the Original() method to retrieve the original value. Semantic Versions +// don't contain a leading v per the spec. Instead it's optional on +// impelementation. +func (v Version) String() string { + return v.toString(false) +} + +// ImpliedCaretString follows the same rules as String(), but in accordance with +// the Constraint interface will always print a leading "=", as all Versions, +// when acting as a Constraint, act as exact matches. +func (v Version) ImpliedCaretString() string { + return v.toString(true) +} + +func (v Version) toString(ic bool) string { + var buf bytes.Buffer + + var base string + if ic { + base = "=%d.%d.%d" + } else { + base = "%d.%d.%d" + } + + fmt.Fprintf(&buf, base, v.major, v.minor, v.patch) + if v.pre != "" { + fmt.Fprintf(&buf, "-%s", v.pre) + } + if v.metadata != "" { + fmt.Fprintf(&buf, "+%s", v.metadata) + } + + return buf.String() +} + +// Original returns the original value passed in to be parsed. +func (v Version) Original() string { + return v.original +} + +// Major returns the major version. +func (v *Version) Major() uint64 { + return v.major +} + +// Minor returns the minor version. +func (v *Version) Minor() uint64 { + return v.minor +} + +// Patch returns the patch version. +func (v *Version) Patch() uint64 { + return v.patch +} + +// Prerelease returns the pre-release version. +func (v Version) Prerelease() string { + return v.pre +} + +// Metadata returns the metadata on the version. +func (v Version) Metadata() string { + return v.metadata +} + +// LessThan tests if one version is less than another one. +func (v Version) LessThan(o Version) bool { + return v.Compare(o) < 0 +} + +// GreaterThan tests if one version is greater than another one. +func (v Version) GreaterThan(o Version) bool { + return v.Compare(o) > 0 +} + +// Equal tests if two versions are equal to each other. +// Note, versions can be equal with different metadata since metadata +// is not considered part of the comparable version. +func (v Version) Equal(o Version) bool { + return v.Compare(o) == 0 +} + +// Compare compares this version to another one. It returns -1, 0, or 1 if +// the version smaller, equal, or larger than the other version. +// +// Versions are compared by X.Y.Z. Build metadata is ignored. Prerelease is +// lower than the version without a prerelease. +func (v Version) Compare(o Version) int { + // The special field supercedes all the other information. If it's not + // equal, we can skip out early + if v.special != o.special { + switch v.special { + case zeroVersion: + return -1 + case notSpecial: + if o.special == zeroVersion { + return 1 + } + return -1 + case infiniteVersion: + return 1 + } + } else if v.special != notSpecial { + // If special fields are equal and not notSpecial, then they're + // necessarily equal + return 0 + } + + // Compare the major, minor, and patch version for differences. If a + // difference is found return the comparison. + if d := compareSegment(v.Major(), o.Major()); d != 0 { + return d + } + if d := compareSegment(v.Minor(), o.Minor()); d != 0 { + return d + } + if d := compareSegment(v.Patch(), o.Patch()); d != 0 { + return d + } + + // At this point the major, minor, and patch versions are the same. + ps := v.pre + po := o.Prerelease() + + if ps == "" && po == "" { + return 0 + } + if ps == "" { + return 1 + } + if po == "" { + return -1 + } + + return comparePrerelease(ps, po) +} + +// Matches checks that a verstions match. If they do not, +// an error is returned indcating the problem; if it does, the error is nil. +// This is part of the Constraint interface. +func (v Version) Matches(v2 Version) error { + if v.Equal(v2) { + return nil + } + + return VersionMatchFailure{v: v, other: v2} +} + +// MatchesAny checks if an instance of a version matches a constraint which can +// include anything matching the Constraint interface. +func (v Version) MatchesAny(c Constraint) bool { + if v2, ok := c.(Version); ok { + return v.Equal(v2) + } + + // The other implementations all have specific handling for this; fall + // back on theirs. + return c.MatchesAny(v) +} + +// Intersect computes the intersection between the receiving Constraint and +// passed Constraint, and returns a new Constraint representing the result. +// This is part of the Constraint interface. +func (v Version) Intersect(c Constraint) Constraint { + if v2, ok := c.(Version); ok { + if v.Equal(v2) { + return v + } + return none{} + } + + return c.Intersect(v) +} + +// Union computes the union between the receiving Constraint and the passed +// Constraint, and returns a new Constraint representing the result. +// This is part of the Constraint interface. +func (v Version) Union(c Constraint) Constraint { + if v2, ok := c.(Version); ok && v.Equal(v2) { + return v + } + + return Union(v, c) +} + +func (Version) _private() {} +func (Version) _real() {} + +func compareSegment(v, o uint64) int { + if v < o { + return -1 + } + if v > o { + return 1 + } + + return 0 +} + +func comparePrerelease(v, o string) int { + + // split the prelease versions by their part. The separator, per the spec, + // is a . + sparts := strings.Split(v, ".") + oparts := strings.Split(o, ".") + + // Find the longer length of the parts to know how many loop iterations to + // go through. + slen := len(sparts) + olen := len(oparts) + + l := slen + if olen > slen { + l = olen + } + + // Iterate over each part of the prereleases to compare the differences. + for i := 0; i < l; i++ { + // Since the length of the parts can be different we need to create + // a placeholder. This is to avoid out of bounds issues. + stemp := "" + if i < slen { + stemp = sparts[i] + } + + otemp := "" + if i < olen { + otemp = oparts[i] + } + + d := comparePrePart(stemp, otemp) + if d != 0 { + return d + } + } + + // Reaching here means two versions are of equal value but have different + // metadata (the part following a +). They are not identical in string form + // but the version comparison finds them to be equal. + return 0 +} + +func comparePrePart(s, o string) int { + // Fastpath if they are equal + if s == o { + return 0 + } + + // When s or o are empty we can use the other in an attempt to determine + // the response. + if o == "" { + _, n := strconv.ParseUint(s, 10, 64) + if n != nil { + return -1 + } + return 1 + } + if s == "" { + _, n := strconv.ParseUint(o, 10, 64) + if n != nil { + return 1 + } + return -1 + } + + if s > o { + return 1 + } + return -1 +} + +func numPartsEq(v1, v2 Version) bool { + if v1.special != v2.special { + return false + } + if v1.special != notSpecial { + // If special fields are equal and not notSpecial, then the versions are + // necessarily equal, so their numeric parts are too. + return true + } + + if v1.major != v2.major { + return false + } + if v1.minor != v2.minor { + return false + } + if v1.patch != v2.patch { + return false + } + return true +} diff --git a/vendor/github.com/Masterminds/semver/version_test.go b/vendor/github.com/Masterminds/semver/version_test.go new file mode 100644 index 00000000..1fae87f5 --- /dev/null +++ b/vendor/github.com/Masterminds/semver/version_test.go @@ -0,0 +1,310 @@ +package semver + +import ( + "testing" +) + +func TestNewVersion(t *testing.T) { + tests := []struct { + version string + err bool + }{ + {"1.2.3", false}, + {"v1.2.3", false}, + {"1.0", false}, + {"v1.0", false}, + {"1", false}, + {"v1", false}, + {"1.2.beta", true}, + {"v1.2.beta", true}, + {"foo", true}, + {"1.2-5", false}, + {"v1.2-5", false}, + {"1.2-beta.5", false}, + {"v1.2-beta.5", false}, + {"\n1.2", true}, + {"\nv1.2", true}, + {"1.2.0-x.Y.0+metadata", false}, + {"v1.2.0-x.Y.0+metadata", false}, + {"1.2.0-x.Y.0+metadata-width-hypen", false}, + {"v1.2.0-x.Y.0+metadata-width-hypen", false}, + {"1.2.3-rc1-with-hypen", false}, + {"v1.2.3-rc1-with-hypen", false}, + {"1.2.3.4", true}, + {"v1.2.3.4", true}, + } + + for _, tc := range tests { + _, err := NewVersion(tc.version) + if tc.err && err == nil { + t.Fatalf("expected error for version: %s", tc.version) + } else if !tc.err && err != nil { + t.Fatalf("error for version %s: %s", tc.version, err) + } + } +} + +func TestOriginal(t *testing.T) { + tests := []string{ + "1.2.3", + "v1.2.3", + "1.0", + "v1.0", + "1", + "v1", + "1.2-5", + "v1.2-5", + "1.2-beta.5", + "v1.2-beta.5", + "1.2.0-x.Y.0+metadata", + "v1.2.0-x.Y.0+metadata", + "1.2.0-x.Y.0+metadata-width-hypen", + "v1.2.0-x.Y.0+metadata-width-hypen", + "1.2.3-rc1-with-hypen", + "v1.2.3-rc1-with-hypen", + } + + for _, tc := range tests { + v, err := NewVersion(tc) + if err != nil { + t.Errorf("Error parsing version %s", tc) + } + + o := v.Original() + if o != tc { + t.Errorf("Error retrieving originl. Expected '%s' but got '%s'", tc, v) + } + } +} + +func TestParts(t *testing.T) { + v, err := NewVersion("1.2.3-beta.1+build.123") + if err != nil { + t.Error("Error parsing version 1.2.3-beta.1+build.123") + } + + if v.Major() != 1 { + t.Error("Major() returning wrong value") + } + if v.Minor() != 2 { + t.Error("Minor() returning wrong value") + } + if v.Patch() != 3 { + t.Error("Patch() returning wrong value") + } + if v.Prerelease() != "beta.1" { + t.Error("Prerelease() returning wrong value") + } + if v.Metadata() != "build.123" { + t.Error("Metadata() returning wrong value") + } +} + +func TestString(t *testing.T) { + tests := []struct { + version string + expected string + }{ + {"1.2.3", "1.2.3"}, + {"v1.2.3", "1.2.3"}, + {"1.0", "1.0.0"}, + {"v1.0", "1.0.0"}, + {"1", "1.0.0"}, + {"v1", "1.0.0"}, + {"1.2-5", "1.2.0-5"}, + {"v1.2-5", "1.2.0-5"}, + {"1.2-beta.5", "1.2.0-beta.5"}, + {"v1.2-beta.5", "1.2.0-beta.5"}, + {"1.2.0-x.Y.0+metadata", "1.2.0-x.Y.0+metadata"}, + {"v1.2.0-x.Y.0+metadata", "1.2.0-x.Y.0+metadata"}, + {"1.2.0-x.Y.0+metadata-width-hypen", "1.2.0-x.Y.0+metadata-width-hypen"}, + {"v1.2.0-x.Y.0+metadata-width-hypen", "1.2.0-x.Y.0+metadata-width-hypen"}, + {"1.2.3-rc1-with-hypen", "1.2.3-rc1-with-hypen"}, + {"v1.2.3-rc1-with-hypen", "1.2.3-rc1-with-hypen"}, + } + + for _, tc := range tests { + v, err := NewVersion(tc.version) + if err != nil { + t.Errorf("Error parsing version %s", tc) + } + + s := v.String() + if s != tc.expected { + t.Errorf("Error generating string. Expected '%s' but got '%s'", tc.expected, s) + } + } +} + +func TestCompare(t *testing.T) { + tests := []struct { + v1 string + v2 string + expected int + }{ + {"1.2.3", "1.5.1", -1}, + {"2.2.3", "1.5.1", 1}, + {"2.2.3", "2.2.2", 1}, + {"3.2-beta", "3.2-beta", 0}, + {"1.3", "1.1.4", 1}, + {"4.2", "4.2-beta", 1}, + {"4.2-beta", "4.2", -1}, + {"4.2-alpha", "4.2-beta", -1}, + {"4.2-alpha", "4.2-alpha", 0}, + {"4.2-beta.2", "4.2-beta.1", 1}, + {"4.2-beta2", "4.2-beta1", 1}, + {"4.2-beta", "4.2-beta.2", -1}, + {"4.2-beta", "4.2-beta.foo", 1}, + {"4.2-beta.2", "4.2-beta", 1}, + {"4.2-beta.foo", "4.2-beta", -1}, + {"1.2+bar", "1.2+baz", 0}, + } + + for _, tc := range tests { + v1, err := NewVersion(tc.v1) + if err != nil { + t.Errorf("Error parsing version: %s", err) + } + + v2, err := NewVersion(tc.v2) + if err != nil { + t.Errorf("Error parsing version: %s", err) + } + + a := v1.Compare(v2) + e := tc.expected + if a != e { + t.Errorf( + "Comparison of '%s' and '%s' failed. Expected '%d', got '%d'", + tc.v1, tc.v2, e, a, + ) + } + } + + // One-off tests for special version comparisons + zero := Version{special: zeroVersion} + inf := Version{special: infiniteVersion} + + if zero.Compare(inf) != -1 { + t.Error("Zero version should always be less than infinite version") + } + if zero.Compare(zero) != 0 { + t.Error("Zero version should equal itself") + } + if inf.Compare(zero) != 1 { + t.Error("Infinite version should always be greater than zero version") + } + if inf.Compare(inf) != 0 { + t.Error("Infinite version should equal itself") + } + + // Need to work vs. a normal version, too. + v := Version{} + + if zero.Compare(v) != -1 { + t.Error("Zero version should always be less than any normal version") + } + if inf.Compare(v) != 1 { + t.Error("Infinite version should always be greater than any normal version") + } +} + +func TestLessThan(t *testing.T) { + tests := []struct { + v1 string + v2 string + expected bool + }{ + {"1.2.3", "1.5.1", true}, + {"2.2.3", "1.5.1", false}, + {"3.2-beta", "3.2-beta", false}, + } + + for _, tc := range tests { + v1, err := NewVersion(tc.v1) + if err != nil { + t.Errorf("Error parsing version: %s", err) + } + + v2, err := NewVersion(tc.v2) + if err != nil { + t.Errorf("Error parsing version: %s", err) + } + + a := v1.LessThan(v2) + e := tc.expected + if a != e { + t.Errorf( + "Comparison of '%s' and '%s' failed. Expected '%t', got '%t'", + tc.v1, tc.v2, e, a, + ) + } + } +} + +func TestGreaterThan(t *testing.T) { + tests := []struct { + v1 string + v2 string + expected bool + }{ + {"1.2.3", "1.5.1", false}, + {"2.2.3", "1.5.1", true}, + {"3.2-beta", "3.2-beta", false}, + } + + for _, tc := range tests { + v1, err := NewVersion(tc.v1) + if err != nil { + t.Errorf("Error parsing version: %s", err) + } + + v2, err := NewVersion(tc.v2) + if err != nil { + t.Errorf("Error parsing version: %s", err) + } + + a := v1.GreaterThan(v2) + e := tc.expected + if a != e { + t.Errorf( + "Comparison of '%s' and '%s' failed. Expected '%t', got '%t'", + tc.v1, tc.v2, e, a, + ) + } + } +} + +func TestEqual(t *testing.T) { + tests := []struct { + v1 string + v2 string + expected bool + }{ + {"1.2.3", "1.5.1", false}, + {"2.2.3", "1.5.1", false}, + {"3.2-beta", "3.2-beta", true}, + {"3.2-beta+foo", "3.2-beta+bar", true}, + } + + for _, tc := range tests { + v1, err := NewVersion(tc.v1) + if err != nil { + t.Errorf("Error parsing version: %s", err) + } + + v2, err := NewVersion(tc.v2) + if err != nil { + t.Errorf("Error parsing version: %s", err) + } + + a := v1.Equal(v2) + e := tc.expected + if a != e { + t.Errorf( + "Comparison of '%s' and '%s' failed. Expected '%t', got '%t'", + tc.v1, tc.v2, e, a, + ) + } + } +} diff --git a/vendor/github.com/Masterminds/vcs/.gitignore b/vendor/github.com/Masterminds/vcs/.gitignore new file mode 100644 index 00000000..daf913b1 --- /dev/null +++ b/vendor/github.com/Masterminds/vcs/.gitignore @@ -0,0 +1,24 @@ +# 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 diff --git a/vendor/github.com/Masterminds/vcs/.travis.yml b/vendor/github.com/Masterminds/vcs/.travis.yml new file mode 100644 index 00000000..f54b68d6 --- /dev/null +++ b/vendor/github.com/Masterminds/vcs/.travis.yml @@ -0,0 +1,30 @@ +language: go + +go: + - 1.6.x + - 1.7.x + - 1.8.x + - 1.9.x + - master + +before_script: + - git version + - svn --version + +# Setting sudo access to false will let Travis CI use containers rather than +# VMs to run the tests. For more details see: +# - http://docs.travis-ci.com/user/workers/container-based-infrastructure/ +# - http://docs.travis-ci.com/user/workers/standard-infrastructure/ +sudo: false + +script: + - make setup + - make test + +notifications: + webhooks: + urls: + - https://webhooks.gitter.im/e/06e3328629952dabe3e0 + on_success: change # options: [always|never|change] default: always + on_failure: always # options: [always|never|change] default: always + on_start: never # options: [always|never|change] default: always diff --git a/vendor/github.com/Masterminds/vcs/CHANGELOG.md b/vendor/github.com/Masterminds/vcs/CHANGELOG.md new file mode 100644 index 00000000..ff0f8280 --- /dev/null +++ b/vendor/github.com/Masterminds/vcs/CHANGELOG.md @@ -0,0 +1,170 @@ +# Changelog + +## 1.12.0 (2017-09-11) + +### Changed + +- #79: Include the error context in the error string (thanks @guywithnose) +- #80: Bump the Go versions for Travis CI testing (thanks @AlekSi) + +## 1.11.1 (2017-04-28) + +### Fixed + +- #76: Fix submodule handling for Windows (thanks @m0j0hn) + +## 1.11.0 (2017-03-23) + +### Added + +- #65: Exposed CmdFromDir function (thanks @erizocosmico) + +### Changed + +- #69: Updated testing for Go 1.8 + +### Fixed + +- #64: Testing fatal error if bzr not installed (thanks @kevinburke) + +## 1.10.2 (2017-01-24) + +### Fixed + +- #63: Remove extra quotes in submodule export (thanks @dt) + +## 1.10.1 (2017-01-18) + +### Fixed + +- #62: Added windows testing via appveyor and fixed issues under windows. + +## 1.10.0 (2017-01-09) + +### Added + +- #60: Handle Git submodules (thanks @sdboyer) +- #61: Add gometalinter to testing + +## 1.9.0 (2016-11-18) + +### Added + +- #50: Auto-detect remotes with file:// prefix. +- #59: Testing against Go 1.7 + +### Changed + +- Removed auto-detection for Google Code as the service is deprecated +- Added auto-detection of git.openstack.org + +### Fixed + +- #53: Git not fetching tags off branch + +## 1.8.0 (2016-06-29) + +### Added + +- #43: Detect when tool (e.g., git, svn, etc) not installed +- #49: Detect access denied and not found situations + +### Changed + +- #48: Updated Go Report Gard url to new format +- Refactored SVN handling to detect when not in a top level directory +- Updating tagging to v[SemVer] structure for compatibility with other tools. + +### Fixed + +- #45: Fixed hg's update method so that it pulls from remote before updates + +## 1.7.0 (2016-05-05) + +- Adds a glide.yaml file with some limited information. +- Implements #37: Ability to export source as a directory. +- Implements #36: Get current version-ish with Current method. This returns + a branch (if on tip) or equivalent tip, a tag if on a tag, or a revision if + on an individual revision. Note, the tip of branch is VCS specific so usage + may require detecting VCS type. + +## 1.6.1 (2016-04-27) + +- Fixed #30: tags from commit should not have ^{} appended (seen in git) +- Fixed #29: isDetachedHead fails with non-english locales (git) +- Fixed #33: Access denied and not found http errors causing xml parsing errors + +## 1.6.0 (2016-04-18) + +- Issue #26: Added Init method to initialize a repo at the local location + (thanks tony). +- Issue #19: Added method to retrieve tags for a commit. +- Issue #24: Reworked errors returned from common methods. Now differing + VCS implementations return the same errors. The original VCS specific error + is available on the error. See the docs for more details. +- Issue #25: Export the function RunFromDir which runs VCS commands from the + root of the local directory. This is useful for those that want to build and + extend on top of the vcs package (thanks tony). +- Issue #22: Added Ping command to test if remote location is present and + accessible. + +## 1.5.1 (2016-03-23) + +- Fixing bug parsing some Git commit dates. + +## 1.5.0 (2016-03-22) + +- Add Travis CI testing for Go 1.6. +- Issue #17: Add CommitInfo method allowing for a common way to get commit + metadata from all VCS. +- Autodetect types that have git@ or hg@ users. +- Autodetect git+ssh, bzr+ssh, git, and svn+ssh scheme urls. +- On Bitbucket for ssh style URLs retrieve the type from the URL. This allows + for private repo type detection. +- Issue #14: Autodetect ssh/scp style urls (thanks chonthu). + +## 1.4.1 (2016-03-07) + +- Fixes #16: some windows situations are unable to create parent directory. + +## 1.4.0 (2016-02-15) + +- Adding support for IBM JazzHub. + +## 1.3.1 (2016-01-27) + +- Issue #12: Failed to checkout Bzr repo when parent directory didn't + exist (thanks cyrilleverrier). + +## 1.3.0 (2015-11-09) + +- Issue #9: Added Date method to get the date/time of latest commit (thanks kamilchm). + +## 1.2.0 (2015-10-29) + +- Adding IsDirty method to detect a checkout with uncommitted changes. + +## 1.1.4 (2015-10-28) + +- Fixed #8: Git IsReference not detecting branches that have not been checked + out yet. + +## 1.1.3 (2015-10-21) + +- Fixing issue where there are multiple go-import statements for go redirects + +## 1.1.2 (2015-10-20) + +- Fixes #7: hg not checking out code when Get is called + +## 1.1.1 (2015-10-20) + +- Issue #6: Allow VCS commands to be run concurrently. + +## 1.1.0 (2015-10-19) + +- #5: Added output of failed command to returned errors. + +## 1.0.0 (2015-10-06) + +- Initial release. diff --git a/vendor/github.com/Masterminds/vcs/LICENSE.txt b/vendor/github.com/Masterminds/vcs/LICENSE.txt new file mode 100644 index 00000000..0da4aead --- /dev/null +++ b/vendor/github.com/Masterminds/vcs/LICENSE.txt @@ -0,0 +1,20 @@ +The Masterminds +Copyright (C) 2014-2015, Matt Butcher and Matt Farina + +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/Masterminds/vcs/Makefile b/vendor/github.com/Masterminds/vcs/Makefile new file mode 100644 index 00000000..5d722c2f --- /dev/null +++ b/vendor/github.com/Masterminds/vcs/Makefile @@ -0,0 +1,41 @@ +.PHONY: setup +setup: + go get -u gopkg.in/alecthomas/gometalinter.v1 + gometalinter.v1 --install + +.PHONY: test +test: validate lint + @echo "==> Running tests" + go test -v + +.PHONY: validate +validate: +# misspell finds the work adresář (used in bzr.go) as a mispelling of +# address. It finds adres. An issue has been filed at +# https://github.com/client9/misspell/issues/99. In the meantime adding +# adres to the ignore list. + @echo "==> Running static validations" + @gometalinter.v1 \ + --disable-all \ + --linter "misspell:misspell -i adres -j 1 {path}/*.go:PATH:LINE:COL:MESSAGE" \ + --enable deadcode \ + --severity deadcode:error \ + --enable gofmt \ + --enable gosimple \ + --enable ineffassign \ + --enable misspell \ + --enable vet \ + --tests \ + --vendor \ + --deadline 60s \ + ./... || exit_code=1 + +.PHONY: lint +lint: + @echo "==> Running linters" + @gometalinter.v1 \ + --disable-all \ + --enable golint \ + --vendor \ + --deadline 60s \ + ./... || : diff --git a/vendor/github.com/Masterminds/vcs/README.md b/vendor/github.com/Masterminds/vcs/README.md new file mode 100644 index 00000000..a1126851 --- /dev/null +++ b/vendor/github.com/Masterminds/vcs/README.md @@ -0,0 +1,48 @@ +# VCS Repository Management for Go + +Manage repos in varying version control systems with ease through a common +interface. + +[![Build Status](https://travis-ci.org/Masterminds/vcs.svg)](https://travis-ci.org/Masterminds/vcs) [![GoDoc](https://godoc.org/github.com/Masterminds/vcs?status.png)](https://godoc.org/github.com/Masterminds/vcs) [![Go Report Card](https://goreportcard.com/badge/github.com/Masterminds/vcs)](https://goreportcard.com/report/github.com/Masterminds/vcs) +[![Build status](https://ci.appveyor.com/api/projects/status/vg3cjc561q2trobm?svg=true&passingText=windows%20build%20passing&failingText=windows%20build%20failing)](https://ci.appveyor.com/project/mattfarina/vcs) + + +## Quick Usage + +Quick usage: + + remote := "https://github.com/Masterminds/vcs" + local, _ := ioutil.TempDir("", "go-vcs") + repo, err := NewRepo(remote, local) + +In this case `NewRepo` will detect the VCS is Git and return a `GitRepo`. All of +the repos implement the `Repo` interface with a common set of features between +them. + +## Supported VCS + +Git, SVN, Bazaar (Bzr), and Mercurial (Hg) are currently supported. They each +have their own type (e.g., `GitRepo`) that follow a simple naming pattern. Each +type implements the `Repo` interface and has a constructor (e.g., `NewGitRepo`). +The constructors have the same signature as `NewRepo`. + +## Features + +- Clone or checkout a repository depending on the version control system. +- Pull updates to a repository. +- Get the currently checked out commit id. +- Checkout a commit id, branch, or tag (depending on the availability in the VCS). +- Get a list of tags and branches in the VCS. +- Check if a string value is a valid reference within the VCS. +- More... + +For more details see [the documentation](https://godoc.org/github.com/Masterminds/vcs). + +## Motivation + +The package `golang.org/x/tools/go/vcs` provides some valuable functionality +for working with packages in repositories in varying source control management +systems. That package, while useful and well tested, is designed with a specific +purpose in mind. Our uses went beyond the scope of that package. To implement +our scope we built a package that went beyond the functionality and scope +of `golang.org/x/tools/go/vcs`. diff --git a/vendor/github.com/Masterminds/vcs/appveyor.yml b/vendor/github.com/Masterminds/vcs/appveyor.yml new file mode 100644 index 00000000..c0c9170f --- /dev/null +++ b/vendor/github.com/Masterminds/vcs/appveyor.yml @@ -0,0 +1,26 @@ + +version: build-{build}.{branch} + +clone_folder: C:\gopath\src\github.com\Masterminds\vcs +shallow_clone: true + +environment: + GOPATH: C:\gopath + +platform: + - x64 + +install: + - go version + - go env + - choco install -y bzr + - set PATH=C:\Program Files (x86)\Bazaar;%PATH% + - bzr --version + +build_script: + - go install -v ./... + +test_script: + - go test -v + +deploy: off diff --git a/vendor/github.com/Masterminds/vcs/bzr.go b/vendor/github.com/Masterminds/vcs/bzr.go new file mode 100644 index 00000000..8343d3ce --- /dev/null +++ b/vendor/github.com/Masterminds/vcs/bzr.go @@ -0,0 +1,342 @@ +package vcs + +import ( + "fmt" + "net/url" + "os" + "os/exec" + "path/filepath" + "regexp" + "strings" + "time" +) + +var bzrDetectURL = regexp.MustCompile("parent branch: (?P.+)\n") + +// NewBzrRepo creates a new instance of BzrRepo. The remote and local directories +// need to be passed in. +func NewBzrRepo(remote, local string) (*BzrRepo, error) { + ins := depInstalled("bzr") + if !ins { + return nil, NewLocalError("bzr is not installed", nil, "") + } + ltype, err := DetectVcsFromFS(local) + + // Found a VCS other than Bzr. Need to report an error. + if err == nil && ltype != Bzr { + return nil, ErrWrongVCS + } + + r := &BzrRepo{} + r.setRemote(remote) + r.setLocalPath(local) + r.Logger = Logger + + // With the other VCS we can check if the endpoint locally is different + // from the one configured internally. But, with Bzr you can't. For example, + // if you do `bzr branch https://launchpad.net/govcstestbzrrepo` and then + // use `bzr info` to get the parent branch you'll find it set to + // http://bazaar.launchpad.net/~mattfarina/govcstestbzrrepo/trunk/. Notice + // the change from https to http and the path chance. + // Here we set the remote to be the local one if none is passed in. + if err == nil && r.CheckLocal() && remote == "" { + c := exec.Command("bzr", "info") + c.Dir = local + c.Env = envForDir(c.Dir) + out, err := c.CombinedOutput() + if err != nil { + return nil, NewLocalError("Unable to retrieve local repo information", err, string(out)) + } + m := bzrDetectURL.FindStringSubmatch(string(out)) + + // If no remote was passed in but one is configured for the locally + // checked out Bzr repo use that one. + if m[1] != "" { + r.setRemote(m[1]) + } + } + + return r, nil +} + +// BzrRepo implements the Repo interface for the Bzr source control. +type BzrRepo struct { + base +} + +// Vcs retrieves the underlying VCS being implemented. +func (s BzrRepo) Vcs() Type { + return Bzr +} + +// Get is used to perform an initial clone of a repository. +func (s *BzrRepo) Get() error { + + basePath := filepath.Dir(filepath.FromSlash(s.LocalPath())) + if _, err := os.Stat(basePath); os.IsNotExist(err) { + err = os.MkdirAll(basePath, 0755) + if err != nil { + return NewLocalError("Unable to create directory", err, "") + } + } + + out, err := s.run("bzr", "branch", s.Remote(), s.LocalPath()) + if err != nil { + return NewRemoteError("Unable to get repository", err, string(out)) + } + + return nil +} + +// Init initializes a bazaar repository at local location. +func (s *BzrRepo) Init() error { + out, err := s.run("bzr", "init", s.LocalPath()) + + // There are some windows cases where bazaar cannot create the parent + // directory if it does not already exist, to the location it's trying + // to create the repo. Catch that error and try to handle it. + if err != nil && s.isUnableToCreateDir(err) { + + basePath := filepath.Dir(filepath.FromSlash(s.LocalPath())) + if _, err := os.Stat(basePath); os.IsNotExist(err) { + err = os.MkdirAll(basePath, 0755) + if err != nil { + return NewLocalError("Unable to initialize repository", err, "") + } + + out, err = s.run("bzr", "init", s.LocalPath()) + if err != nil { + return NewLocalError("Unable to initialize repository", err, string(out)) + } + return nil + } + + } else if err != nil { + return NewLocalError("Unable to initialize repository", err, string(out)) + } + + return nil +} + +// Update performs a Bzr pull and update to an existing checkout. +func (s *BzrRepo) Update() error { + out, err := s.RunFromDir("bzr", "pull") + if err != nil { + return NewRemoteError("Unable to update repository", err, string(out)) + } + out, err = s.RunFromDir("bzr", "update") + if err != nil { + return NewRemoteError("Unable to update repository", err, string(out)) + } + return nil +} + +// UpdateVersion sets the version of a package currently checked out via Bzr. +func (s *BzrRepo) UpdateVersion(version string) error { + out, err := s.RunFromDir("bzr", "update", "-r", version) + if err != nil { + return NewLocalError("Unable to update checked out version", err, string(out)) + } + return nil +} + +// Version retrieves the current version. +func (s *BzrRepo) Version() (string, error) { + + out, err := s.RunFromDir("bzr", "revno", "--tree") + if err != nil { + return "", NewLocalError("Unable to retrieve checked out version", err, string(out)) + } + + return strings.TrimSpace(string(out)), nil +} + +// Current returns the current version-ish. This means: +// * -1 if on the tip of the branch (this is the Bzr value for HEAD) +// * A tag if on a tag +// * Otherwise a revision +func (s *BzrRepo) Current() (string, error) { + tip, err := s.CommitInfo("-1") + if err != nil { + return "", err + } + + curr, err := s.Version() + if err != nil { + return "", err + } + + if tip.Commit == curr { + return "-1", nil + } + + ts, err := s.TagsFromCommit(curr) + if err != nil { + return "", err + } + if len(ts) > 0 { + return ts[0], nil + } + + return curr, nil +} + +// Date retrieves the date on the latest commit. +func (s *BzrRepo) Date() (time.Time, error) { + out, err := s.RunFromDir("bzr", "version-info", "--custom", "--template={date}") + if err != nil { + return time.Time{}, NewLocalError("Unable to retrieve revision date", err, string(out)) + } + t, err := time.Parse(longForm, string(out)) + if err != nil { + return time.Time{}, NewLocalError("Unable to retrieve revision date", err, string(out)) + } + return t, nil +} + +// CheckLocal verifies the local location is a Bzr repo. +func (s *BzrRepo) CheckLocal() bool { + if _, err := os.Stat(s.LocalPath() + "/.bzr"); err == nil { + return true + } + + return false +} + +// Branches returns a list of available branches on the repository. +// In Bazaar (Bzr) clones and branches are the same. A different branch will +// have a different URL location which we cannot detect from the repo. This +// is a little different from other VCS. +func (s *BzrRepo) Branches() ([]string, error) { + var branches []string + return branches, nil +} + +// Tags returns a list of available tags on the repository. +func (s *BzrRepo) Tags() ([]string, error) { + out, err := s.RunFromDir("bzr", "tags") + if err != nil { + return []string{}, NewLocalError("Unable to retrieve tags", err, string(out)) + } + tags := s.referenceList(string(out), `(?m-s)^(\S+)`) + return tags, nil +} + +// IsReference returns if a string is a reference. A reference can be a +// commit id or tag. +func (s *BzrRepo) IsReference(r string) bool { + _, err := s.RunFromDir("bzr", "revno", "-r", r) + return err == nil +} + +// IsDirty returns if the checkout has been modified from the checked +// out reference. +func (s *BzrRepo) IsDirty() bool { + out, err := s.RunFromDir("bzr", "diff") + return err != nil || len(out) != 0 +} + +// CommitInfo retrieves metadata about a commit. +func (s *BzrRepo) CommitInfo(id string) (*CommitInfo, error) { + r := "-r" + id + out, err := s.RunFromDir("bzr", "log", r, "--log-format=long") + if err != nil { + return nil, ErrRevisionUnavailable + } + + ci := &CommitInfo{} + lines := strings.Split(string(out), "\n") + const format = "Mon 2006-01-02 15:04:05 -0700" + var track int + var trackOn bool + + // Note, bzr does not appear to use i18m. + for i, l := range lines { + if strings.HasPrefix(l, "revno:") { + ci.Commit = strings.TrimSpace(strings.TrimPrefix(l, "revno:")) + } else if strings.HasPrefix(l, "committer:") { + ci.Author = strings.TrimSpace(strings.TrimPrefix(l, "committer:")) + } else if strings.HasPrefix(l, "timestamp:") { + ts := strings.TrimSpace(strings.TrimPrefix(l, "timestamp:")) + ci.Date, err = time.Parse(format, ts) + if err != nil { + return nil, NewLocalError("Unable to retrieve commit information", err, string(out)) + } + } else if strings.TrimSpace(l) == "message:" { + track = i + trackOn = true + } else if trackOn && i > track { + ci.Message = ci.Message + l + } + } + ci.Message = strings.TrimSpace(ci.Message) + + // Didn't find the revision + if ci.Author == "" { + return nil, ErrRevisionUnavailable + } + + return ci, nil +} + +// TagsFromCommit retrieves tags from a commit id. +func (s *BzrRepo) TagsFromCommit(id string) ([]string, error) { + out, err := s.RunFromDir("bzr", "tags", "-r", id) + if err != nil { + return []string{}, NewLocalError("Unable to retrieve tags", err, string(out)) + } + + tags := s.referenceList(string(out), `(?m-s)^(\S+)`) + return tags, nil +} + +// Ping returns if remote location is accessible. +func (s *BzrRepo) Ping() bool { + + // Running bzr info is slow. Many of the projects are on launchpad which + // has a public 1.0 API we can use. + u, err := url.Parse(s.Remote()) + if err == nil { + if u.Host == "launchpad.net" { + try := strings.TrimPrefix(u.Path, "/") + + // get returns the body and an err. If the status code is not a 200 + // an error is returned. Launchpad returns a 404 for a codebase that + // does not exist. Otherwise it returns a JSON object describing it. + _, er := get("https://api.launchpad.net/1.0/" + try) + return er == nil + } + } + + // This is the same command that Go itself uses but it's not fast (or fast + // enough by my standards). A faster method would be useful. + _, err = s.run("bzr", "info", s.Remote()) + return err == nil +} + +// ExportDir exports the current revision to the passed in directory. +func (s *BzrRepo) ExportDir(dir string) error { + out, err := s.RunFromDir("bzr", "export", dir) + s.log(out) + if err != nil { + return NewLocalError("Unable to export source", err, string(out)) + } + + return nil +} + +// Multi-lingual manner check for the VCS error that it couldn't create directory. +// https://bazaar.launchpad.net/~bzr-pqm/bzr/bzr.dev/files/head:/po/ +func (s *BzrRepo) isUnableToCreateDir(err error) bool { + msg := err.Error() + + if strings.HasPrefix(msg, fmt.Sprintf("Parent directory of %s does not exist.", s.LocalPath())) || + strings.HasPrefix(msg, fmt.Sprintf("Nadřazený adresář %s neexistuje.", s.LocalPath())) || + strings.HasPrefix(msg, fmt.Sprintf("El directorio padre de %s no existe.", s.LocalPath())) || + strings.HasPrefix(msg, fmt.Sprintf("%s の親ディレクトリがありません。", s.LocalPath())) || + strings.HasPrefix(msg, fmt.Sprintf("Родительская директория для %s не существует.", s.LocalPath())) { + return true + } + + return false +} diff --git a/vendor/github.com/Masterminds/vcs/bzr_test.go b/vendor/github.com/Masterminds/vcs/bzr_test.go new file mode 100644 index 00000000..4b2e50ec --- /dev/null +++ b/vendor/github.com/Masterminds/vcs/bzr_test.go @@ -0,0 +1,328 @@ +package vcs + +import ( + "io/ioutil" + "path/filepath" + "time" + //"log" + "os" + "testing" +) + +// Canary test to ensure BzrRepo implements the Repo interface. +var _ Repo = &BzrRepo{} + +// To verify bzr is working we perform integration testing +// with a known bzr service. Due to the long time of repeatedly checking out +// repos these tests are structured to work together. + +func TestBzr(t *testing.T) { + + tempDir, err := ioutil.TempDir("", "go-vcs-bzr-tests") + if err != nil { + t.Error(err) + } + defer func() { + err = os.RemoveAll(tempDir) + if err != nil { + t.Error(err) + } + }() + + repo, err := NewBzrRepo("https://launchpad.net/govcstestbzrrepo", tempDir+"/govcstestbzrrepo") + if err != nil { + t.Fatal(err) + } + + if repo.Vcs() != Bzr { + t.Error("Bzr is detecting the wrong type") + } + + // Check the basic getters. + if repo.Remote() != "https://launchpad.net/govcstestbzrrepo" { + t.Error("Remote not set properly") + } + if repo.LocalPath() != tempDir+"/govcstestbzrrepo" { + t.Error("Local disk location not set properly") + } + + //Logger = log.New(os.Stdout, "", log.LstdFlags) + + // Do an initial clone. + err = repo.Get() + if err != nil { + t.Errorf("Unable to clone Bzr repo. Err was %s", err) + } + + // Verify Bzr repo is a Bzr repo + if !repo.CheckLocal() { + t.Error("Problem checking out repo or Bzr CheckLocal is not working") + } + + // Test internal lookup mechanism used outside of Bzr specific functionality. + ltype, err := DetectVcsFromFS(tempDir + "/govcstestbzrrepo") + if err != nil { + t.Error("detectVcsFromFS unable to Bzr repo") + } + if ltype != Bzr { + t.Errorf("detectVcsFromFS detected %s instead of Bzr type", ltype) + } + + // Test NewRepo on existing checkout. This should simply provide a working + // instance without error based on looking at the local directory. + nrepo, nrerr := NewRepo("https://launchpad.net/govcstestbzrrepo", tempDir+"/govcstestbzrrepo") + if nrerr != nil { + t.Error(nrerr) + } + // Verify the right oject is returned. It will check the local repo type. + if !nrepo.CheckLocal() { + t.Error("Wrong version returned from NewRepo") + } + + v, err := repo.Current() + if err != nil { + t.Errorf("Error trying Bzr Current: %s", err) + } + if v != "-1" { + t.Errorf("Current failed to detect Bzr on tip of branch. Got version: %s", v) + } + + err = repo.UpdateVersion("2") + if err != nil { + t.Errorf("Unable to update Bzr repo version. Err was %s", err) + } + + // Use Version to verify we are on the right version. + v, err = repo.Version() + if v != "2" { + t.Error("Error checking checked out Bzr version") + } + if err != nil { + t.Error(err) + } + + v, err = repo.Current() + if err != nil { + t.Errorf("Error trying Bzr Current: %s", err) + } + if v != "2" { + t.Errorf("Current failed to detect Bzr on rev 2 of branch. Got version: %s", v) + } + + // Use Date to verify we are on the right commit. + d, err := repo.Date() + if d.Format(longForm) != "2015-07-31 09:50:42 -0400" { + t.Error("Error checking checked out Bzr commit date") + } + if err != nil { + t.Error(err) + } + + // Perform an update. + err = repo.Update() + if err != nil { + t.Error(err) + } + + v, err = repo.Version() + if v != "3" { + t.Error("Error checking checked out Bzr version") + } + if err != nil { + t.Error(err) + } + + tags, err := repo.Tags() + if err != nil { + t.Error(err) + } + if tags[0] != "1.0.0" { + t.Error("Bzr tags is not reporting the correct version") + } + + tags, err = repo.TagsFromCommit("2") + if err != nil { + t.Error(err) + } + if len(tags) != 0 { + t.Error("Bzr is incorrectly returning tags for a commit") + } + + tags, err = repo.TagsFromCommit("3") + if err != nil { + t.Error(err) + } + if len(tags) != 1 || tags[0] != "1.0.0" { + t.Error("Bzr is incorrectly returning tags for a commit") + } + + branches, err := repo.Branches() + if err != nil { + t.Error(err) + } + if len(branches) != 0 { + t.Error("Bzr is incorrectly returning branches") + } + + if !repo.IsReference("1.0.0") { + t.Error("Bzr is reporting a reference is not one") + } + + if repo.IsReference("foo") { + t.Error("Bzr is reporting a non-existent reference is one") + } + + if repo.IsDirty() { + t.Error("Bzr incorrectly reporting dirty") + } + + ci, err := repo.CommitInfo("3") + if err != nil { + t.Error(err) + } + if ci.Commit != "3" { + t.Error("Bzr.CommitInfo wrong commit id") + } + if ci.Author != "Matt Farina " { + t.Error("Bzr.CommitInfo wrong author") + } + if ci.Message != "Updated Readme with pointer." { + t.Error("Bzr.CommitInfo wrong message") + } + ti, err := time.Parse(time.RFC1123Z, "Fri, 31 Jul 2015 09:51:37 -0400") + if err != nil { + t.Error(err) + } + if !ti.Equal(ci.Date) { + t.Error("Bzr.CommitInfo wrong date") + } + + _, err = repo.CommitInfo("asdfasdfasdf") + if err != ErrRevisionUnavailable { + t.Error("Bzr didn't return expected ErrRevisionUnavailable") + } + + tempDir2, err := ioutil.TempDir("", "go-vcs-bzr-tests-export") + if err != nil { + t.Fatalf("Error creating temp directory: %s", err) + } + defer func() { + err = os.RemoveAll(tempDir2) + if err != nil { + t.Error(err) + } + }() + + exportDir := filepath.Join(tempDir2, "src") + + err = repo.ExportDir(exportDir) + if err != nil { + t.Errorf("Unable to export Bzr repo. Err was %s", err) + } + + _, err = os.Stat(filepath.Join(exportDir, "Readme.md")) + if err != nil { + t.Errorf("Error checking exported file in Bzr: %s", err) + } + + _, err = os.Stat(filepath.Join(exportDir, string(repo.Vcs()))) + if err != nil { + if found := os.IsNotExist(err); !found { + t.Errorf("Error checking exported metadata in Bzr: %s", err) + } + } else { + t.Error("Error checking Bzr metadata. It exists.") + } +} + +func TestBzrCheckLocal(t *testing.T) { + // Verify repo.CheckLocal fails for non-Bzr directories. + // TestBzr is already checking on a valid repo + tempDir, err := ioutil.TempDir("", "go-vcs-bzr-tests") + if err != nil { + t.Error(err) + } + defer func() { + err = os.RemoveAll(tempDir) + if err != nil { + t.Error(err) + } + }() + + repo, _ := NewBzrRepo("", tempDir) + if repo.CheckLocal() { + t.Error("Bzr CheckLocal does not identify non-Bzr location") + } + + // Test NewRepo when there's no local. This should simply provide a working + // instance without error based on looking at the remote localtion. + _, nrerr := NewRepo("https://launchpad.net/govcstestbzrrepo", tempDir+"/govcstestbzrrepo") + if nrerr != nil { + t.Error(nrerr) + } +} + +func TestBzrPing(t *testing.T) { + tempDir, err := ioutil.TempDir("", "go-vcs-bzr-tests") + if err != nil { + t.Error(err) + } + defer func() { + err = os.RemoveAll(tempDir) + if err != nil { + t.Error(err) + } + }() + + repo, err := NewBzrRepo("https://launchpad.net/govcstestbzrrepo", tempDir) + if err != nil { + t.Error(err) + } + + ping := repo.Ping() + if !ping { + t.Error("Bzr unable to ping working repo") + } + + repo, err = NewBzrRepo("https://launchpad.net/ihopethisneverexistsbecauseitshouldnt", tempDir) + if err != nil { + t.Error(err) + } + + ping = repo.Ping() + if ping { + t.Error("Bzr got a ping response from when it should not have") + } +} + +func TestBzrInit(t *testing.T) { + tempDir, err := ioutil.TempDir("", "go-vcs-bzr-tests") + repoDir := tempDir + "/repo" + if err != nil { + t.Error(err) + } + defer func() { + err = os.RemoveAll(tempDir) + if err != nil { + t.Error(err) + } + }() + + repo, err := NewBzrRepo(repoDir, repoDir) + if err != nil { + t.Error(err) + } + + err = repo.Init() + if err != nil { + t.Error(err) + } + + v, err := repo.Version() + if err != nil { + t.Error(err) + } + if v != "0" { + t.Errorf("Bzr Init returns wrong version: %s", v) + } +} diff --git a/vendor/github.com/Masterminds/vcs/errors.go b/vendor/github.com/Masterminds/vcs/errors.go new file mode 100644 index 00000000..b1eb464f --- /dev/null +++ b/vendor/github.com/Masterminds/vcs/errors.go @@ -0,0 +1,114 @@ +package vcs + +import ( + "errors" + "fmt" +) + +// The vcs package provides ways to work with errors that hide the underlying +// implementation details but make them accessible if needed. For basic errors +// that do not have underlying implementation specific details or the underlying +// details are not necessary there are errors for comparison. +// +// For example: +// +// ci, err := repo.CommitInfo("123") +// if err == vcs.ErrRevisionUnavailable { +// // The commit id was not available in the VCS. +// } +// +// There are other times where getting the details are more useful. For example, +// if you're performing a repo.Get() and an error occurs. In general you'll want +// to consistently know it failed. But, you may want to know the underlying +// details (opt-in) to them. For those cases there is a different form of error +// handling. +// +// For example: +// +// err := repo.Get() +// if err != nil { +// // A RemoteError was returned. This has access to the output of the +// // vcs command, original error, and has a consistent cross vcs message. +// } +// +// The errors returned here can be used in type switches to detect the underlying +// error. For example: +// +// switch err.(type) { +// case *vcs.RemoteError: +// // This an error connecting to a remote system. +// } +// +// For more information on using type switches to detect error types you can +// read the Go wiki at https://github.com/golang/go/wiki/Errors + +var ( + // ErrWrongVCS is returned when an action is tried on the wrong VCS. + ErrWrongVCS = errors.New("Wrong VCS detected") + + // ErrCannotDetectVCS is returned when VCS cannot be detected from URI string. + ErrCannotDetectVCS = errors.New("Cannot detect VCS") + + // ErrWrongRemote occurs when the passed in remote does not match the VCS + // configured endpoint. + ErrWrongRemote = errors.New("The Remote does not match the VCS endpoint") + + // ErrRevisionUnavailable happens when commit revision information is + // unavailable. + ErrRevisionUnavailable = errors.New("Revision unavailable") +) + +// RemoteError is returned when an operation fails against a remote repo +type RemoteError struct { + vcsError +} + +// NewRemoteError constructs a RemoteError +func NewRemoteError(msg string, err error, out string) error { + e := &RemoteError{} + e.s = msg + e.e = err + e.o = out + + return e +} + +// LocalError is returned when a local operation has an error +type LocalError struct { + vcsError +} + +// NewLocalError constructs a LocalError +func NewLocalError(msg string, err error, out string) error { + e := &LocalError{} + e.s = msg + e.e = err + e.o = out + + return e +} + +type vcsError struct { + s string + e error // The original error + o string // The output from executing the command +} + +// Error implements the Error interface +func (e *vcsError) Error() string { + if e.e == nil { + return e.s + } + + return fmt.Sprintf("%s: %v", e.s, e.e) +} + +// Original retrieves the underlying implementation specific error. +func (e *vcsError) Original() error { + return e.e +} + +// Out retrieves the output of the original command that was run. +func (e *vcsError) Out() string { + return e.o +} diff --git a/vendor/github.com/Masterminds/vcs/errors_test.go b/vendor/github.com/Masterminds/vcs/errors_test.go new file mode 100644 index 00000000..2effd7cc --- /dev/null +++ b/vendor/github.com/Masterminds/vcs/errors_test.go @@ -0,0 +1,36 @@ +package vcs + +import ( + "errors" + "testing" +) + +func TestNewRemoteError(t *testing.T) { + base := errors.New("Foo error") + out := "This is a test" + msg := "remote error msg" + + e := NewRemoteError(msg, base, out) + + switch e.(type) { + case *RemoteError: + // This is the right error type + default: + t.Error("Wrong error type returned from NewRemoteError") + } +} + +func TestNewLocalError(t *testing.T) { + base := errors.New("Foo error") + out := "This is a test" + msg := "local error msg" + + e := NewLocalError(msg, base, out) + + switch e.(type) { + case *LocalError: + // This is the right error type + default: + t.Error("Wrong error type returned from NewLocalError") + } +} diff --git a/vendor/github.com/Masterminds/vcs/git.go b/vendor/github.com/Masterminds/vcs/git.go new file mode 100644 index 00000000..4094e0d0 --- /dev/null +++ b/vendor/github.com/Masterminds/vcs/git.go @@ -0,0 +1,457 @@ +package vcs + +import ( + "bytes" + "encoding/xml" + "io/ioutil" + "os" + "os/exec" + "path/filepath" + "runtime" + "strings" + "time" +) + +// NewGitRepo creates a new instance of GitRepo. The remote and local directories +// need to be passed in. +func NewGitRepo(remote, local string) (*GitRepo, error) { + ins := depInstalled("git") + if !ins { + return nil, NewLocalError("git is not installed", nil, "") + } + ltype, err := DetectVcsFromFS(local) + + // Found a VCS other than Git. Need to report an error. + if err == nil && ltype != Git { + return nil, ErrWrongVCS + } + + r := &GitRepo{} + r.setRemote(remote) + r.setLocalPath(local) + r.RemoteLocation = "origin" + r.Logger = Logger + + // Make sure the local Git repo is configured the same as the remote when + // A remote value was passed in. + if err == nil && r.CheckLocal() { + c := exec.Command("git", "config", "--get", "remote.origin.url") + c.Dir = local + c.Env = envForDir(c.Dir) + out, err := c.CombinedOutput() + if err != nil { + return nil, NewLocalError("Unable to retrieve local repo information", err, string(out)) + } + + localRemote := strings.TrimSpace(string(out)) + if remote != "" && localRemote != remote { + return nil, ErrWrongRemote + } + + // If no remote was passed in but one is configured for the locally + // checked out Git repo use that one. + if remote == "" && localRemote != "" { + r.setRemote(localRemote) + } + } + + return r, nil +} + +// GitRepo implements the Repo interface for the Git source control. +type GitRepo struct { + base + RemoteLocation string +} + +// Vcs retrieves the underlying VCS being implemented. +func (s GitRepo) Vcs() Type { + return Git +} + +// Get is used to perform an initial clone of a repository. +func (s *GitRepo) Get() error { + out, err := s.run("git", "clone", "--recursive", s.Remote(), s.LocalPath()) + + // There are some windows cases where Git cannot create the parent directory, + // if it does not already exist, to the location it's trying to create the + // repo. Catch that error and try to handle it. + if err != nil && s.isUnableToCreateDir(err) { + + basePath := filepath.Dir(filepath.FromSlash(s.LocalPath())) + if _, err := os.Stat(basePath); os.IsNotExist(err) { + err = os.MkdirAll(basePath, 0755) + if err != nil { + return NewLocalError("Unable to create directory", err, "") + } + + out, err = s.run("git", "clone", s.Remote(), s.LocalPath()) + if err != nil { + return NewRemoteError("Unable to get repository", err, string(out)) + } + return err + } + + } else if err != nil { + return NewRemoteError("Unable to get repository", err, string(out)) + } + + return nil +} + +// Init initializes a git repository at local location. +func (s *GitRepo) Init() error { + out, err := s.run("git", "init", s.LocalPath()) + + // There are some windows cases where Git cannot create the parent directory, + // if it does not already exist, to the location it's trying to create the + // repo. Catch that error and try to handle it. + if err != nil && s.isUnableToCreateDir(err) { + + basePath := filepath.Dir(filepath.FromSlash(s.LocalPath())) + if _, err := os.Stat(basePath); os.IsNotExist(err) { + err = os.MkdirAll(basePath, 0755) + if err != nil { + return NewLocalError("Unable to initialize repository", err, "") + } + + out, err = s.run("git", "init", s.LocalPath()) + if err != nil { + return NewLocalError("Unable to initialize repository", err, string(out)) + } + return nil + } + + } else if err != nil { + return NewLocalError("Unable to initialize repository", err, string(out)) + } + + return nil +} + +// Update performs an Git fetch and pull to an existing checkout. +func (s *GitRepo) Update() error { + // Perform a fetch to make sure everything is up to date. + out, err := s.RunFromDir("git", "fetch", "--tags", s.RemoteLocation) + if err != nil { + return NewRemoteError("Unable to update repository", err, string(out)) + } + + // When in a detached head state, such as when an individual commit is checked + // out do not attempt a pull. It will cause an error. + detached, err := isDetachedHead(s.LocalPath()) + if err != nil { + return NewLocalError("Unable to update repository", err, "") + } + + if detached { + return nil + } + + out, err = s.RunFromDir("git", "pull") + if err != nil { + return NewRemoteError("Unable to update repository", err, string(out)) + } + + return s.defendAgainstSubmodules() +} + +// UpdateVersion sets the version of a package currently checked out via Git. +func (s *GitRepo) UpdateVersion(version string) error { + out, err := s.RunFromDir("git", "checkout", version) + if err != nil { + return NewLocalError("Unable to update checked out version", err, string(out)) + } + + return s.defendAgainstSubmodules() +} + +// defendAgainstSubmodules tries to keep repo state sane in the event of +// submodules. Or nested submodules. What a great idea, submodules. +func (s *GitRepo) defendAgainstSubmodules() error { + // First, update them to whatever they should be, if there should happen to be any. + out, err := s.RunFromDir("git", "submodule", "update", "--init", "--recursive") + if err != nil { + return NewLocalError("Unexpected error while defensively updating submodules", err, string(out)) + } + // Now, do a special extra-aggressive clean in case changing versions caused + // one or more submodules to go away. + out, err = s.RunFromDir("git", "clean", "-x", "-d", "-f", "-f") + if err != nil { + return NewLocalError("Unexpected error while defensively cleaning up after possible derelict submodule directories", err, string(out)) + } + // Then, repeat just in case there are any nested submodules that went away. + out, err = s.RunFromDir("git", "submodule", "foreach", "--recursive", "git", "clean", "-x", "-d", "-f", "-f") + if err != nil { + return NewLocalError("Unexpected error while defensively cleaning up after possible derelict nested submodule directories", err, string(out)) + } + + return nil +} + +// Version retrieves the current version. +func (s *GitRepo) Version() (string, error) { + out, err := s.RunFromDir("git", "rev-parse", "HEAD") + if err != nil { + return "", NewLocalError("Unable to retrieve checked out version", err, string(out)) + } + + return strings.TrimSpace(string(out)), nil +} + +// Current returns the current version-ish. This means: +// * Branch name if on the tip of the branch +// * Tag if on a tag +// * Otherwise a revision id +func (s *GitRepo) Current() (string, error) { + out, err := s.RunFromDir("git", "symbolic-ref", "HEAD") + if err == nil { + o := bytes.TrimSpace(bytes.TrimPrefix(out, []byte("refs/heads/"))) + return string(o), nil + } + + v, err := s.Version() + if err != nil { + return "", err + } + + ts, err := s.TagsFromCommit(v) + if err != nil { + return "", err + } + + if len(ts) > 0 { + return ts[0], nil + } + + return v, nil +} + +// Date retrieves the date on the latest commit. +func (s *GitRepo) Date() (time.Time, error) { + out, err := s.RunFromDir("git", "log", "-1", "--date=iso", "--pretty=format:%cd") + if err != nil { + return time.Time{}, NewLocalError("Unable to retrieve revision date", err, string(out)) + } + t, err := time.Parse(longForm, string(out)) + if err != nil { + return time.Time{}, NewLocalError("Unable to retrieve revision date", err, string(out)) + } + return t, nil +} + +// Branches returns a list of available branches on the RemoteLocation +func (s *GitRepo) Branches() ([]string, error) { + out, err := s.RunFromDir("git", "show-ref") + if err != nil { + return []string{}, NewLocalError("Unable to retrieve branches", err, string(out)) + } + branches := s.referenceList(string(out), `(?m-s)(?:`+s.RemoteLocation+`)/(\S+)$`) + return branches, nil +} + +// Tags returns a list of available tags on the RemoteLocation +func (s *GitRepo) Tags() ([]string, error) { + out, err := s.RunFromDir("git", "show-ref") + if err != nil { + return []string{}, NewLocalError("Unable to retrieve tags", err, string(out)) + } + tags := s.referenceList(string(out), `(?m-s)(?:tags)/(\S+)$`) + return tags, nil +} + +// CheckLocal verifies the local location is a Git repo. +func (s *GitRepo) CheckLocal() bool { + if _, err := os.Stat(s.LocalPath() + "/.git"); err == nil { + return true + } + + return false +} + +// IsReference returns if a string is a reference. A reference can be a +// commit id, branch, or tag. +func (s *GitRepo) IsReference(r string) bool { + _, err := s.RunFromDir("git", "rev-parse", "--verify", r) + if err == nil { + return true + } + + // Some refs will fail rev-parse. For example, a remote branch that has + // not been checked out yet. This next step should pickup the other + // possible references. + _, err = s.RunFromDir("git", "show-ref", r) + return err == nil +} + +// IsDirty returns if the checkout has been modified from the checked +// out reference. +func (s *GitRepo) IsDirty() bool { + out, err := s.RunFromDir("git", "diff") + return err != nil || len(out) != 0 +} + +// CommitInfo retrieves metadata about a commit. +func (s *GitRepo) CommitInfo(id string) (*CommitInfo, error) { + fm := `--pretty=format:"%H%an <%ae>%aD%s"` + out, err := s.RunFromDir("git", "log", id, fm, "-1") + if err != nil { + return nil, ErrRevisionUnavailable + } + + cis := struct { + Commit string `xml:"commit"` + Author string `xml:"author"` + Date string `xml:"date"` + Message string `xml:"message"` + }{} + err = xml.Unmarshal(out, &cis) + if err != nil { + return nil, NewLocalError("Unable to retrieve commit information", err, string(out)) + } + + t, err := time.Parse("Mon, _2 Jan 2006 15:04:05 -0700", cis.Date) + if err != nil { + return nil, NewLocalError("Unable to retrieve commit information", err, string(out)) + } + + ci := &CommitInfo{ + Commit: cis.Commit, + Author: cis.Author, + Date: t, + Message: cis.Message, + } + + return ci, nil +} + +// TagsFromCommit retrieves tags from a commit id. +func (s *GitRepo) TagsFromCommit(id string) ([]string, error) { + // This is imperfect and a better method would be great. + + var re []string + + out, err := s.RunFromDir("git", "show-ref", "-d") + if err != nil { + return []string{}, NewLocalError("Unable to retrieve tags", err, string(out)) + } + + lines := strings.Split(string(out), "\n") + var list []string + for _, i := range lines { + if strings.HasPrefix(strings.TrimSpace(i), id) { + list = append(list, i) + } + } + tags := s.referenceList(strings.Join(list, "\n"), `(?m-s)(?:tags)/(\S+)$`) + for _, t := range tags { + // Dereferenced tags have ^{} appended to them. + re = append(re, strings.TrimSuffix(t, "^{}")) + } + + return re, nil +} + +// Ping returns if remote location is accessible. +func (s *GitRepo) Ping() bool { + c := exec.Command("git", "ls-remote", s.Remote()) + + // If prompted for a username and password, which GitHub does for all things + // not public, it's considered not available. To make it available the + // remote needs to be different. + c.Env = mergeEnvLists([]string{"GIT_TERMINAL_PROMPT=0"}, os.Environ()) + _, err := c.CombinedOutput() + return err == nil +} + +// EscapePathSeparator escapes the path separator by replacing it with several. +// Note: this is harmless on Unix, and needed on Windows. +func EscapePathSeparator(path string) (string) { + switch runtime.GOOS { + case `windows`: + // On Windows, triple all path separators. + // Needed to escape backslash(s) preceding doublequotes, + // because of how Windows strings treats backslash+doublequote combo, + // and Go seems to be implicitly passing around a doublequoted string on Windows, + // so we cannnot use default string instead. + // See: https://blogs.msdn.microsoft.com/twistylittlepassagesallalike/2011/04/23/everyone-quotes-command-line-arguments-the-wrong-way/ + // e.g., C:\foo\bar\ -> C:\\\foo\\\bar\\\ + // used with --prefix, like this: --prefix=C:\foo\bar\ -> --prefix=C:\\\foo\\\bar\\\ + return strings.Replace(path, + string(os.PathSeparator), + string(os.PathSeparator) + string(os.PathSeparator) + string(os.PathSeparator), + -1) + default: + return path + } +} + +// ExportDir exports the current revision to the passed in directory. +func (s *GitRepo) ExportDir(dir string) error { + + var path string + + // Without the trailing / there can be problems. + if !strings.HasSuffix(dir, string(os.PathSeparator)) { + dir = dir + string(os.PathSeparator) + } + + // checkout-index on some systems, such as some Windows cases, does not + // create the parent directory to export into if it does not exist. Explicitly + // creating it. + err := os.MkdirAll(dir, 0755) + if err != nil { + return NewLocalError("Unable to create directory", err, "") + } + + path = EscapePathSeparator( dir ) + out, err := s.RunFromDir("git", "checkout-index", "-f", "-a", "--prefix="+path) + s.log(out) + if err != nil { + return NewLocalError("Unable to export source", err, string(out)) + } + + // and now, the horror of submodules + path = EscapePathSeparator( dir + "$path" + string(os.PathSeparator) ) + out, err = s.RunFromDir("git", "submodule", "foreach", "--recursive", "git checkout-index -f -a --prefix="+path) + s.log(out) + if err != nil { + return NewLocalError("Error while exporting submodule sources", err, string(out)) + } + + return nil +} + +// isDetachedHead will detect if git repo is in "detached head" state. +func isDetachedHead(dir string) (bool, error) { + p := filepath.Join(dir, ".git", "HEAD") + contents, err := ioutil.ReadFile(p) + if err != nil { + return false, err + } + + contents = bytes.TrimSpace(contents) + if bytes.HasPrefix(contents, []byte("ref: ")) { + return false, nil + } + + return true, nil +} + +// isUnableToCreateDir checks for an error in Init() to see if an error +// where the parent directory of the VCS local path doesn't exist. This is +// done in a multi-lingual manner. +func (s *GitRepo) isUnableToCreateDir(err error) bool { + msg := err.Error() + if strings.HasPrefix(msg, "could not create work tree dir") || + strings.HasPrefix(msg, "不能创建工作区目录") || + strings.HasPrefix(msg, "no s'ha pogut crear el directori d'arbre de treball") || + strings.HasPrefix(msg, "impossible de créer le répertoire de la copie de travail") || + strings.HasPrefix(msg, "kunde inte skapa arbetskatalogen") || + (strings.HasPrefix(msg, "Konnte Arbeitsverzeichnis") && strings.Contains(msg, "nicht erstellen")) || + (strings.HasPrefix(msg, "작업 디렉터리를") && strings.Contains(msg, "만들 수 없습니다")) { + return true + } + + return false +} diff --git a/vendor/github.com/Masterminds/vcs/git_test.go b/vendor/github.com/Masterminds/vcs/git_test.go new file mode 100644 index 00000000..b58c2c2e --- /dev/null +++ b/vendor/github.com/Masterminds/vcs/git_test.go @@ -0,0 +1,599 @@ +package vcs + +import ( + "fmt" + "io/ioutil" + "path/filepath" + "time" + //"log" + "os" + "testing" +) + +// Canary test to ensure GitRepo implements the Repo interface. +var _ Repo = &GitRepo{} + +// To verify git is working we perform integration testing +// with a known git service. + +func TestGit(t *testing.T) { + tempDir, err := ioutil.TempDir("", "go-vcs-git-tests") + if err != nil { + t.Error(err) + } + defer func() { + err = os.RemoveAll(tempDir) + if err != nil { + t.Error(err) + } + }() + + repo, err := NewGitRepo("https://github.com/Masterminds/VCSTestRepo", tempDir+"/VCSTestRepo") + if err != nil { + t.Error(err) + } + + if repo.Vcs() != Git { + t.Error("Git is detecting the wrong type") + } + + // Check the basic getters. + if repo.Remote() != "https://github.com/Masterminds/VCSTestRepo" { + t.Error("Remote not set properly") + } + if repo.LocalPath() != tempDir+"/VCSTestRepo" { + t.Error("Local disk location not set properly") + } + + //Logger = log.New(os.Stdout, "", log.LstdFlags) + + // Do an initial clone. + err = repo.Get() + if err != nil { + t.Errorf("Unable to clone Git repo. Err was %s", err) + } + + // Verify Git repo is a Git repo + if !repo.CheckLocal() { + t.Error("Problem checking out repo or Git CheckLocal is not working") + } + + // Test internal lookup mechanism used outside of Git specific functionality. + ltype, err := DetectVcsFromFS(tempDir + "/VCSTestRepo") + if err != nil { + t.Error("detectVcsFromFS unable to Git repo") + } + if ltype != Git { + t.Errorf("detectVcsFromFS detected %s instead of Git type", ltype) + } + + // Test NewRepo on existing checkout. This should simply provide a working + // instance without error based on looking at the local directory. + nrepo, nrerr := NewRepo("https://github.com/Masterminds/VCSTestRepo", tempDir+"/VCSTestRepo") + if nrerr != nil { + t.Error(nrerr) + } + // Verify the right oject is returned. It will check the local repo type. + if !nrepo.CheckLocal() { + t.Error("Wrong version returned from NewRepo") + } + + // Perform an update. + err = repo.Update() + if err != nil { + t.Error(err) + } + + v, err := repo.Current() + if err != nil { + t.Errorf("Error trying Git Current: %s", err) + } + if v != "master" { + t.Errorf("Current failed to detect Git on tip of master. Got version: %s", v) + } + + // Set the version using the short hash. + err = repo.UpdateVersion("806b07b") + if err != nil { + t.Errorf("Unable to update Git repo version. Err was %s", err) + } + + // Once a ref has been checked out the repo is in a detached head state. + // Trying to pull in an update in this state will cause an error. Update + // should cleanly handle this. Pulling on a branch (tested elsewhere) and + // skipping that here. + err = repo.Update() + if err != nil { + t.Error(err) + } + + // Use Version to verify we are on the right version. + v, err = repo.Version() + if v != "806b07b08faa21cfbdae93027904f80174679402" { + t.Error("Error checking checked out Git version") + } + if err != nil { + t.Error(err) + } + + v, err = repo.Current() + if err != nil { + t.Errorf("Error trying Git Current for ref: %s", err) + } + if v != "806b07b08faa21cfbdae93027904f80174679402" { + t.Errorf("Current failed to detect Git on ref of branch. Got version: %s", v) + } + + // Use Date to verify we are on the right commit. + d, err := repo.Date() + if d.Format(longForm) != "2015-07-29 09:46:39 -0400" { + t.Error("Error checking checked out Git commit date") + } + if err != nil { + t.Error(err) + } + + // Verify that we can set the version something other than short hash + err = repo.UpdateVersion("master") + if err != nil { + t.Errorf("Unable to update Git repo version. Err was %s", err) + } + err = repo.UpdateVersion("806b07b08faa21cfbdae93027904f80174679402") + if err != nil { + t.Errorf("Unable to update Git repo version. Err was %s", err) + } + v, err = repo.Version() + if v != "806b07b08faa21cfbdae93027904f80174679402" { + t.Error("Error checking checked out Git version") + } + if err != nil { + t.Error(err) + } + + tags, err := repo.Tags() + if err != nil { + t.Error(err) + } + + var hasRelTag bool + var hasOffMasterTag bool + + for _, tv := range tags { + if tv == "1.0.0" { + hasRelTag = true + } else if tv == "off-master-tag" { + hasOffMasterTag = true + } + } + + if !hasRelTag { + t.Error("Git tags unable to find release tag on master") + } + if !hasOffMasterTag { + t.Error("Git tags did not fetch tags not on master") + } + + tags, err = repo.TagsFromCommit("74dd547545b7df4aa285bcec1b54e2b76f726395") + if err != nil { + t.Error(err) + } + if len(tags) != 0 { + t.Error("Git is incorrectly returning tags for a commit") + } + + tags, err = repo.TagsFromCommit("30605f6ac35fcb075ad0bfa9296f90a7d891523e") + if err != nil { + t.Error(err) + } + if len(tags) != 1 || tags[0] != "1.0.0" { + t.Error("Git is incorrectly returning tags for a commit") + } + + branches, err := repo.Branches() + if err != nil { + t.Error(err) + } + // The branches should be HEAD, master, other, and test. + if branches[3] != "test" { + t.Error("Git is incorrectly returning branches") + } + + if !repo.IsReference("1.0.0") { + t.Error("Git is reporting a reference is not one") + } + + if repo.IsReference("foo") { + t.Error("Git is reporting a non-existent reference is one") + } + + if repo.IsDirty() { + t.Error("Git incorrectly reporting dirty") + } + + ci, err := repo.CommitInfo("806b07b08faa21cfbdae93027904f80174679402") + if err != nil { + t.Error(err) + } + if ci.Commit != "806b07b08faa21cfbdae93027904f80174679402" { + t.Error("Git.CommitInfo wrong commit id") + } + if ci.Author != "Matt Farina " { + t.Error("Git.CommitInfo wrong author") + } + if ci.Message != "Update README.md" { + t.Error("Git.CommitInfo wrong message") + } + ti, err := time.Parse(time.RFC1123Z, "Wed, 29 Jul 2015 09:46:39 -0400") + if err != nil { + t.Error(err) + } + if !ti.Equal(ci.Date) { + t.Error("Git.CommitInfo wrong date") + } + + _, err = repo.CommitInfo("asdfasdfasdf") + if err != ErrRevisionUnavailable { + t.Error("Git didn't return expected ErrRevisionUnavailable") + } + + tempDir2, err := ioutil.TempDir("", "go-vcs-git-tests-export") + if err != nil { + t.Fatalf("Error creating temp directory: %s", err) + } + defer func() { + err = os.RemoveAll(tempDir2) + if err != nil { + t.Error(err) + } + }() + + exportDir := filepath.Join(tempDir2, "src") + + err = repo.ExportDir(exportDir) + if err != nil { + t.Errorf("Unable to export Git repo. Err was %s", err) + } + + _, err = os.Stat(filepath.Join(exportDir, "README.md")) + if err != nil { + t.Errorf("Error checking exported file in Git: %s", err) + } + + _, err = os.Stat(filepath.Join(exportDir, string(repo.Vcs()))) + if err != nil { + if found := os.IsNotExist(err); !found { + t.Errorf("Error checking exported metadata in Git: %s", err) + } + } else { + t.Error("Error checking Git metadata. It exists.") + } +} + +func TestGitCheckLocal(t *testing.T) { + // Verify repo.CheckLocal fails for non-Git directories. + // TestGit is already checking on a valid repo + tempDir, err := ioutil.TempDir("", "go-vcs-git-tests") + if err != nil { + t.Error(err) + } + defer func() { + err = os.RemoveAll(tempDir) + if err != nil { + t.Error(err) + } + }() + + repo, _ := NewGitRepo("", tempDir) + if repo.CheckLocal() { + t.Error("Git CheckLocal does not identify non-Git location") + } + + // Test NewRepo when there's no local. This should simply provide a working + // instance without error based on looking at the remote localtion. + _, nrerr := NewRepo("https://github.com/Masterminds/VCSTestRepo", tempDir+"/VCSTestRepo") + if nrerr != nil { + t.Error(nrerr) + } +} + +func TestGitPing(t *testing.T) { + tempDir, err := ioutil.TempDir("", "go-vcs-git-tests") + if err != nil { + t.Error(err) + } + defer func() { + err = os.RemoveAll(tempDir) + if err != nil { + t.Error(err) + } + }() + + repo, err := NewGitRepo("https://github.com/Masterminds/VCSTestRepo", tempDir) + if err != nil { + t.Error(err) + } + + ping := repo.Ping() + if !ping { + t.Error("Git unable to ping working repo") + } + + repo, err = NewGitRepo("https://github.com/Masterminds/ihopethisneverexistsbecauseitshouldnt", tempDir) + if err != nil { + t.Error(err) + } + + ping = repo.Ping() + if ping { + t.Error("Git got a ping response from when it should not have") + } +} + +func TestGitInit(t *testing.T) { + tempDir, err := ioutil.TempDir("", "go-vcs-git-tests") + repoDir := tempDir + "/repo" + if err != nil { + t.Error(err) + } + defer func() { + err = os.RemoveAll(tempDir) + if err != nil { + t.Error(err) + } + }() + + repo, err := NewGitRepo(repoDir, repoDir) + if err != nil { + t.Error(err) + } + + err = repo.Init() + if err != nil { + t.Error(err) + } + + _, err = repo.RunFromDir("git", "status") + if err != nil { + t.Error(err) + } +} + +func TestGitSubmoduleHandling(t *testing.T) { + tempDir, err := ioutil.TempDir("", "go-vcs-git-submodule-tests") + if err != nil { + t.Fatal(err) + } + defer func() { + err = os.RemoveAll(tempDir) + if err != nil { + t.Error(err) + } + }() + + dumplocal := func(err error) string { + if terr, ok := err.(*LocalError); ok { + return fmt.Sprintf("msg: %s\norig: %s\nout: %s", terr.Error(), terr.Original(), terr.Out()) + } + return err.Error() + } + + subdirExists := func(dir ...string) bool { + _, err := os.Stat(filepath.Join(append([]string{tempDir}, dir...)...)) + return err == nil + } + + // Initial clone should get version with two submodules, each of which have + // their own submodule + repo, err := NewGitRepo("https://github.com/sdboyer/subm", tempDir) + if err != nil { + t.Fatal(dumplocal(err)) + } + err = repo.Get() + if err != nil { + t.Fatalf("unable to clone Git repo. Err was %s", dumplocal(err)) + } + + // Verify we are on the right version. + v, err := repo.Version() + if v != "18e3a5f6fc7f6d577e732e7a5ab2caf990efbf8f" { + t.Fatalf("did not start from expected rev, tests could fail - bailing out (got %s)", v) + } + if err != nil { + t.Fatal(dumplocal(err)) + } + + if !subdirExists("subm1", ".git") { + t.Fatal("subm1 submodule does not exist on initial clone/checkout") + } + if !subdirExists("subm1", "dep-test", ".git") { + t.Fatal("dep-test submodule nested under subm1 does not exist on initial clone/checkout") + } + + if !subdirExists("subm-again", ".git") { + t.Fatal("subm-again submodule does not exist on initial clone/checkout") + } + if !subdirExists("subm-again", "dep-test", ".git") { + t.Fatal("dep-test submodule nested under subm-again does not exist on initial clone/checkout") + } + + // Now switch to version with no submodules, make sure they all go away + err = repo.UpdateVersion("e677f82015f72ac1c8fafa66b5463163b3597af2") + if err != nil { + t.Fatalf("checking out needed version failed with err: %s", dumplocal(err)) + } + + if subdirExists("subm1") { + t.Fatal("checking out version without submodule did not clean up immediate submodules") + } + if subdirExists("subm1", "dep-test") { + t.Fatal("checking out version without submodule did not clean up nested submodules") + } + if subdirExists("subm-again") { + t.Fatal("checking out version without submodule did not clean up immediate submodules") + } + if subdirExists("subm-again", "dep-test") { + t.Fatal("checking out version without submodule did not clean up nested submodules") + } + + err = repo.UpdateVersion("aaf7aa1bc4c3c682cc530eca8f80417088ee8540") + if err != nil { + t.Fatalf("checking out needed version failed with err: %s", dumplocal(err)) + } + + if !subdirExists("subm1", ".git") { + t.Fatal("checking out version with immediate submodule did not set up git subrepo") + } + + err = repo.UpdateVersion("6cc4669af468f3b4f16e7e96275ad01ade5b522f") + if err != nil { + t.Fatalf("checking out needed version failed with err: %s", dumplocal(err)) + } + + if !subdirExists("subm1", "dep-test", ".git") { + t.Fatal("checking out version with nested submodule did not set up nested git subrepo") + } + + err = repo.UpdateVersion("aaf7aa1bc4c3c682cc530eca8f80417088ee8540") + if err != nil { + t.Fatalf("checking out needed version failed with err: %s", dumplocal(err)) + } + + if subdirExists("subm1", "dep-test") { + t.Fatal("rolling back to version without nested submodule did not clean up the nested submodule") + } + + err = repo.UpdateVersion("18e3a5f6fc7f6d577e732e7a5ab2caf990efbf8f") + if err != nil { + t.Fatalf("checking out needed version failed with err: %s", dumplocal(err)) + } + + if !subdirExists("subm1", ".git") { + t.Fatal("subm1 submodule does not exist after switch from other commit") + } + if !subdirExists("subm1", "dep-test", ".git") { + t.Fatal("dep-test submodule nested under subm1 does not exist after switch from other commit") + } + + if !subdirExists("subm-again", ".git") { + t.Fatal("subm-again submodule does not exist after switch from other commit") + } + if !subdirExists("subm-again", "dep-test", ".git") { + t.Fatal("dep-test submodule nested under subm-again does not exist after switch from other commit") + } + +} + +func TestGitSubmoduleHandling2(t *testing.T) { + tempDir, err := ioutil.TempDir("", "go-vcs-git-submodule-tests2") + if err != nil { + t.Error(err) + } + defer func() { + err = os.RemoveAll(tempDir) + if err != nil { + t.Error(err) + } + }() + + repo, err := NewGitRepo("https://github.com/cloudfoundry/sonde-go", tempDir+"/VCSTestRepo2") + if err != nil { + t.Error(err) + } + + if repo.Vcs() != Git { + t.Error("Git is detecting the wrong type") + } + + // Check the basic getters. + if repo.Remote() != "https://github.com/cloudfoundry/sonde-go" { + t.Error("Remote not set properly") + } + if repo.LocalPath() != tempDir+"/VCSTestRepo2" { + t.Error("Local disk location not set properly") + } + + //Logger = log.New(os.Stdout, "", log.LstdFlags) + + // Do an initial clone. + err = repo.Get() + if err != nil { + t.Errorf("Unable to clone Git repo. Err was %s", err) + } + + // Verify Git repo is a Git repo + if !repo.CheckLocal() { + t.Error("Problem checking out repo or Git CheckLocal is not working") + } + + // Test internal lookup mechanism used outside of Git specific functionality. + ltype, err := DetectVcsFromFS(tempDir + "/VCSTestRepo2") + if err != nil { + t.Error("detectVcsFromFS unable to Git repo") + } + if ltype != Git { + t.Errorf("detectVcsFromFS detected %s instead of Git type", ltype) + } + + // Test NewRepo on existing checkout. This should simply provide a working + // instance without error based on looking at the local directory. + nrepo, nrerr := NewRepo("https://github.com/cloudfoundry/sonde-go", tempDir+"/VCSTestRepo2") + if nrerr != nil { + t.Error(nrerr) + } + // Verify the right oject is returned. It will check the local repo type. + if !nrepo.CheckLocal() { + t.Error("Wrong version returned from NewRepo") + } + + // Perform an update. + err = repo.Update() + if err != nil { + t.Error(err) + } + + v, err := repo.Current() + if err != nil { + t.Errorf("Error trying Git Current: %s", err) + } + if v != "master" { + t.Errorf("Current failed to detect Git on tip of master. Got version: %s", v) + } + + + tempDir2, err := ioutil.TempDir("", "go-vcs-git-tests-export") + if err != nil { + t.Fatalf("Error creating temp directory: %s", err) + } + defer func() { + err = os.RemoveAll(tempDir2) + if err != nil { + t.Error(err) + } + }() + + exportDir := filepath.Join(tempDir2, "src") + + err = repo.ExportDir(exportDir) + if err != nil { + t.Errorf("Unable to export Git repo. Err was %s", err) + } + + _, err = os.Stat(filepath.Join(exportDir, "README.md")) + if err != nil { + t.Errorf("Error checking exported file in Git: %s", err) + } + + _, err = os.Stat(filepath.Join( filepath.Join(exportDir, "definitions"), "README.md")) + if err != nil { + t.Errorf("Error checking exported file in Git: %s", err) + } + + _, err = os.Stat(filepath.Join(exportDir, string(repo.Vcs()))) + if err != nil { + if found := os.IsNotExist(err); !found { + t.Errorf("Error checking exported metadata in Git: %s", err) + } + } else { + t.Error("Error checking Git metadata. It exists.") + } +} diff --git a/vendor/github.com/Masterminds/vcs/glide.yaml b/vendor/github.com/Masterminds/vcs/glide.yaml new file mode 100644 index 00000000..b96e0bd3 --- /dev/null +++ b/vendor/github.com/Masterminds/vcs/glide.yaml @@ -0,0 +1,8 @@ +package: github.com/Masterminds/vcs +homepage: https://github.com/Masterminds/vcs +license: MIT +owners: +- name: Matt Farina + email: matt@mattfarina.com + homepage: https://www.mattfarina.com/ +import: [] diff --git a/vendor/github.com/Masterminds/vcs/hg.go b/vendor/github.com/Masterminds/vcs/hg.go new file mode 100644 index 00000000..5000a6d9 --- /dev/null +++ b/vendor/github.com/Masterminds/vcs/hg.go @@ -0,0 +1,317 @@ +package vcs + +import ( + "encoding/xml" + "os" + "os/exec" + "regexp" + "strings" + "time" +) + +var hgDetectURL = regexp.MustCompile("default = (?P.+)\n") + +// NewHgRepo creates a new instance of HgRepo. The remote and local directories +// need to be passed in. +func NewHgRepo(remote, local string) (*HgRepo, error) { + ins := depInstalled("hg") + if !ins { + return nil, NewLocalError("hg is not installed", nil, "") + } + ltype, err := DetectVcsFromFS(local) + + // Found a VCS other than Hg. Need to report an error. + if err == nil && ltype != Hg { + return nil, ErrWrongVCS + } + + r := &HgRepo{} + r.setRemote(remote) + r.setLocalPath(local) + r.Logger = Logger + + // Make sure the local Hg repo is configured the same as the remote when + // A remote value was passed in. + if err == nil && r.CheckLocal() { + // An Hg repo was found so test that the URL there matches + // the repo passed in here. + c := exec.Command("hg", "paths") + c.Dir = local + c.Env = envForDir(c.Dir) + out, err := c.CombinedOutput() + if err != nil { + return nil, NewLocalError("Unable to retrieve local repo information", err, string(out)) + } + + m := hgDetectURL.FindStringSubmatch(string(out)) + if m[1] != "" && m[1] != remote { + return nil, ErrWrongRemote + } + + // If no remote was passed in but one is configured for the locally + // checked out Hg repo use that one. + if remote == "" && m[1] != "" { + r.setRemote(m[1]) + } + } + + return r, nil +} + +// HgRepo implements the Repo interface for the Mercurial source control. +type HgRepo struct { + base +} + +// Vcs retrieves the underlying VCS being implemented. +func (s HgRepo) Vcs() Type { + return Hg +} + +// Get is used to perform an initial clone of a repository. +func (s *HgRepo) Get() error { + out, err := s.run("hg", "clone", s.Remote(), s.LocalPath()) + if err != nil { + return NewRemoteError("Unable to get repository", err, string(out)) + } + return nil +} + +// Init will initialize a mercurial repository at local location. +func (s *HgRepo) Init() error { + out, err := s.run("hg", "init", s.LocalPath()) + if err != nil { + return NewLocalError("Unable to initialize repository", err, string(out)) + } + return nil +} + +// Update performs a Mercurial pull to an existing checkout. +func (s *HgRepo) Update() error { + return s.UpdateVersion(``) +} + +// UpdateVersion sets the version of a package currently checked out via Hg. +func (s *HgRepo) UpdateVersion(version string) error { + out, err := s.RunFromDir("hg", "pull") + if err != nil { + return NewLocalError("Unable to update checked out version", err, string(out)) + } + if len(strings.TrimSpace(version)) > 0 { + out, err = s.RunFromDir("hg", "update", version) + } else { + out, err = s.RunFromDir("hg", "update") + } + if err != nil { + return NewLocalError("Unable to update checked out version", err, string(out)) + } + return nil +} + +// Version retrieves the current version. +func (s *HgRepo) Version() (string, error) { + out, err := s.RunFromDir("hg", "--debug", "identify") + if err != nil { + return "", NewLocalError("Unable to retrieve checked out version", err, string(out)) + } + + parts := strings.SplitN(string(out), " ", 2) + sha := parts[0] + return strings.TrimSpace(sha), nil +} + +// Current returns the current version-ish. This means: +// * Branch name if on the tip of the branch +// * Tag if on a tag +// * Otherwise a revision id +func (s *HgRepo) Current() (string, error) { + out, err := s.RunFromDir("hg", "branch") + if err != nil { + return "", err + } + branch := strings.TrimSpace(string(out)) + + tip, err := s.CommitInfo("max(branch(" + branch + "))") + if err != nil { + return "", err + } + + curr, err := s.Version() + if err != nil { + return "", err + } + + if tip.Commit == curr { + + return branch, nil + } + + ts, err := s.TagsFromCommit(curr) + if err != nil { + return "", err + } + if len(ts) > 0 { + return ts[0], nil + } + + return curr, nil +} + +// Date retrieves the date on the latest commit. +func (s *HgRepo) Date() (time.Time, error) { + version, err := s.Version() + if err != nil { + return time.Time{}, NewLocalError("Unable to retrieve revision date", err, "") + } + out, err := s.RunFromDir("hg", "log", "-r", version, "--template", "{date|isodatesec}") + if err != nil { + return time.Time{}, NewLocalError("Unable to retrieve revision date", err, string(out)) + } + t, err := time.Parse(longForm, string(out)) + if err != nil { + return time.Time{}, NewLocalError("Unable to retrieve revision date", err, string(out)) + } + return t, nil +} + +// CheckLocal verifies the local location is a Git repo. +func (s *HgRepo) CheckLocal() bool { + if _, err := os.Stat(s.LocalPath() + "/.hg"); err == nil { + return true + } + + return false +} + +// Branches returns a list of available branches +func (s *HgRepo) Branches() ([]string, error) { + out, err := s.RunFromDir("hg", "branches") + if err != nil { + return []string{}, NewLocalError("Unable to retrieve branches", err, string(out)) + } + branches := s.referenceList(string(out), `(?m-s)^(\S+)`) + return branches, nil +} + +// Tags returns a list of available tags +func (s *HgRepo) Tags() ([]string, error) { + out, err := s.RunFromDir("hg", "tags") + if err != nil { + return []string{}, NewLocalError("Unable to retrieve tags", err, string(out)) + } + tags := s.referenceList(string(out), `(?m-s)^(\S+)`) + return tags, nil +} + +// IsReference returns if a string is a reference. A reference can be a +// commit id, branch, or tag. +func (s *HgRepo) IsReference(r string) bool { + _, err := s.RunFromDir("hg", "log", "-r", r) + return err == nil +} + +// IsDirty returns if the checkout has been modified from the checked +// out reference. +func (s *HgRepo) IsDirty() bool { + out, err := s.RunFromDir("hg", "diff") + return err != nil || len(out) != 0 +} + +// CommitInfo retrieves metadata about a commit. +func (s *HgRepo) CommitInfo(id string) (*CommitInfo, error) { + out, err := s.RunFromDir("hg", "log", "-r", id, "--style=xml") + if err != nil { + return nil, ErrRevisionUnavailable + } + + type Author struct { + Name string `xml:",chardata"` + Email string `xml:"email,attr"` + } + type Logentry struct { + Node string `xml:"node,attr"` + Author Author `xml:"author"` + Date string `xml:"date"` + Msg string `xml:"msg"` + } + type Log struct { + XMLName xml.Name `xml:"log"` + Logs []Logentry `xml:"logentry"` + } + + logs := &Log{} + err = xml.Unmarshal(out, &logs) + if err != nil { + return nil, NewLocalError("Unable to retrieve commit information", err, string(out)) + } + if len(logs.Logs) == 0 { + return nil, ErrRevisionUnavailable + } + + ci := &CommitInfo{ + Commit: logs.Logs[0].Node, + Author: logs.Logs[0].Author.Name + " <" + logs.Logs[0].Author.Email + ">", + Message: logs.Logs[0].Msg, + } + + if logs.Logs[0].Date != "" { + ci.Date, err = time.Parse(time.RFC3339, logs.Logs[0].Date) + if err != nil { + return nil, NewLocalError("Unable to retrieve commit information", err, string(out)) + } + } + + return ci, nil +} + +// TagsFromCommit retrieves tags from a commit id. +func (s *HgRepo) TagsFromCommit(id string) ([]string, error) { + // Hg has a single tag per commit. If a second tag is added to a commit a + // new commit is created and the tag is attached to that new commit. + out, err := s.RunFromDir("hg", "log", "-r", id, "--style=xml") + if err != nil { + return []string{}, NewLocalError("Unable to retrieve tags", err, string(out)) + } + + type Logentry struct { + Node string `xml:"node,attr"` + Tag string `xml:"tag"` + } + type Log struct { + XMLName xml.Name `xml:"log"` + Logs []Logentry `xml:"logentry"` + } + + logs := &Log{} + err = xml.Unmarshal(out, &logs) + if err != nil { + return []string{}, NewLocalError("Unable to retrieve tags", err, string(out)) + } + if len(logs.Logs) == 0 { + return []string{}, NewLocalError("Unable to retrieve tags", err, string(out)) + } + + t := strings.TrimSpace(logs.Logs[0].Tag) + if t != "" { + return []string{t}, nil + } + return []string{}, nil +} + +// Ping returns if remote location is accessible. +func (s *HgRepo) Ping() bool { + _, err := s.run("hg", "identify", s.Remote()) + return err == nil +} + +// ExportDir exports the current revision to the passed in directory. +func (s *HgRepo) ExportDir(dir string) error { + + out, err := s.RunFromDir("hg", "archive", dir) + s.log(out) + if err != nil { + return NewLocalError("Unable to export source", err, string(out)) + } + + return nil +} diff --git a/vendor/github.com/Masterminds/vcs/hg_test.go b/vendor/github.com/Masterminds/vcs/hg_test.go new file mode 100644 index 00000000..6b19f728 --- /dev/null +++ b/vendor/github.com/Masterminds/vcs/hg_test.go @@ -0,0 +1,332 @@ +package vcs + +import ( + "io/ioutil" + "path/filepath" + "strings" + "time" + //"log" + "os" + "testing" +) + +// Canary test to ensure HgRepo implements the Repo interface. +var _ Repo = &HgRepo{} + +// To verify hg is working we perform integration testing +// with a known hg service. + +func TestHg(t *testing.T) { + + tempDir, err := ioutil.TempDir("", "go-vcs-hg-tests") + if err != nil { + t.Error(err) + } + defer func() { + err = os.RemoveAll(tempDir) + if err != nil { + t.Error(err) + } + }() + + repo, err := NewHgRepo("https://bitbucket.org/mattfarina/testhgrepo", tempDir+"/testhgrepo") + if err != nil { + t.Error(err) + } + + if repo.Vcs() != Hg { + t.Error("Hg is detecting the wrong type") + } + + // Check the basic getters. + if repo.Remote() != "https://bitbucket.org/mattfarina/testhgrepo" { + t.Error("Remote not set properly") + } + if repo.LocalPath() != tempDir+"/testhgrepo" { + t.Error("Local disk location not set properly") + } + + //Logger = log.New(os.Stdout, "", log.LstdFlags) + + // Do an initial clone. + err = repo.Get() + if err != nil { + t.Errorf("Unable to clone Hg repo. Err was %s", err) + } + + // Verify Hg repo is a Hg repo + if !repo.CheckLocal() { + t.Error("Problem checking out repo or Hg CheckLocal is not working") + } + + // Test internal lookup mechanism used outside of Hg specific functionality. + ltype, err := DetectVcsFromFS(tempDir + "/testhgrepo") + if err != nil { + t.Error("detectVcsFromFS unable to Hg repo") + } + if ltype != Hg { + t.Errorf("detectVcsFromFS detected %s instead of Hg type", ltype) + } + + // Test NewRepo on existing checkout. This should simply provide a working + // instance without error based on looking at the local directory. + nrepo, nrerr := NewRepo("https://bitbucket.org/mattfarina/testhgrepo", tempDir+"/testhgrepo") + if nrerr != nil { + t.Error(nrerr) + } + // Verify the right oject is returned. It will check the local repo type. + if !nrepo.CheckLocal() { + t.Error("Wrong version returned from NewRepo") + } + + v, err := repo.Current() + if err != nil { + t.Errorf("Error trying Hg Current: %s", err) + } + if v != "default" { + t.Errorf("Current failed to detect Hg on tip of default. Got version: %s", v) + } + + // Set the version using the short hash. + err = repo.UpdateVersion("a5494ba2177f") + if err != nil { + t.Errorf("Unable to update Hg repo version. Err was %s", err) + } + + // Use Version to verify we are on the right version. + v, err = repo.Version() + if v != "a5494ba2177ff9ef26feb3c155dfecc350b1a8ef" { + t.Errorf("Error checking checked out Hg version: %s", v) + } + if err != nil { + t.Error(err) + } + + v, err = repo.Current() + if err != nil { + t.Errorf("Error trying Hg Current for ref: %s", err) + } + if v != "a5494ba2177ff9ef26feb3c155dfecc350b1a8ef" { + t.Errorf("Current failed to detect Hg on ref of branch. Got version: %s", v) + } + + // Use Date to verify we are on the right commit. + d, err := repo.Date() + if err != nil { + t.Error(err) + } + if d.Format(longForm) != "2015-07-30 16:14:08 -0400" { + t.Error("Error checking checked out Hg commit date. Got wrong date:", d) + } + + // Perform an update. + err = repo.Update() + if err != nil { + t.Error(err) + } + + v, err = repo.Version() + if v != "9c6ccbca73e8a1351c834f33f57f1f7a0329ad35" { + t.Errorf("Error checking checked out Hg version: %s", v) + } + if err != nil { + t.Error(err) + } + + tags, err := repo.Tags() + if err != nil { + t.Error(err) + } + if tags[1] != "1.0.0" { + t.Error("Hg tags is not reporting the correct version") + } + + tags, err = repo.TagsFromCommit("a5494ba2177f") + if err != nil { + t.Error(err) + } + if len(tags) != 0 { + t.Error("Hg is incorrectly returning tags for a commit") + } + + tags, err = repo.TagsFromCommit("d680e82228d2") + if err != nil { + t.Error(err) + } + if len(tags) != 1 || tags[0] != "1.0.0" { + t.Error("Hg is incorrectly returning tags for a commit") + } + + branches, err := repo.Branches() + if err != nil { + t.Error(err) + } + // The branches should be HEAD, master, and test. + if branches[0] != "test" { + t.Error("Hg is incorrectly returning branches") + } + + if !repo.IsReference("1.0.0") { + t.Error("Hg is reporting a reference is not one") + } + + if !repo.IsReference("test") { + t.Error("Hg is reporting a reference is not one") + } + + if repo.IsReference("foo") { + t.Error("Hg is reporting a non-existent reference is one") + } + + if repo.IsDirty() { + t.Error("Hg incorrectly reporting dirty") + } + + ci, err := repo.CommitInfo("a5494ba2177f") + if err != nil { + t.Error(err) + } + if ci.Commit != "a5494ba2177ff9ef26feb3c155dfecc350b1a8ef" { + t.Error("Hg.CommitInfo wrong commit id") + } + if ci.Author != "Matt Farina " { + t.Error("Hg.CommitInfo wrong author") + } + if ci.Message != "A commit" { + t.Error("Hg.CommitInfo wrong message") + } + + ti := time.Unix(1438287248, 0) + if !ti.Equal(ci.Date) { + t.Error("Hg.CommitInfo wrong date") + } + + _, err = repo.CommitInfo("asdfasdfasdf") + if err != ErrRevisionUnavailable { + t.Error("Hg didn't return expected ErrRevisionUnavailable") + } + + tempDir2, err := ioutil.TempDir("", "go-vcs-hg-tests-export") + if err != nil { + t.Fatalf("Error creating temp directory: %s", err) + } + defer func() { + err = os.RemoveAll(tempDir2) + if err != nil { + t.Error(err) + } + }() + + exportDir := filepath.Join(tempDir2, "src") + + err = repo.ExportDir(exportDir) + if err != nil { + t.Errorf("Unable to export Hg repo. Err was %s", err) + } + + _, err = os.Stat(filepath.Join(exportDir, "Readme.md")) + if err != nil { + t.Errorf("Error checking exported file in Hg: %s", err) + } + + _, err = os.Stat(filepath.Join(exportDir, string(repo.Vcs()))) + if err != nil { + if found := os.IsNotExist(err); !found { + t.Errorf("Error checking exported metadata in Hg: %s", err) + } + } else { + t.Error("Error checking Hg metadata. It exists.") + } +} + +func TestHgCheckLocal(t *testing.T) { + // Verify repo.CheckLocal fails for non-Hg directories. + // TestHg is already checking on a valid repo + tempDir, err := ioutil.TempDir("", "go-vcs-hg-tests") + if err != nil { + t.Error(err) + } + defer func() { + err = os.RemoveAll(tempDir) + if err != nil { + t.Error(err) + } + }() + + repo, _ := NewHgRepo("", tempDir) + if repo.CheckLocal() { + t.Error("Hg CheckLocal does not identify non-Hg location") + } + + // Test NewRepo when there's no local. This should simply provide a working + // instance without error based on looking at the remote localtion. + _, nrerr := NewRepo("https://bitbucket.org/mattfarina/testhgrepo", tempDir+"/testhgrepo") + if nrerr != nil { + t.Error(nrerr) + } +} + +func TestHgPing(t *testing.T) { + tempDir, err := ioutil.TempDir("", "go-vcs-hg-tests") + if err != nil { + t.Error(err) + } + defer func() { + err = os.RemoveAll(tempDir) + if err != nil { + t.Error(err) + } + }() + + repo, err := NewHgRepo("https://bitbucket.org/mattfarina/testhgrepo", tempDir) + if err != nil { + t.Error(err) + } + + ping := repo.Ping() + if !ping { + t.Error("Hg unable to ping working repo") + } + + repo, err = NewHgRepo("https://bitbucket.org/mattfarina/ihopethisneverexistsbecauseitshouldnt", tempDir) + if err != nil { + t.Error(err) + } + + ping = repo.Ping() + if ping { + t.Error("Hg got a ping response from when it should not have") + } +} + +func TestHgInit(t *testing.T) { + tempDir, err := ioutil.TempDir("", "go-vcs-hg-tests") + repoDir := tempDir + "/repo" + if err != nil { + t.Error(err) + } + defer func() { + err = os.RemoveAll(tempDir) + if err != nil { + t.Error(err) + } + }() + + repo, err := NewHgRepo(repoDir, repoDir) + if err != nil { + t.Error(err) + } + + err = repo.Init() + if err != nil { + t.Error(err) + } + + v, err := repo.Version() + if err != nil { + t.Error(err) + } + if !strings.HasPrefix(v, "000000") { + t.Errorf("Hg Init reporting wrong initial version: %s", v) + } +} diff --git a/vendor/github.com/Masterminds/vcs/repo.go b/vendor/github.com/Masterminds/vcs/repo.go new file mode 100644 index 00000000..356dad6f --- /dev/null +++ b/vendor/github.com/Masterminds/vcs/repo.go @@ -0,0 +1,276 @@ +// Package vcs provides the ability to work with varying version control systems +// (VCS), also known as source control systems (SCM) though the same interface. +// +// This package includes a function that attempts to detect the repo type from +// the remote URL and return the proper type. For example, +// +// remote := "https://github.com/Masterminds/vcs" +// local, _ := ioutil.TempDir("", "go-vcs") +// repo, err := NewRepo(remote, local) +// +// In this case repo will be a GitRepo instance. NewRepo can detect the VCS for +// numerous popular VCS and from the URL. For example, a URL ending in .git +// that's not from one of the popular VCS will be detected as a Git repo and +// the correct type will be returned. +// +// If you know the repository type and would like to create an instance of a +// specific type you can use one of constructors for a type. They are NewGitRepo, +// NewSvnRepo, NewBzrRepo, and NewHgRepo. The definition and usage is the same +// as NewRepo. +// +// Once you have an object implementing the Repo interface the operations are +// the same no matter which VCS you're using. There are some caveats. For +// example, each VCS has its own version formats that need to be respected and +// checkout out branches, if a branch is being worked with, is different in +// each VCS. +package vcs + +import ( + "fmt" + "io/ioutil" + "log" + "os" + "os/exec" + "regexp" + "strings" + "time" +) + +// Logger is where you can provide a logger, implementing the log.Logger interface, +// where verbose output from each VCS will be written. The default logger does +// not log data. To log data supply your own logger or change the output location +// of the provided logger. +var Logger *log.Logger + +func init() { + // Initialize the logger to one that does not actually log anywhere. This is + // to be overridden by the package user by setting vcs.Logger to a different + // logger. + Logger = log.New(ioutil.Discard, "go-vcs", log.LstdFlags) +} + +const longForm = "2006-01-02 15:04:05 -0700" + +// Type describes the type of VCS +type Type string + +// VCS types +const ( + NoVCS Type = "" + Git Type = "git" + Svn Type = "svn" + Bzr Type = "bzr" + Hg Type = "hg" +) + +// Repo provides an interface to work with repositories using different source +// control systems such as Git, Bzr, Mercurial, and SVN. For implementations +// of this interface see BzrRepo, GitRepo, HgRepo, and SvnRepo. +type Repo interface { + + // Vcs retrieves the underlying VCS being implemented. + Vcs() Type + + // Remote retrieves the remote location for a repo. + Remote() string + + // LocalPath retrieves the local file system location for a repo. + LocalPath() string + + // Get is used to perform an initial clone/checkout of a repository. + Get() error + + // Initializes a new repository locally. + Init() error + + // Update performs an update to an existing checkout of a repository. + Update() error + + // UpdateVersion sets the version of a package of a repository. + UpdateVersion(string) error + + // Version retrieves the current version. + Version() (string, error) + + // Current retrieves the current version-ish. This is different from the + // Version method. The output could be a branch name if on the tip of a + // branch (git), a tag if on a tag, a revision if on a specific revision + // that's not the tip of the branch. The values here vary based on the VCS. + Current() (string, error) + + // Date retrieves the date on the latest commit. + Date() (time.Time, error) + + // CheckLocal verifies the local location is of the correct VCS type + CheckLocal() bool + + // Branches returns a list of available branches on the repository. + Branches() ([]string, error) + + // Tags returns a list of available tags on the repository. + Tags() ([]string, error) + + // IsReference returns if a string is a reference. A reference can be a + // commit id, branch, or tag. + IsReference(string) bool + + // IsDirty returns if the checkout has been modified from the checked + // out reference. + IsDirty() bool + + // CommitInfo retrieves metadata about a commit. + CommitInfo(string) (*CommitInfo, error) + + // TagsFromCommit retrieves tags from a commit id. + TagsFromCommit(string) ([]string, error) + + // Ping returns if remote location is accessible. + Ping() bool + + // RunFromDir executes a command from repo's directory. + RunFromDir(cmd string, args ...string) ([]byte, error) + + // CmdFromDir creates a new command that will be executed from repo's + // directory. + CmdFromDir(cmd string, args ...string) *exec.Cmd + + // ExportDir exports the current revision to the passed in directory. + ExportDir(string) error +} + +// NewRepo returns a Repo based on trying to detect the source control from the +// remote and local locations. The appropriate implementation will be returned +// or an ErrCannotDetectVCS if the VCS type cannot be detected. +// Note, this function may make calls to the Internet to determind help determine +// the VCS. +func NewRepo(remote, local string) (Repo, error) { + vtype, remote, err := detectVcsFromRemote(remote) + + // From the remote URL the VCS could not be detected. See if the local + // repo contains enough information to figure out the VCS. The reason the + // local repo is not checked first is because of the potential for VCS type + // switches which will be detected in each of the type builders. + if err == ErrCannotDetectVCS { + vtype, err = DetectVcsFromFS(local) + } + + if err != nil { + return nil, err + } + + switch vtype { + case Git: + return NewGitRepo(remote, local) + case Svn: + return NewSvnRepo(remote, local) + case Hg: + return NewHgRepo(remote, local) + case Bzr: + return NewBzrRepo(remote, local) + } + + // Should never fall through to here but just in case. + return nil, ErrCannotDetectVCS +} + +// CommitInfo contains metadata about a commit. +type CommitInfo struct { + // The commit id + Commit string + + // Who authored the commit + Author string + + // Date of the commit + Date time.Time + + // Commit message + Message string +} + +type base struct { + remote, local string + Logger *log.Logger +} + +func (b *base) log(v interface{}) { + b.Logger.Printf("%s", v) +} + +// Remote retrieves the remote location for a repo. +func (b *base) Remote() string { + return b.remote +} + +// LocalPath retrieves the local file system location for a repo. +func (b *base) LocalPath() string { + return b.local +} + +func (b *base) setRemote(remote string) { + b.remote = remote +} + +func (b *base) setLocalPath(local string) { + b.local = local +} + +func (b base) run(cmd string, args ...string) ([]byte, error) { + out, err := exec.Command(cmd, args...).CombinedOutput() + b.log(out) + if err != nil { + err = fmt.Errorf("%s: %s", out, err) + } + return out, err +} + +func (b *base) CmdFromDir(cmd string, args ...string) *exec.Cmd { + c := exec.Command(cmd, args...) + c.Dir = b.local + c.Env = envForDir(c.Dir) + return c +} + +func (b *base) RunFromDir(cmd string, args ...string) ([]byte, error) { + c := b.CmdFromDir(cmd, args...) + out, err := c.CombinedOutput() + return out, err +} + +func (b *base) referenceList(c, r string) []string { + var out []string + re := regexp.MustCompile(r) + for _, m := range re.FindAllStringSubmatch(c, -1) { + out = append(out, m[1]) + } + + return out +} + +func envForDir(dir string) []string { + env := os.Environ() + return mergeEnvLists([]string{"PWD=" + dir}, env) +} + +func mergeEnvLists(in, out []string) []string { +NextVar: + for _, inkv := range in { + k := strings.SplitAfterN(inkv, "=", 2)[0] + for i, outkv := range out { + if strings.HasPrefix(outkv, k) { + out[i] = inkv + continue NextVar + } + } + out = append(out, inkv) + } + return out +} + +func depInstalled(name string) bool { + if _, err := exec.LookPath(name); err != nil { + return false + } + + return true +} diff --git a/vendor/github.com/Masterminds/vcs/repo_test.go b/vendor/github.com/Masterminds/vcs/repo_test.go new file mode 100644 index 00000000..8c083b3f --- /dev/null +++ b/vendor/github.com/Masterminds/vcs/repo_test.go @@ -0,0 +1,74 @@ +package vcs + +import ( + "fmt" + "io/ioutil" + "os" + "testing" +) + +func ExampleNewRepo() { + remote := "https://github.com/Masterminds/vcs" + local, _ := ioutil.TempDir("", "go-vcs") + repo, _ := NewRepo(remote, local) + // Returns: instance of GitRepo + + repo.Vcs() + // Returns Git as this is a Git repo + + err := repo.Get() + // Pulls down a repo, or a checkout in the case of SVN, and returns an + // error if that didn't happen successfully. + if err != nil { + fmt.Println(err) + } + + err = repo.UpdateVersion("master") + // Checkouts out a specific version. In most cases this can be a commit id, + // branch, or tag. + if err != nil { + fmt.Println(err) + } +} + +func TestTypeSwitch(t *testing.T) { + + // To test repo type switching we checkout as SVN and then try to get it as + // a git repo afterwards. + tempDir, err := ioutil.TempDir("", "go-vcs-svn-tests") + if err != nil { + t.Error(err) + } + defer func() { + err = os.RemoveAll(tempDir) + if err != nil { + t.Error(err) + } + }() + + repo, err := NewSvnRepo("https://github.com/Masterminds/VCSTestRepo/trunk", tempDir+string(os.PathSeparator)+"VCSTestRepo") + if err != nil { + t.Error(err) + } + err = repo.Get() + if err != nil { + t.Errorf("Unable to checkout SVN repo for repo switching tests. Err was %s", err) + } + + _, err = NewRepo("https://github.com/Masterminds/VCSTestRepo", tempDir+string(os.PathSeparator)+"VCSTestRepo") + if err != ErrWrongVCS { + t.Errorf("Not detecting repo switch from SVN to Git") + } +} + +func TestDepInstalled(t *testing.T) { + i := depInstalled("git") + if !i { + t.Error("depInstalled not finding installed dep.") + } + + i = depInstalled("thisreallyisntinstalled") + if i { + t.Error("depInstalled finding not installed dep.") + } +} diff --git a/vendor/github.com/Masterminds/vcs/svn.go b/vendor/github.com/Masterminds/vcs/svn.go new file mode 100644 index 00000000..913f90a8 --- /dev/null +++ b/vendor/github.com/Masterminds/vcs/svn.go @@ -0,0 +1,386 @@ +package vcs + +import ( + "encoding/xml" + "fmt" + "os" + "os/exec" + "path/filepath" + "runtime" + "strings" + "time" +) + +// NewSvnRepo creates a new instance of SvnRepo. The remote and local directories +// need to be passed in. The remote location should include the branch for SVN. +// For example, if the package is https://github.com/Masterminds/cookoo/ the remote +// should be https://github.com/Masterminds/cookoo/trunk for the trunk branch. +func NewSvnRepo(remote, local string) (*SvnRepo, error) { + ins := depInstalled("svn") + if !ins { + return nil, NewLocalError("svn is not installed", nil, "") + } + ltype, err := DetectVcsFromFS(local) + + // Found a VCS other than Svn. Need to report an error. + if err == nil && ltype != Svn { + return nil, ErrWrongVCS + } + + r := &SvnRepo{} + r.setRemote(remote) + r.setLocalPath(local) + r.Logger = Logger + + // Make sure the local SVN repo is configured the same as the remote when + // A remote value was passed in. + if err == nil && r.CheckLocal() { + // An SVN repo was found so test that the URL there matches + // the repo passed in here. + out, err := exec.Command("svn", "info", local).CombinedOutput() + if err != nil { + return nil, NewLocalError("Unable to retrieve local repo information", err, string(out)) + } + + detectedRemote, err := detectRemoteFromInfoCommand(string(out)) + if err != nil { + return nil, NewLocalError("Unable to retrieve local repo information", err, string(out)) + } + if detectedRemote != "" && remote != "" && detectedRemote != remote { + return nil, ErrWrongRemote + } + + // If no remote was passed in but one is configured for the locally + // checked out Svn repo use that one. + if remote == "" && detectedRemote != "" { + r.setRemote(detectedRemote) + } + } + + return r, nil +} + +// SvnRepo implements the Repo interface for the Svn source control. +type SvnRepo struct { + base +} + +// Vcs retrieves the underlying VCS being implemented. +func (s SvnRepo) Vcs() Type { + return Svn +} + +// Get is used to perform an initial checkout of a repository. +// Note, because SVN isn't distributed this is a checkout without +// a clone. +func (s *SvnRepo) Get() error { + remote := s.Remote() + if strings.HasPrefix(remote, "/") { + remote = "file://" + remote + } else if runtime.GOOS == "windows" && filepath.VolumeName(remote) != "" { + remote = "file:///" + remote + } + out, err := s.run("svn", "checkout", remote, s.LocalPath()) + if err != nil { + return NewRemoteError("Unable to get repository", err, string(out)) + } + return nil +} + +// Init will create a svn repository at remote location. +func (s *SvnRepo) Init() error { + out, err := s.run("svnadmin", "create", s.Remote()) + + if err != nil && s.isUnableToCreateDir(err) { + + basePath := filepath.Dir(filepath.FromSlash(s.Remote())) + if _, err := os.Stat(basePath); os.IsNotExist(err) { + err = os.MkdirAll(basePath, 0755) + if err != nil { + return NewLocalError("Unable to initialize repository", err, "") + } + + out, err = s.run("svnadmin", "create", s.Remote()) + if err != nil { + return NewLocalError("Unable to initialize repository", err, string(out)) + } + return nil + } + + } else if err != nil { + return NewLocalError("Unable to initialize repository", err, string(out)) + } + + return nil +} + +// Update performs an SVN update to an existing checkout. +func (s *SvnRepo) Update() error { + out, err := s.RunFromDir("svn", "update") + if err != nil { + return NewRemoteError("Unable to update repository", err, string(out)) + } + return err +} + +// UpdateVersion sets the version of a package currently checked out via SVN. +func (s *SvnRepo) UpdateVersion(version string) error { + out, err := s.RunFromDir("svn", "update", "-r", version) + if err != nil { + return NewRemoteError("Unable to update checked out version", err, string(out)) + } + return nil +} + +// Version retrieves the current version. +func (s *SvnRepo) Version() (string, error) { + type Commit struct { + Revision string `xml:"revision,attr"` + } + type Info struct { + Commit Commit `xml:"entry>commit"` + } + + out, err := s.RunFromDir("svn", "info", "--xml") + if err != nil { + return "", NewLocalError("Unable to retrieve checked out version", err, string(out)) + } + s.log(out) + infos := &Info{} + err = xml.Unmarshal(out, &infos) + if err != nil { + return "", NewLocalError("Unable to retrieve checked out version", err, string(out)) + } + + return infos.Commit.Revision, nil +} + +// Current returns the current version-ish. This means: +// * HEAD if on the tip. +// * Otherwise a revision id +func (s *SvnRepo) Current() (string, error) { + tip, err := s.CommitInfo("HEAD") + if err != nil { + return "", err + } + + curr, err := s.Version() + if err != nil { + return "", err + } + + if tip.Commit == curr { + return "HEAD", nil + } + + return curr, nil +} + +// Date retrieves the date on the latest commit. +func (s *SvnRepo) Date() (time.Time, error) { + version, err := s.Version() + if err != nil { + return time.Time{}, NewLocalError("Unable to retrieve revision date", err, "") + } + out, err := s.RunFromDir("svn", "pget", "svn:date", "--revprop", "-r", version) + if err != nil { + return time.Time{}, NewLocalError("Unable to retrieve revision date", err, string(out)) + } + const longForm = "2006-01-02T15:04:05.000000Z" + t, err := time.Parse(longForm, strings.TrimSpace(string(out))) + if err != nil { + return time.Time{}, NewLocalError("Unable to retrieve revision date", err, string(out)) + } + return t, nil +} + +// CheckLocal verifies the local location is an SVN repo. +func (s *SvnRepo) CheckLocal() bool { + pth, err := filepath.Abs(s.LocalPath()) + if err != nil { + s.log(err.Error()) + return false + } + + if _, err := os.Stat(filepath.Join(pth, ".svn")); err == nil { + return true + } + + oldpth := pth + for oldpth != pth { + pth = filepath.Dir(pth) + if _, err := os.Stat(filepath.Join(pth, ".svn")); err == nil { + return true + } + } + + return false +} + +// Tags returns []string{} as there are no formal tags in SVN. Tags are a +// convention in SVN. They are typically implemented as a copy of the trunk and +// placed in the /tags/[tag name] directory. Since this is a convention the +// expectation is to checkout a tag the correct subdirectory will be used +// as the path. For more information see: +// http://svnbook.red-bean.com/en/1.7/svn.branchmerge.tags.html +func (s *SvnRepo) Tags() ([]string, error) { + return []string{}, nil +} + +// Branches returns []string{} as there are no formal branches in SVN. Branches +// are a convention. They are typically implemented as a copy of the trunk and +// placed in the /branches/[tag name] directory. Since this is a convention the +// expectation is to checkout a branch the correct subdirectory will be used +// as the path. For more information see: +// http://svnbook.red-bean.com/en/1.7/svn.branchmerge.using.html +func (s *SvnRepo) Branches() ([]string, error) { + return []string{}, nil +} + +// IsReference returns if a string is a reference. A reference is a commit id. +// Branches and tags are part of the path. +func (s *SvnRepo) IsReference(r string) bool { + out, err := s.RunFromDir("svn", "log", "-r", r) + + // This is a complete hack. There must be a better way to do this. Pull + // requests welcome. When the reference isn't real you get a line of + // repeated - followed by an empty line. If the reference is real there + // is commit information in addition to those. So, we look for responses + // over 2 lines long. + lines := strings.Split(string(out), "\n") + if err == nil && len(lines) > 2 { + return true + } + + return false +} + +// IsDirty returns if the checkout has been modified from the checked +// out reference. +func (s *SvnRepo) IsDirty() bool { + out, err := s.RunFromDir("svn", "diff") + return err != nil || len(out) != 0 +} + +// CommitInfo retrieves metadata about a commit. +func (s *SvnRepo) CommitInfo(id string) (*CommitInfo, error) { + + // There are cases where Svn log doesn't return anything for HEAD or BASE. + // svn info does provide details for these but does not have elements like + // the commit message. + if id == "HEAD" || id == "BASE" { + type Commit struct { + Revision string `xml:"revision,attr"` + } + type Info struct { + Commit Commit `xml:"entry>commit"` + } + + out, err := s.RunFromDir("svn", "info", "-r", id, "--xml") + if err != nil { + return nil, NewLocalError("Unable to retrieve commit information", err, string(out)) + } + infos := &Info{} + err = xml.Unmarshal(out, &infos) + if err != nil { + return nil, NewLocalError("Unable to retrieve commit information", err, string(out)) + } + + id = infos.Commit.Revision + if id == "" { + return nil, ErrRevisionUnavailable + } + } + + out, err := s.RunFromDir("svn", "log", "-r", id, "--xml") + if err != nil { + return nil, NewRemoteError("Unable to retrieve commit information", err, string(out)) + } + + type Logentry struct { + Author string `xml:"author"` + Date string `xml:"date"` + Msg string `xml:"msg"` + } + type Log struct { + XMLName xml.Name `xml:"log"` + Logs []Logentry `xml:"logentry"` + } + + logs := &Log{} + err = xml.Unmarshal(out, &logs) + if err != nil { + return nil, NewLocalError("Unable to retrieve commit information", err, string(out)) + } + if len(logs.Logs) == 0 { + return nil, ErrRevisionUnavailable + } + + ci := &CommitInfo{ + Commit: id, + Author: logs.Logs[0].Author, + Message: logs.Logs[0].Msg, + } + + if len(logs.Logs[0].Date) > 0 { + ci.Date, err = time.Parse(time.RFC3339Nano, logs.Logs[0].Date) + if err != nil { + return nil, NewLocalError("Unable to retrieve commit information", err, string(out)) + } + } + + return ci, nil +} + +// TagsFromCommit retrieves tags from a commit id. +func (s *SvnRepo) TagsFromCommit(id string) ([]string, error) { + // Svn tags are a convention implemented as paths. See the details on the + // Tag() method for more information. + return []string{}, nil +} + +// Ping returns if remote location is accessible. +func (s *SvnRepo) Ping() bool { + _, err := s.run("svn", "--non-interactive", "info", s.Remote()) + return err == nil +} + +// ExportDir exports the current revision to the passed in directory. +func (s *SvnRepo) ExportDir(dir string) error { + + out, err := s.RunFromDir("svn", "export", ".", dir) + s.log(out) + if err != nil { + return NewLocalError("Unable to export source", err, string(out)) + } + + return nil +} + +// isUnableToCreateDir checks for an error in Init() to see if an error +// where the parent directory of the VCS local path doesn't exist. +func (s *SvnRepo) isUnableToCreateDir(err error) bool { + msg := err.Error() + return strings.HasPrefix(msg, "E000002") +} + +// detectRemoteFromInfoCommand finds the remote url from the `svn info` +// command's output without using a regex. We avoid regex because URLs +// are notoriously complex to accurately match with a regex and +// splitting strings is less complex and often faster +func detectRemoteFromInfoCommand(infoOut string) (string, error) { + sBytes := []byte(infoOut) + urlIndex := strings.Index(infoOut, "URL: ") + if urlIndex == -1 { + return "", fmt.Errorf("Remote not specified in svn info") + } + urlEndIndex := strings.Index(string(sBytes[urlIndex:]), "\n") + if urlEndIndex == -1 { + urlEndIndex = strings.Index(string(sBytes[urlIndex:]), "\r") + if urlEndIndex == -1 { + return "", fmt.Errorf("Unable to parse remote URL for svn info") + } + } + + return string(sBytes[(urlIndex + 5):(urlIndex + urlEndIndex)]), nil +} diff --git a/vendor/github.com/Masterminds/vcs/svn_test.go b/vendor/github.com/Masterminds/vcs/svn_test.go new file mode 100644 index 00000000..93fc139a --- /dev/null +++ b/vendor/github.com/Masterminds/vcs/svn_test.go @@ -0,0 +1,337 @@ +package vcs + +import ( + "io/ioutil" + "path/filepath" + "time" + //"log" + "os" + "testing" +) + +// To verify svn is working we perform integration testing +// with a known svn service. + +// Canary test to ensure SvnRepo implements the Repo interface. +var _ Repo = &SvnRepo{} + +func TestSvn(t *testing.T) { + + tempDir, err := ioutil.TempDir("", "go-vcs-svn-tests") + if err != nil { + t.Error(err) + } + defer func() { + err = os.RemoveAll(tempDir) + if err != nil { + t.Error(err) + } + }() + + repo, err := NewSvnRepo("https://github.com/Masterminds/VCSTestRepo/trunk", tempDir+string(os.PathSeparator)+"VCSTestRepo") + if err != nil { + t.Error(err) + } + + if repo.Vcs() != Svn { + t.Error("Svn is detecting the wrong type") + } + + // Check the basic getters. + if repo.Remote() != "https://github.com/Masterminds/VCSTestRepo/trunk" { + t.Error("Remote not set properly") + } + if repo.LocalPath() != tempDir+string(os.PathSeparator)+"VCSTestRepo" { + t.Error("Local disk location not set properly") + } + + //Logger = log.New(os.Stdout, "", log.LstdFlags) + + // Do an initial checkout. + err = repo.Get() + if err != nil { + t.Errorf("Unable to checkout SVN repo. Err was %s", err) + } + + // Verify SVN repo is a SVN repo + if !repo.CheckLocal() { + t.Error("Problem checking out repo or SVN CheckLocal is not working") + } + + // Verify an incorrect remote is caught when NewSvnRepo is used on an existing location + _, nrerr := NewSvnRepo("https://github.com/Masterminds/VCSTestRepo/unknownbranch", tempDir+"/VCSTestRepo") + if nrerr != ErrWrongRemote { + t.Error("ErrWrongRemote was not triggered for SVN") + } + + // Test internal lookup mechanism used outside of Hg specific functionality. + ltype, err := DetectVcsFromFS(tempDir + "/VCSTestRepo") + if err != nil { + t.Error("detectVcsFromFS unable to Svn repo") + } + if ltype != Svn { + t.Errorf("detectVcsFromFS detected %s instead of Svn type", ltype) + } + + // Commenting out auto-detection tests for SVN. NewRepo automatically detects + // GitHub to be a Git repo and that's an issue for this test. Need an + // SVN host that can autodetect from before using this test again. + // + // Test NewRepo on existing checkout. This should simply provide a working + // instance without error based on looking at the local directory. + // nrepo, nrerr := NewRepo("https://github.com/Masterminds/VCSTestRepo/trunk", tempDir+"/VCSTestRepo") + // if nrerr != nil { + // t.Error(nrerr) + // } + // // Verify the right oject is returned. It will check the local repo type. + // if nrepo.CheckLocal() == false { + // t.Error("Wrong version returned from NewRepo") + // } + + v, err := repo.Current() + if err != nil { + t.Errorf("Error trying Svn Current: %s", err) + } + if v != "HEAD" { + t.Errorf("Current failed to detect Svn on HEAD. Got version: %s", v) + } + + // Update the version to a previous version. + err = repo.UpdateVersion("r2") + if err != nil { + t.Errorf("Unable to update SVN repo version. Err was %s", err) + } + + // Use Version to verify we are on the right version. + v, err = repo.Version() + if v != "2" { + t.Error("Error checking checked SVN out version") + } + if err != nil { + t.Error(err) + } + + v, err = repo.Current() + if err != nil { + t.Errorf("Error trying Svn Current for ref: %s", err) + } + if v != "2" { + t.Errorf("Current failed to detect Svn on HEAD. Got version: %s", v) + } + + // Perform an update which should take up back to the latest version. + err = repo.Update() + if err != nil { + t.Error(err) + } + + // Make sure we are on a newer version because of the update. + v, err = repo.Version() + if v == "2" { + t.Error("Error with version. Still on old version. Update failed") + } + if err != nil { + t.Error(err) + } + + // Use Date to verify we are on the right commit. + d, err := repo.Date() + if d.Format(longForm) != "2015-07-29 13:47:03 +0000" { + t.Error("Error checking checked out Svn commit date") + } + if err != nil { + t.Error(err) + } + + tags, err := repo.Tags() + if err != nil { + t.Error(err) + } + if len(tags) != 0 { + t.Error("Svn is incorrectly returning tags") + } + + tags, err = repo.TagsFromCommit("2") + if err != nil { + t.Error(err) + } + if len(tags) != 0 { + t.Error("Svn is incorrectly returning tags for a commit") + } + + branches, err := repo.Branches() + if err != nil { + t.Error(err) + } + if len(branches) != 0 { + t.Error("Svn is incorrectly returning branches") + } + + if !repo.IsReference("r4") { + t.Error("Svn is reporting a reference is not one") + } + + if repo.IsReference("55") { + t.Error("Svn is reporting a non-existent reference is one") + } + + if repo.IsDirty() { + t.Error("Svn incorrectly reporting dirty") + } + + ci, err := repo.CommitInfo("2") + if err != nil { + t.Error(err) + } + if ci.Commit != "2" { + t.Error("Svn.CommitInfo wrong commit id") + } + if ci.Author != "matt.farina" { + t.Error("Svn.CommitInfo wrong author") + } + if ci.Message != "Update README.md" { + t.Error("Svn.CommitInfo wrong message") + } + ti, err := time.Parse(time.RFC3339Nano, "2015-07-29T13:46:20.000000Z") + if err != nil { + t.Error(err) + } + if !ti.Equal(ci.Date) { + t.Error("Svn.CommitInfo wrong date") + } + + _, err = repo.CommitInfo("555555555") + if err != ErrRevisionUnavailable { + t.Error("Svn didn't return expected ErrRevisionUnavailable") + } + + tempDir2, err := ioutil.TempDir("", "go-vcs-svn-tests-export") + if err != nil { + t.Fatalf("Error creating temp directory: %s", err) + } + defer func() { + err = os.RemoveAll(tempDir2) + if err != nil { + t.Error(err) + } + }() + + exportDir := filepath.Join(tempDir2, "src") + + err = repo.ExportDir(exportDir) + if err != nil { + t.Errorf("Unable to export Svn repo. Err was %s", err) + } + + _, err = os.Stat(filepath.Join(exportDir, "README.md")) + if err != nil { + t.Errorf("Error checking exported file in Svn: %s", err) + } + + _, err = os.Stat(filepath.Join(exportDir, string(repo.Vcs()))) + if err != nil { + if found := os.IsNotExist(err); !found { + t.Errorf("Error checking exported metadata in Svn: %s", err) + } + } else { + t.Error("Error checking Svn metadata. It exists.") + } +} + +func TestSvnCheckLocal(t *testing.T) { + // Verify repo.CheckLocal fails for non-SVN directories. + // TestSvn is already checking on a valid repo + tempDir, err := ioutil.TempDir("", "go-vcs-svn-tests") + if err != nil { + t.Error(err) + } + defer func() { + err = os.RemoveAll(tempDir) + if err != nil { + t.Error(err) + } + }() + + repo, _ := NewSvnRepo("", tempDir) + if repo.CheckLocal() { + t.Error("SVN CheckLocal does not identify non-SVN location") + } + + // Test NewRepo when there's no local. This should simply provide a working + // instance without error based on looking at the remote localtion. + _, nrerr := NewRepo("https://github.com/Masterminds/VCSTestRepo/trunk", tempDir+"/VCSTestRepo") + if nrerr != nil { + t.Error(nrerr) + } +} + +func TestSvnPing(t *testing.T) { + tempDir, err := ioutil.TempDir("", "go-vcs-svn-tests") + if err != nil { + t.Error(err) + } + defer func() { + err = os.RemoveAll(tempDir) + if err != nil { + t.Error(err) + } + }() + + repo, err := NewSvnRepo("https://github.com/Masterminds/VCSTestRepo/trunk", tempDir) + if err != nil { + t.Error(err) + } + + ping := repo.Ping() + if !ping { + t.Error("Svn unable to ping working repo") + } + + repo, err = NewSvnRepo("https://github.com/Masterminds/ihopethisneverexistsbecauseitshouldnt", tempDir) + if err != nil { + t.Error(err) + } + + ping = repo.Ping() + if ping { + t.Error("Svn got a ping response from when it should not have") + } +} + +func TestSvnInit(t *testing.T) { + tempDir, err := ioutil.TempDir("", "go-vcs-svn-tests") + remoteDir := tempDir + string(os.PathSeparator) + "remoteDir" + localDir := tempDir + string(os.PathSeparator) + "localDir" + if err != nil { + t.Error(err) + } + defer func() { + err = os.RemoveAll(tempDir) + if err != nil { + t.Error(err) + } + }() + + repo, err := NewSvnRepo(remoteDir, localDir) + if err != nil { + t.Error(err) + } + + err = repo.Init() + if err != nil { + t.Error(err) + } + + err = repo.Get() + if err != nil { + t.Error(err) + } + + v, err := repo.Version() + if err != nil { + t.Error(err) + } + if v != "0" { + t.Errorf("Svn Init returns wrong version: %s", v) + } +} diff --git a/vendor/github.com/Masterminds/vcs/vcs_local_lookup.go b/vendor/github.com/Masterminds/vcs/vcs_local_lookup.go new file mode 100644 index 00000000..09f6e22e --- /dev/null +++ b/vendor/github.com/Masterminds/vcs/vcs_local_lookup.go @@ -0,0 +1,46 @@ +package vcs + +import ( + "os" + "runtime" + "strings" +) + +// DetectVcsFromFS detects the type from the local path. +// Is there a better way to do this? +func DetectVcsFromFS(vcsPath string) (Type, error) { + + // There are cases under windows that a path could start with a / and it needs + // to be stripped. For example, a path such as /C:\foio\bar. + if runtime.GOOS == "windows" && strings.HasPrefix(vcsPath, "/") { + vcsPath = strings.TrimPrefix(vcsPath, "/") + } + + // When the local directory to the package doesn't exist + // it's not yet downloaded so we can't detect the type + // locally. + if _, err := os.Stat(vcsPath); os.IsNotExist(err) { + return "", ErrCannotDetectVCS + } + + separator := string(os.PathSeparator) + + // Walk through each of the different VCS types to see if + // one can be detected. Do this is order of guessed popularity. + if _, err := os.Stat(vcsPath + separator + ".git"); err == nil { + return Git, nil + } + if _, err := os.Stat(vcsPath + separator + ".svn"); err == nil { + return Svn, nil + } + if _, err := os.Stat(vcsPath + separator + ".hg"); err == nil { + return Hg, nil + } + if _, err := os.Stat(vcsPath + separator + ".bzr"); err == nil { + return Bzr, nil + } + + // If one was not already detected than we default to not finding it. + return "", ErrCannotDetectVCS + +} diff --git a/vendor/github.com/Masterminds/vcs/vcs_remote_lookup.go b/vendor/github.com/Masterminds/vcs/vcs_remote_lookup.go new file mode 100644 index 00000000..6689f957 --- /dev/null +++ b/vendor/github.com/Masterminds/vcs/vcs_remote_lookup.go @@ -0,0 +1,374 @@ +package vcs + +import ( + "encoding/json" + "encoding/xml" + "fmt" + "io" + "io/ioutil" + "net/http" + "net/url" + "regexp" + "strings" +) + +type vcsInfo struct { + host string + pattern string + vcs Type + addCheck func(m map[string]string, u *url.URL) (Type, error) + regex *regexp.Regexp +} + +// scpSyntaxRe matches the SCP-like addresses used by Git to access +// repositories by SSH. +var scpSyntaxRe = regexp.MustCompile(`^([a-zA-Z0-9_]+)@([a-zA-Z0-9._-]+):(.*)$`) + +var vcsList = []*vcsInfo{ + { + host: "github.com", + vcs: Git, + pattern: `^(github\.com[/|:][A-Za-z0-9_.\-]+/[A-Za-z0-9_.\-]+)(/[A-Za-z0-9_.\-]+)*$`, + }, + { + host: "bitbucket.org", + pattern: `^(bitbucket\.org/(?P[A-Za-z0-9_.\-]+/[A-Za-z0-9_.\-]+))(/[A-Za-z0-9_.\-]+)*$`, + addCheck: checkBitbucket, + }, + { + host: "launchpad.net", + pattern: `^(launchpad\.net/(([A-Za-z0-9_.\-]+)(/[A-Za-z0-9_.\-]+)?|~[A-Za-z0-9_.\-]+/(\+junk|[A-Za-z0-9_.\-]+)/[A-Za-z0-9_.\-]+))(/[A-Za-z0-9_.\-]+)*$`, + vcs: Bzr, + }, + { + host: "git.launchpad.net", + vcs: Git, + pattern: `^(git\.launchpad\.net/(([A-Za-z0-9_.\-]+)|~[A-Za-z0-9_.\-]+/(\+git|[A-Za-z0-9_.\-]+)/[A-Za-z0-9_.\-]+))$`, + }, + { + host: "hub.jazz.net", + vcs: Git, + pattern: `^(hub\.jazz\.net/git/[a-z0-9]+/[A-Za-z0-9_.\-]+)(/[A-Za-z0-9_.\-]+)*$`, + }, + { + host: "go.googlesource.com", + vcs: Git, + pattern: `^(go\.googlesource\.com/[A-Za-z0-9_.\-]+/?)$`, + }, + { + host: "git.openstack.org", + vcs: Git, + pattern: `^(git\.openstack\.org/[A-Za-z0-9_.\-]+/[A-Za-z0-9_.\-]+)$`, + }, + // If none of the previous detect the type they will fall to this looking for the type in a generic sense + // by the extension to the path. + { + addCheck: checkURL, + pattern: `\.(?Pgit|hg|svn|bzr)$`, + }, +} + +func init() { + // Precompile the regular expressions used to check VCS locations. + for _, v := range vcsList { + v.regex = regexp.MustCompile(v.pattern) + } +} + +// This function is really a hack around Go redirects rather than around +// something VCS related. Should this be moved to the glide project or a +// helper function? +func detectVcsFromRemote(vcsURL string) (Type, string, error) { + t, e := detectVcsFromURL(vcsURL) + if e == nil { + return t, vcsURL, nil + } else if e != ErrCannotDetectVCS { + return NoVCS, "", e + } + + // Pages like https://golang.org/x/net provide an html document with + // meta tags containing a location to work with. The go tool uses + // a meta tag with the name go-import which is what we use here. + // godoc.org also has one call go-source that we do not need to use. + // The value of go-import is in the form "prefix vcs repo". The prefix + // should match the vcsURL and the repo is a location that can be + // checked out. Note, to get the html document you you need to add + // ?go-get=1 to the url. + u, err := url.Parse(vcsURL) + if err != nil { + return NoVCS, "", err + } + if u.RawQuery == "" { + u.RawQuery = "go-get=1" + } else { + u.RawQuery = u.RawQuery + "+go-get=1" + } + checkURL := u.String() + resp, err := http.Get(checkURL) + if err != nil { + return NoVCS, "", ErrCannotDetectVCS + } + defer resp.Body.Close() + if resp.StatusCode < 200 || resp.StatusCode >= 300 { + if resp.StatusCode == 404 { + return NoVCS, "", NewRemoteError(fmt.Sprintf("%s Not Found", vcsURL), nil, "") + } else if resp.StatusCode == 401 || resp.StatusCode == 403 { + return NoVCS, "", NewRemoteError(fmt.Sprintf("%s Access Denied", vcsURL), nil, "") + } + return NoVCS, "", ErrCannotDetectVCS + } + + t, nu, err := parseImportFromBody(u, resp.Body) + if err != nil { + // TODO(mattfarina): Log the parsing error + return NoVCS, "", ErrCannotDetectVCS + } else if t == "" || nu == "" { + return NoVCS, "", ErrCannotDetectVCS + } + + return t, nu, nil +} + +// From a remote vcs url attempt to detect the VCS. +func detectVcsFromURL(vcsURL string) (Type, error) { + + var u *url.URL + var err error + + if m := scpSyntaxRe.FindStringSubmatch(vcsURL); m != nil { + // Match SCP-like syntax and convert it to a URL. + // Eg, "git@github.com:user/repo" becomes + // "ssh://git@github.com/user/repo". + u = &url.URL{ + Scheme: "ssh", + User: url.User(m[1]), + Host: m[2], + Path: "/" + m[3], + } + } else { + u, err = url.Parse(vcsURL) + if err != nil { + return "", err + } + } + + // Detect file schemes + if u.Scheme == "file" { + return DetectVcsFromFS(u.Path) + } + + if u.Host == "" { + return "", ErrCannotDetectVCS + } + + // Try to detect from the scheme + switch u.Scheme { + case "git+ssh": + return Git, nil + case "git": + return Git, nil + case "bzr+ssh": + return Bzr, nil + case "svn+ssh": + return Svn, nil + } + + // Try to detect from known hosts, such as Github + for _, v := range vcsList { + if v.host != "" && v.host != u.Host { + continue + } + + // Make sure the pattern matches for an actual repo location. For example, + // we should fail if the VCS listed is github.com/masterminds as that's + // not actually a repo. + uCheck := u.Host + u.Path + m := v.regex.FindStringSubmatch(uCheck) + if m == nil { + if v.host != "" { + return "", ErrCannotDetectVCS + } + + continue + } + + // If we are here the host matches. If the host has a singular + // VCS type, such as Github, we can return the type right away. + if v.vcs != "" { + return v.vcs, nil + } + + // Run additional checks to determine try and determine the repo + // for the matched service. + info := make(map[string]string) + for i, name := range v.regex.SubexpNames() { + if name != "" { + info[name] = m[i] + } + } + t, err := v.addCheck(info, u) + if err != nil { + switch err.(type) { + case *RemoteError: + return "", err + } + return "", ErrCannotDetectVCS + } + + return t, nil + } + + // Attempt to ascertain from the username passed in. + if u.User != nil { + un := u.User.Username() + if un == "git" { + return Git, nil + } else if un == "hg" { + return Hg, nil + } + } + + // Unable to determine the vcs from the url. + return "", ErrCannotDetectVCS +} + +// Figure out the type for Bitbucket by the passed in information +// or via the public API. +func checkBitbucket(i map[string]string, ul *url.URL) (Type, error) { + + // Fast path for ssh urls where we may not even be able to + // anonymously get details from the API. + if ul.User != nil { + un := ul.User.Username() + if un == "git" { + return Git, nil + } else if un == "hg" { + return Hg, nil + } + } + + // The part of the response we care about. + var response struct { + SCM Type `json:"scm"` + } + + u := expand(i, "https://api.bitbucket.org/1.0/repositories/{name}") + data, err := get(u) + if err != nil { + return "", err + } + + if err := json.Unmarshal(data, &response); err != nil { + return "", fmt.Errorf("Decoding error %s: %v", u, err) + } + + return response.SCM, nil + +} + +// Expect a type key on i with the exact type detected from the regex. +func checkURL(i map[string]string, u *url.URL) (Type, error) { + return Type(i["type"]), nil +} + +func get(url string) ([]byte, error) { + resp, err := http.Get(url) + if err != nil { + return nil, err + } + defer resp.Body.Close() + if resp.StatusCode != 200 { + if resp.StatusCode == 404 { + return nil, NewRemoteError("Not Found", err, resp.Status) + } else if resp.StatusCode == 401 || resp.StatusCode == 403 { + return nil, NewRemoteError("Access Denied", err, resp.Status) + } + return nil, fmt.Errorf("%s: %s", url, resp.Status) + } + b, err := ioutil.ReadAll(resp.Body) + if err != nil { + return nil, fmt.Errorf("%s: %v", url, err) + } + return b, nil +} + +func expand(match map[string]string, s string) string { + for k, v := range match { + s = strings.Replace(s, "{"+k+"}", v, -1) + } + return s +} + +func parseImportFromBody(ur *url.URL, r io.ReadCloser) (tp Type, u string, err error) { + d := xml.NewDecoder(r) + d.CharsetReader = charsetReader + d.Strict = false + var t xml.Token + for { + t, err = d.Token() + if err != nil { + if err == io.EOF { + // When the end is reached it could not detect a VCS if it + // got here. + err = ErrCannotDetectVCS + } + return + } + if e, ok := t.(xml.StartElement); ok && strings.EqualFold(e.Name.Local, "body") { + return + } + if e, ok := t.(xml.EndElement); ok && strings.EqualFold(e.Name.Local, "head") { + return + } + e, ok := t.(xml.StartElement) + if !ok || !strings.EqualFold(e.Name.Local, "meta") { + continue + } + if attrValue(e.Attr, "name") != "go-import" { + continue + } + if f := strings.Fields(attrValue(e.Attr, "content")); len(f) == 3 { + // If the prefix supplied by the remote system isn't a prefix to the + // url we're fetching continue to look for other imports. + // This will work for exact matches and prefixes. For example, + // golang.org/x/net as a prefix will match for golang.org/x/net and + // golang.org/x/net/context. + vcsURL := ur.Host + ur.Path + if !strings.HasPrefix(vcsURL, f[0]) { + continue + } else { + switch Type(f[1]) { + case Git: + tp = Git + case Svn: + tp = Svn + case Bzr: + tp = Bzr + case Hg: + tp = Hg + } + + u = f[2] + return + } + } + } +} + +func charsetReader(charset string, input io.Reader) (io.Reader, error) { + switch strings.ToLower(charset) { + case "ascii": + return input, nil + default: + return nil, fmt.Errorf("can't decode XML document using charset %q", charset) + } +} + +func attrValue(attrs []xml.Attr, name string) string { + for _, a := range attrs { + if strings.EqualFold(a.Name.Local, name) { + return a.Value + } + } + return "" +} diff --git a/vendor/github.com/Masterminds/vcs/vcs_remote_lookup_test.go b/vendor/github.com/Masterminds/vcs/vcs_remote_lookup_test.go new file mode 100644 index 00000000..938cb0eb --- /dev/null +++ b/vendor/github.com/Masterminds/vcs/vcs_remote_lookup_test.go @@ -0,0 +1,137 @@ +package vcs + +import ( + "io/ioutil" + "os" + "os/exec" + "runtime" + "strings" + "testing" +) + +func TestVCSLookup(t *testing.T) { + // TODO: Expand to make sure it detected the right vcs. + urlList := map[string]struct { + work bool + t Type + }{ + "https://github.com/masterminds": {work: false, t: Git}, + "https://github.com/Masterminds/VCSTestRepo": {work: true, t: Git}, + "https://bitbucket.org/mattfarina/testhgrepo": {work: true, t: Hg}, + "https://bitbucket.org/mattfarina/repo-does-not-exist": {work: false, t: Hg}, + "https://bitbucket.org/mattfarina/private-repo-for-vcs-testing": {work: false, t: Hg}, + "https://launchpad.net/govcstestbzrrepo/trunk": {work: true, t: Bzr}, + "https://launchpad.net/~mattfarina/+junk/mygovcstestbzrrepo": {work: true, t: Bzr}, + "https://launchpad.net/~mattfarina/+junk/mygovcstestbzrrepo/trunk": {work: true, t: Bzr}, + "https://git.launchpad.net/govcstestgitrepo": {work: true, t: Git}, + "https://git.launchpad.net/~mattfarina/+git/mygovcstestgitrepo": {work: true, t: Git}, + "https://hub.jazz.net/git/user1/pkgname": {work: true, t: Git}, + "https://hub.jazz.net/git/user1/pkgname/subpkg/subpkg/subpkg": {work: true, t: Git}, + "https://hubs.jazz.net/git/user1/pkgname": {work: false, t: Git}, + "https://example.com/foo/bar.git": {work: true, t: Git}, + "https://example.com/foo/bar.svn": {work: true, t: Svn}, + "https://example.com/foo/bar/baz.bzr": {work: true, t: Bzr}, + "https://example.com/foo/bar/baz.hg": {work: true, t: Hg}, + "https://gopkg.in/tomb.v1": {work: true, t: Git}, + "https://golang.org/x/net": {work: true, t: Git}, + "https://speter.net/go/exp/math/dec/inf": {work: true, t: Git}, + "https://git.openstack.org/foo/bar": {work: true, t: Git}, + "git@github.com:Masterminds/vcs.git": {work: true, t: Git}, + "git@example.com:foo.git": {work: true, t: Git}, + "ssh://hg@bitbucket.org/mattfarina/testhgrepo": {work: true, t: Hg}, + "git@bitbucket.org:mattfarina/glide-bitbucket-example.git": {work: true, t: Git}, + "git+ssh://example.com/foo/bar": {work: true, t: Git}, + "git://example.com/foo/bar": {work: true, t: Git}, + "bzr+ssh://example.com/foo/bar": {work: true, t: Bzr}, + "svn+ssh://example.com/foo/bar": {work: true, t: Svn}, + "git@example.com:foo/bar": {work: true, t: Git}, + "hg@example.com:foo/bar": {work: true, t: Hg}, + } + + for u, c := range urlList { + ty, _, err := detectVcsFromRemote(u) + if err == nil && !c.work { + t.Errorf("Error detecting VCS from URL(%s)", u) + } + + if err == ErrCannotDetectVCS && c.work { + t.Errorf("Error detecting VCS from URL(%s)", u) + } + + if err != nil && c.work { + t.Errorf("Error detecting VCS from URL(%s): %s", u, err) + } + + if err != nil && + err != ErrCannotDetectVCS && + !strings.HasSuffix(err.Error(), "Not Found") && + !strings.HasSuffix(err.Error(), "Access Denied") && + !c.work { + t.Errorf("Unexpected error returned (%s): %s", u, err) + } + + if c.work && ty != c.t { + t.Errorf("Incorrect VCS type returned(%s)", u) + } + } +} + +func TestVCSFileLookup(t *testing.T) { + tempDir, err := ioutil.TempDir("", "go-vcs-file-lookup-tests") + if err != nil { + t.Error(err) + } + defer func() { + err = os.RemoveAll(tempDir) + if err != nil { + t.Error(err) + } + }() + + _, err = exec.Command("git", "init", tempDir).CombinedOutput() + if err != nil { + t.Error(err) + } + + // On Windows it should be file:// followed by /C:\for\bar. That / before + // the drive needs to be included in testing. + var pth string + if runtime.GOOS == "windows" { + pth = "file:///" + tempDir + } else { + pth = "file://" + tempDir + } + ty, _, err := detectVcsFromRemote(pth) + + if err != nil { + t.Errorf("Unable to detect file:// path: %s", err) + } + + if ty != Git { + t.Errorf("Detected wrong type from file:// path. Found type %v", ty) + } +} + +func TestNotFound(t *testing.T) { + _, _, err := detectVcsFromRemote("https://mattfarina.com/notfound") + if err == nil || !strings.HasSuffix(err.Error(), " Not Found") { + t.Errorf("Failed to find not found repo") + } + + _, err = NewRepo("https://mattfarina.com/notfound", "") + if err == nil || !strings.HasSuffix(err.Error(), " Not Found") { + t.Errorf("Failed to find not found repo") + } +} + +func TestAccessDenied(t *testing.T) { + _, _, err := detectVcsFromRemote("https://bitbucket.org/mattfarina/private-repo-for-vcs-testing") + if err == nil || err.Error() != "Access Denied" { + t.Errorf("Failed to detect access denied") + } + + _, err = NewRepo("https://bitbucket.org/mattfarina/private-repo-for-vcs-testing", "") + if err == nil || err.Error() != "Access Denied" { + t.Errorf("Failed to detect access denied") + } +} diff --git a/vendor/github.com/armon/go-radix/.gitignore b/vendor/github.com/armon/go-radix/.gitignore new file mode 100644 index 00000000..00268614 --- /dev/null +++ b/vendor/github.com/armon/go-radix/.gitignore @@ -0,0 +1,22 @@ +# 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 diff --git a/vendor/github.com/armon/go-radix/.travis.yml b/vendor/github.com/armon/go-radix/.travis.yml new file mode 100644 index 00000000..1a0bbea6 --- /dev/null +++ b/vendor/github.com/armon/go-radix/.travis.yml @@ -0,0 +1,3 @@ +language: go +go: + - tip diff --git a/vendor/github.com/armon/go-radix/LICENSE b/vendor/github.com/armon/go-radix/LICENSE new file mode 100644 index 00000000..a5df10e6 --- /dev/null +++ b/vendor/github.com/armon/go-radix/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2014 Armon Dadgar + +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/armon/go-radix/README.md b/vendor/github.com/armon/go-radix/README.md new file mode 100644 index 00000000..26f42a28 --- /dev/null +++ b/vendor/github.com/armon/go-radix/README.md @@ -0,0 +1,38 @@ +go-radix [![Build Status](https://travis-ci.org/armon/go-radix.png)](https://travis-ci.org/armon/go-radix) +========= + +Provides the `radix` package that implements a [radix tree](http://en.wikipedia.org/wiki/Radix_tree). +The package only provides a single `Tree` implementation, optimized for sparse nodes. + +As a radix tree, it provides the following: + * O(k) operations. In many cases, this can be faster than a hash table since + the hash function is an O(k) operation, and hash tables have very poor cache locality. + * Minimum / Maximum value lookups + * Ordered iteration + +For an immutable variant, see [go-immutable-radix](https://github.com/hashicorp/go-immutable-radix). + +Documentation +============= + +The full documentation is available on [Godoc](http://godoc.org/github.com/armon/go-radix). + +Example +======= + +Below is a simple example of usage + +```go +// Create a tree +r := radix.New() +r.Insert("foo", 1) +r.Insert("bar", 2) +r.Insert("foobar", 2) + +// Find the longest prefix match +m, _, _ := r.LongestPrefix("foozip") +if m != "foo" { + panic("should be foo") +} +``` + diff --git a/vendor/github.com/armon/go-radix/radix.go b/vendor/github.com/armon/go-radix/radix.go new file mode 100644 index 00000000..f9655a12 --- /dev/null +++ b/vendor/github.com/armon/go-radix/radix.go @@ -0,0 +1,543 @@ +package radix + +import ( + "sort" + "strings" +) + +// WalkFn is used when walking the tree. Takes a +// key and value, returning if iteration should +// be terminated. +type WalkFn func(s string, v interface{}) bool + +// leafNode is used to represent a value +type leafNode struct { + key string + val interface{} +} + +// edge is used to represent an edge node +type edge struct { + label byte + node *node +} + +type node struct { + // leaf is used to store possible leaf + leaf *leafNode + + // prefix is the common prefix we ignore + prefix string + + // Edges should be stored in-order for iteration. + // We avoid a fully materialized slice to save memory, + // since in most cases we expect to be sparse + edges edges +} + +func (n *node) isLeaf() bool { + return n.leaf != nil +} + +func (n *node) addEdge(e edge) { + n.edges = append(n.edges, e) + n.edges.Sort() +} + +func (n *node) replaceEdge(e edge) { + num := len(n.edges) + idx := sort.Search(num, func(i int) bool { + return n.edges[i].label >= e.label + }) + if idx < num && n.edges[idx].label == e.label { + n.edges[idx].node = e.node + return + } + panic("replacing missing edge") +} + +func (n *node) getEdge(label byte) *node { + num := len(n.edges) + idx := sort.Search(num, func(i int) bool { + return n.edges[i].label >= label + }) + if idx < num && n.edges[idx].label == label { + return n.edges[idx].node + } + return nil +} + +func (n *node) delEdge(label byte) { + num := len(n.edges) + idx := sort.Search(num, func(i int) bool { + return n.edges[i].label >= label + }) + if idx < num && n.edges[idx].label == label { + copy(n.edges[idx:], n.edges[idx+1:]) + n.edges[len(n.edges)-1] = edge{} + n.edges = n.edges[:len(n.edges)-1] + } +} + +type edges []edge + +func (e edges) Len() int { + return len(e) +} + +func (e edges) Less(i, j int) bool { + return e[i].label < e[j].label +} + +func (e edges) Swap(i, j int) { + e[i], e[j] = e[j], e[i] +} + +func (e edges) Sort() { + sort.Sort(e) +} + +// Tree implements a radix tree. This can be treated as a +// Dictionary abstract data type. The main advantage over +// a standard hash map is prefix-based lookups and +// ordered iteration, +type Tree struct { + root *node + size int +} + +// New returns an empty Tree +func New() *Tree { + return NewFromMap(nil) +} + +// NewFromMap returns a new tree containing the keys +// from an existing map +func NewFromMap(m map[string]interface{}) *Tree { + t := &Tree{root: &node{}} + for k, v := range m { + t.Insert(k, v) + } + return t +} + +// Len is used to return the number of elements in the tree +func (t *Tree) Len() int { + return t.size +} + +// longestPrefix finds the length of the shared prefix +// of two strings +func longestPrefix(k1, k2 string) int { + max := len(k1) + if l := len(k2); l < max { + max = l + } + var i int + for i = 0; i < max; i++ { + if k1[i] != k2[i] { + break + } + } + return i +} + +// Insert is used to add a newentry or update +// an existing entry. Returns if updated. +func (t *Tree) Insert(s string, v interface{}) (interface{}, bool) { + var parent *node + n := t.root + search := s + for { + // Handle key exhaution + if len(search) == 0 { + if n.isLeaf() { + old := n.leaf.val + n.leaf.val = v + return old, true + } + + n.leaf = &leafNode{ + key: s, + val: v, + } + t.size++ + return nil, false + } + + // Look for the edge + parent = n + n = n.getEdge(search[0]) + + // No edge, create one + if n == nil { + e := edge{ + label: search[0], + node: &node{ + leaf: &leafNode{ + key: s, + val: v, + }, + prefix: search, + }, + } + parent.addEdge(e) + t.size++ + return nil, false + } + + // Determine longest prefix of the search key on match + commonPrefix := longestPrefix(search, n.prefix) + if commonPrefix == len(n.prefix) { + search = search[commonPrefix:] + continue + } + + // Split the node + t.size++ + child := &node{ + prefix: search[:commonPrefix], + } + parent.replaceEdge(edge{ + label: search[0], + node: child, + }) + + // Restore the existing node + child.addEdge(edge{ + label: n.prefix[commonPrefix], + node: n, + }) + n.prefix = n.prefix[commonPrefix:] + + // Create a new leaf node + leaf := &leafNode{ + key: s, + val: v, + } + + // If the new key is a subset, add to to this node + search = search[commonPrefix:] + if len(search) == 0 { + child.leaf = leaf + return nil, false + } + + // Create a new edge for the node + child.addEdge(edge{ + label: search[0], + node: &node{ + leaf: leaf, + prefix: search, + }, + }) + return nil, false + } +} + +// Delete is used to delete a key, returning the previous +// value and if it was deleted +func (t *Tree) Delete(s string) (interface{}, bool) { + var parent *node + var label byte + n := t.root + search := s + for { + // Check for key exhaution + if len(search) == 0 { + if !n.isLeaf() { + break + } + goto DELETE + } + + // Look for an edge + parent = n + label = search[0] + n = n.getEdge(label) + if n == nil { + break + } + + // Consume the search prefix + if strings.HasPrefix(search, n.prefix) { + search = search[len(n.prefix):] + } else { + break + } + } + return nil, false + +DELETE: + // Delete the leaf + leaf := n.leaf + n.leaf = nil + t.size-- + + // Check if we should delete this node from the parent + if parent != nil && len(n.edges) == 0 { + parent.delEdge(label) + } + + // Check if we should merge this node + if n != t.root && len(n.edges) == 1 { + n.mergeChild() + } + + // Check if we should merge the parent's other child + if parent != nil && parent != t.root && len(parent.edges) == 1 && !parent.isLeaf() { + parent.mergeChild() + } + + return leaf.val, true +} + +// DeletePrefix is used to delete the subtree under a prefix +// Returns how many nodes were deleted +// Use this to delete large subtrees efficiently +func (t *Tree) DeletePrefix(s string) int { + return t.deletePrefix(nil, t.root, s) +} + +// delete does a recursive deletion +func (t *Tree) deletePrefix(parent, n *node, prefix string) int { + // Check for key exhaustion + if len(prefix) == 0 { + // Remove the leaf node + subTreeSize := 0 + //recursively walk from all edges of the node to be deleted + recursiveWalk(n, func(s string, v interface{}) bool { + subTreeSize++ + return false + }) + if n.isLeaf() { + n.leaf = nil + } + n.edges = nil // deletes the entire subtree + + // Check if we should merge the parent's other child + if parent != nil && parent != t.root && len(parent.edges) == 1 && !parent.isLeaf() { + parent.mergeChild() + } + t.size -= subTreeSize + return subTreeSize + } + + // Look for an edge + label := prefix[0] + child := n.getEdge(label) + if child == nil || (!strings.HasPrefix(child.prefix, prefix) && !strings.HasPrefix(prefix, child.prefix)) { + return 0 + } + + // Consume the search prefix + if len(child.prefix) > len(prefix) { + prefix = prefix[len(prefix):] + } else { + prefix = prefix[len(child.prefix):] + } + return t.deletePrefix(n, child, prefix) +} + +func (n *node) mergeChild() { + e := n.edges[0] + child := e.node + n.prefix = n.prefix + child.prefix + n.leaf = child.leaf + n.edges = child.edges +} + +// Get is used to lookup a specific key, returning +// the value and if it was found +func (t *Tree) Get(s string) (interface{}, bool) { + n := t.root + search := s + for { + // Check for key exhaution + if len(search) == 0 { + if n.isLeaf() { + return n.leaf.val, true + } + break + } + + // Look for an edge + n = n.getEdge(search[0]) + if n == nil { + break + } + + // Consume the search prefix + if strings.HasPrefix(search, n.prefix) { + search = search[len(n.prefix):] + } else { + break + } + } + return nil, false +} + +// LongestPrefix is like Get, but instead of an +// exact match, it will return the longest prefix match. +func (t *Tree) LongestPrefix(s string) (string, interface{}, bool) { + var last *leafNode + n := t.root + search := s + for { + // Look for a leaf node + if n.isLeaf() { + last = n.leaf + } + + // Check for key exhaution + if len(search) == 0 { + break + } + + // Look for an edge + n = n.getEdge(search[0]) + if n == nil { + break + } + + // Consume the search prefix + if strings.HasPrefix(search, n.prefix) { + search = search[len(n.prefix):] + } else { + break + } + } + if last != nil { + return last.key, last.val, true + } + return "", nil, false +} + +// Minimum is used to return the minimum value in the tree +func (t *Tree) Minimum() (string, interface{}, bool) { + n := t.root + for { + if n.isLeaf() { + return n.leaf.key, n.leaf.val, true + } + if len(n.edges) > 0 { + n = n.edges[0].node + } else { + break + } + } + return "", nil, false +} + +// Maximum is used to return the maximum value in the tree +func (t *Tree) Maximum() (string, interface{}, bool) { + n := t.root + for { + if num := len(n.edges); num > 0 { + n = n.edges[num-1].node + continue + } + if n.isLeaf() { + return n.leaf.key, n.leaf.val, true + } + break + } + return "", nil, false +} + +// Walk is used to walk the tree +func (t *Tree) Walk(fn WalkFn) { + recursiveWalk(t.root, fn) +} + +// WalkPrefix is used to walk the tree under a prefix +func (t *Tree) WalkPrefix(prefix string, fn WalkFn) { + n := t.root + search := prefix + for { + // Check for key exhaution + if len(search) == 0 { + recursiveWalk(n, fn) + return + } + + // Look for an edge + n = n.getEdge(search[0]) + if n == nil { + break + } + + // Consume the search prefix + if strings.HasPrefix(search, n.prefix) { + search = search[len(n.prefix):] + + } else if strings.HasPrefix(n.prefix, search) { + // Child may be under our search prefix + recursiveWalk(n, fn) + return + } else { + break + } + } + +} + +// WalkPath is used to walk the tree, but only visiting nodes +// from the root down to a given leaf. Where WalkPrefix walks +// all the entries *under* the given prefix, this walks the +// entries *above* the given prefix. +func (t *Tree) WalkPath(path string, fn WalkFn) { + n := t.root + search := path + for { + // Visit the leaf values if any + if n.leaf != nil && fn(n.leaf.key, n.leaf.val) { + return + } + + // Check for key exhaution + if len(search) == 0 { + return + } + + // Look for an edge + n = n.getEdge(search[0]) + if n == nil { + return + } + + // Consume the search prefix + if strings.HasPrefix(search, n.prefix) { + search = search[len(n.prefix):] + } else { + break + } + } +} + +// recursiveWalk is used to do a pre-order walk of a node +// recursively. Returns true if the walk should be aborted +func recursiveWalk(n *node, fn WalkFn) bool { + // Visit the leaf values if any + if n.leaf != nil && fn(n.leaf.key, n.leaf.val) { + return true + } + + // Recurse on the children + for _, e := range n.edges { + if recursiveWalk(e.node, fn) { + return true + } + } + return false +} + +// ToMap is used to walk the tree and convert it into a map +func (t *Tree) ToMap() map[string]interface{} { + out := make(map[string]interface{}, t.size) + t.Walk(func(k string, v interface{}) bool { + out[k] = v + return false + }) + return out +} diff --git a/vendor/github.com/armon/go-radix/radix_test.go b/vendor/github.com/armon/go-radix/radix_test.go new file mode 100644 index 00000000..a7a4eab3 --- /dev/null +++ b/vendor/github.com/armon/go-radix/radix_test.go @@ -0,0 +1,359 @@ +package radix + +import ( + crand "crypto/rand" + "fmt" + "reflect" + "sort" + "testing" +) + +func TestRadix(t *testing.T) { + var min, max string + inp := make(map[string]interface{}) + for i := 0; i < 1000; i++ { + gen := generateUUID() + inp[gen] = i + if gen < min || i == 0 { + min = gen + } + if gen > max || i == 0 { + max = gen + } + } + + r := NewFromMap(inp) + if r.Len() != len(inp) { + t.Fatalf("bad length: %v %v", r.Len(), len(inp)) + } + + r.Walk(func(k string, v interface{}) bool { + println(k) + return false + }) + + for k, v := range inp { + out, ok := r.Get(k) + if !ok { + t.Fatalf("missing key: %v", k) + } + if out != v { + t.Fatalf("value mis-match: %v %v", out, v) + } + } + + // Check min and max + outMin, _, _ := r.Minimum() + if outMin != min { + t.Fatalf("bad minimum: %v %v", outMin, min) + } + outMax, _, _ := r.Maximum() + if outMax != max { + t.Fatalf("bad maximum: %v %v", outMax, max) + } + + for k, v := range inp { + out, ok := r.Delete(k) + if !ok { + t.Fatalf("missing key: %v", k) + } + if out != v { + t.Fatalf("value mis-match: %v %v", out, v) + } + } + if r.Len() != 0 { + t.Fatalf("bad length: %v", r.Len()) + } +} + +func TestRoot(t *testing.T) { + r := New() + _, ok := r.Delete("") + if ok { + t.Fatalf("bad") + } + _, ok = r.Insert("", true) + if ok { + t.Fatalf("bad") + } + val, ok := r.Get("") + if !ok || val != true { + t.Fatalf("bad: %v", val) + } + val, ok = r.Delete("") + if !ok || val != true { + t.Fatalf("bad: %v", val) + } +} + +func TestDelete(t *testing.T) { + + r := New() + + s := []string{"", "A", "AB"} + + for _, ss := range s { + r.Insert(ss, true) + } + + for _, ss := range s { + _, ok := r.Delete(ss) + if !ok { + t.Fatalf("bad %q", ss) + } + } +} + +func TestDeletePrefix(t *testing.T) { + type exp struct { + inp[] string + prefix string + out[] string + numDeleted int + } + + cases := []exp{ + {[]string{"", "A", "AB", "ABC", "R", "S"}, "A", []string{"", "R", "S"}, 3}, + {[]string{"", "A", "AB", "ABC", "R", "S"}, "ABC", []string{"", "A", "AB", "R", "S"}, 1}, + {[]string{"", "A", "AB", "ABC", "R", "S"}, "", []string{}, 6}, + {[]string{"", "A", "AB", "ABC", "R", "S"}, "S", []string{"", "A", "AB", "ABC", "R"}, 1}, + {[]string{"", "A", "AB", "ABC", "R", "S"}, "SS", []string{"", "A", "AB", "ABC", "R", "S"}, 0}, + } + + for _, test := range cases { + r := New() + for _, ss := range test.inp { + r.Insert(ss, true) + } + + deleted := r.DeletePrefix(test.prefix) + if deleted != test.numDeleted { + t.Fatalf("Bad delete, expected %v to be deleted but got %v", test.numDeleted, deleted) + } + + out := []string{} + fn := func(s string, v interface{}) bool { + out = append(out, s) + return false + } + r.Walk(fn) + + if !reflect.DeepEqual(out, test.out) { + t.Fatalf("mis-match: %v %v", out, test.out) + } + } +} + +func TestLongestPrefix(t *testing.T) { + r := New() + + keys := []string{ + "", + "foo", + "foobar", + "foobarbaz", + "foobarbazzip", + "foozip", + } + for _, k := range keys { + r.Insert(k, nil) + } + if r.Len() != len(keys) { + t.Fatalf("bad len: %v %v", r.Len(), len(keys)) + } + + type exp struct { + inp string + out string + } + cases := []exp{ + {"a", ""}, + {"abc", ""}, + {"fo", ""}, + {"foo", "foo"}, + {"foob", "foo"}, + {"foobar", "foobar"}, + {"foobarba", "foobar"}, + {"foobarbaz", "foobarbaz"}, + {"foobarbazzi", "foobarbaz"}, + {"foobarbazzip", "foobarbazzip"}, + {"foozi", "foo"}, + {"foozip", "foozip"}, + {"foozipzap", "foozip"}, + } + for _, test := range cases { + m, _, ok := r.LongestPrefix(test.inp) + if !ok { + t.Fatalf("no match: %v", test) + } + if m != test.out { + t.Fatalf("mis-match: %v %v", m, test) + } + } +} + +func TestWalkPrefix(t *testing.T) { + r := New() + + keys := []string{ + "foobar", + "foo/bar/baz", + "foo/baz/bar", + "foo/zip/zap", + "zipzap", + } + for _, k := range keys { + r.Insert(k, nil) + } + if r.Len() != len(keys) { + t.Fatalf("bad len: %v %v", r.Len(), len(keys)) + } + + type exp struct { + inp string + out []string + } + cases := []exp{ + { + "f", + []string{"foobar", "foo/bar/baz", "foo/baz/bar", "foo/zip/zap"}, + }, + { + "foo", + []string{"foobar", "foo/bar/baz", "foo/baz/bar", "foo/zip/zap"}, + }, + { + "foob", + []string{"foobar"}, + }, + { + "foo/", + []string{"foo/bar/baz", "foo/baz/bar", "foo/zip/zap"}, + }, + { + "foo/b", + []string{"foo/bar/baz", "foo/baz/bar"}, + }, + { + "foo/ba", + []string{"foo/bar/baz", "foo/baz/bar"}, + }, + { + "foo/bar", + []string{"foo/bar/baz"}, + }, + { + "foo/bar/baz", + []string{"foo/bar/baz"}, + }, + { + "foo/bar/bazoo", + []string{}, + }, + { + "z", + []string{"zipzap"}, + }, + } + + for _, test := range cases { + out := []string{} + fn := func(s string, v interface{}) bool { + out = append(out, s) + return false + } + r.WalkPrefix(test.inp, fn) + sort.Strings(out) + sort.Strings(test.out) + if !reflect.DeepEqual(out, test.out) { + t.Fatalf("mis-match: %v %v", out, test.out) + } + } +} + +func TestWalkPath(t *testing.T) { + r := New() + + keys := []string{ + "foo", + "foo/bar", + "foo/bar/baz", + "foo/baz/bar", + "foo/zip/zap", + "zipzap", + } + for _, k := range keys { + r.Insert(k, nil) + } + if r.Len() != len(keys) { + t.Fatalf("bad len: %v %v", r.Len(), len(keys)) + } + + type exp struct { + inp string + out []string + } + cases := []exp{ + { + "f", + []string{}, + }, + { + "foo", + []string{"foo"}, + }, + { + "foo/", + []string{"foo"}, + }, + { + "foo/ba", + []string{"foo"}, + }, + { + "foo/bar", + []string{"foo", "foo/bar"}, + }, + { + "foo/bar/baz", + []string{"foo", "foo/bar", "foo/bar/baz"}, + }, + { + "foo/bar/bazoo", + []string{"foo", "foo/bar", "foo/bar/baz"}, + }, + { + "z", + []string{}, + }, + } + + for _, test := range cases { + out := []string{} + fn := func(s string, v interface{}) bool { + out = append(out, s) + return false + } + r.WalkPath(test.inp, fn) + sort.Strings(out) + sort.Strings(test.out) + if !reflect.DeepEqual(out, test.out) { + t.Fatalf("mis-match: %v %v", out, test.out) + } + } +} + +// generateUUID is used to generate a random UUID +func generateUUID() string { + buf := make([]byte, 16) + if _, err := crand.Read(buf); err != nil { + panic(fmt.Errorf("failed to read random bytes: %v", err)) + } + + return fmt.Sprintf("%08x-%04x-%04x-%04x-%12x", + buf[0:4], + buf[4:6], + buf[6:8], + buf[8:10], + buf[10:16]) +} diff --git a/vendor/github.com/boltdb/bolt/.gitignore b/vendor/github.com/boltdb/bolt/.gitignore new file mode 100644 index 00000000..c7bd2b7a --- /dev/null +++ b/vendor/github.com/boltdb/bolt/.gitignore @@ -0,0 +1,4 @@ +*.prof +*.test +*.swp +/bin/ diff --git a/vendor/github.com/boltdb/bolt/LICENSE b/vendor/github.com/boltdb/bolt/LICENSE new file mode 100644 index 00000000..004e77fe --- /dev/null +++ b/vendor/github.com/boltdb/bolt/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2013 Ben Johnson + +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/boltdb/bolt/Makefile b/vendor/github.com/boltdb/bolt/Makefile new file mode 100644 index 00000000..e035e63a --- /dev/null +++ b/vendor/github.com/boltdb/bolt/Makefile @@ -0,0 +1,18 @@ +BRANCH=`git rev-parse --abbrev-ref HEAD` +COMMIT=`git rev-parse --short HEAD` +GOLDFLAGS="-X main.branch $(BRANCH) -X main.commit $(COMMIT)" + +default: build + +race: + @go test -v -race -test.run="TestSimulate_(100op|1000op)" + +# go get github.com/kisielk/errcheck +errcheck: + @errcheck -ignorepkg=bytes -ignore=os:Remove github.com/boltdb/bolt + +test: + @go test -v -cover . + @go test -v ./cmd/bolt + +.PHONY: fmt test diff --git a/vendor/github.com/boltdb/bolt/README.md b/vendor/github.com/boltdb/bolt/README.md new file mode 100644 index 00000000..7d43a15b --- /dev/null +++ b/vendor/github.com/boltdb/bolt/README.md @@ -0,0 +1,916 @@ +Bolt [![Coverage Status](https://coveralls.io/repos/boltdb/bolt/badge.svg?branch=master)](https://coveralls.io/r/boltdb/bolt?branch=master) [![GoDoc](https://godoc.org/github.com/boltdb/bolt?status.svg)](https://godoc.org/github.com/boltdb/bolt) ![Version](https://img.shields.io/badge/version-1.2.1-green.svg) +==== + +Bolt is a pure Go key/value store inspired by [Howard Chu's][hyc_symas] +[LMDB project][lmdb]. The goal of the project is to provide a simple, +fast, and reliable database for projects that don't require a full database +server such as Postgres or MySQL. + +Since Bolt is meant to be used as such a low-level piece of functionality, +simplicity is key. The API will be small and only focus on getting values +and setting values. That's it. + +[hyc_symas]: https://twitter.com/hyc_symas +[lmdb]: http://symas.com/mdb/ + +## Project Status + +Bolt is stable, the API is fixed, and the file format is fixed. Full unit +test coverage and randomized black box testing are used to ensure database +consistency and thread safety. Bolt is currently used in high-load production +environments serving databases as large as 1TB. Many companies such as +Shopify and Heroku use Bolt-backed services every day. + +## Table of Contents + +- [Getting Started](#getting-started) + - [Installing](#installing) + - [Opening a database](#opening-a-database) + - [Transactions](#transactions) + - [Read-write transactions](#read-write-transactions) + - [Read-only transactions](#read-only-transactions) + - [Batch read-write transactions](#batch-read-write-transactions) + - [Managing transactions manually](#managing-transactions-manually) + - [Using buckets](#using-buckets) + - [Using key/value pairs](#using-keyvalue-pairs) + - [Autoincrementing integer for the bucket](#autoincrementing-integer-for-the-bucket) + - [Iterating over keys](#iterating-over-keys) + - [Prefix scans](#prefix-scans) + - [Range scans](#range-scans) + - [ForEach()](#foreach) + - [Nested buckets](#nested-buckets) + - [Database backups](#database-backups) + - [Statistics](#statistics) + - [Read-Only Mode](#read-only-mode) + - [Mobile Use (iOS/Android)](#mobile-use-iosandroid) +- [Resources](#resources) +- [Comparison with other databases](#comparison-with-other-databases) + - [Postgres, MySQL, & other relational databases](#postgres-mysql--other-relational-databases) + - [LevelDB, RocksDB](#leveldb-rocksdb) + - [LMDB](#lmdb) +- [Caveats & Limitations](#caveats--limitations) +- [Reading the Source](#reading-the-source) +- [Other Projects Using Bolt](#other-projects-using-bolt) + +## Getting Started + +### Installing + +To start using Bolt, install Go and run `go get`: + +```sh +$ go get github.com/boltdb/bolt/... +``` + +This will retrieve the library and install the `bolt` command line utility into +your `$GOBIN` path. + + +### Opening a database + +The top-level object in Bolt is a `DB`. It is represented as a single file on +your disk and represents a consistent snapshot of your data. + +To open your database, simply use the `bolt.Open()` function: + +```go +package main + +import ( + "log" + + "github.com/boltdb/bolt" +) + +func main() { + // Open the my.db data file in your current directory. + // It will be created if it doesn't exist. + db, err := bolt.Open("my.db", 0600, nil) + if err != nil { + log.Fatal(err) + } + defer db.Close() + + ... +} +``` + +Please note that Bolt obtains a file lock on the data file so multiple processes +cannot open the same database at the same time. Opening an already open Bolt +database will cause it to hang until the other process closes it. To prevent +an indefinite wait you can pass a timeout option to the `Open()` function: + +```go +db, err := bolt.Open("my.db", 0600, &bolt.Options{Timeout: 1 * time.Second}) +``` + + +### Transactions + +Bolt allows only one read-write transaction at a time but allows as many +read-only transactions as you want at a time. Each transaction has a consistent +view of the data as it existed when the transaction started. + +Individual transactions and all objects created from them (e.g. buckets, keys) +are not thread safe. To work with data in multiple goroutines you must start +a transaction for each one or use locking to ensure only one goroutine accesses +a transaction at a time. Creating transaction from the `DB` is thread safe. + +Read-only transactions and read-write transactions should not depend on one +another and generally shouldn't be opened simultaneously in the same goroutine. +This can cause a deadlock as the read-write transaction needs to periodically +re-map the data file but it cannot do so while a read-only transaction is open. + + +#### Read-write transactions + +To start a read-write transaction, you can use the `DB.Update()` function: + +```go +err := db.Update(func(tx *bolt.Tx) error { + ... + return nil +}) +``` + +Inside the closure, you have a consistent view of the database. You commit the +transaction by returning `nil` at the end. You can also rollback the transaction +at any point by returning an error. All database operations are allowed inside +a read-write transaction. + +Always check the return error as it will report any disk failures that can cause +your transaction to not complete. If you return an error within your closure +it will be passed through. + + +#### Read-only transactions + +To start a read-only transaction, you can use the `DB.View()` function: + +```go +err := db.View(func(tx *bolt.Tx) error { + ... + return nil +}) +``` + +You also get a consistent view of the database within this closure, however, +no mutating operations are allowed within a read-only transaction. You can only +retrieve buckets, retrieve values, and copy the database within a read-only +transaction. + + +#### Batch read-write transactions + +Each `DB.Update()` waits for disk to commit the writes. This overhead +can be minimized by combining multiple updates with the `DB.Batch()` +function: + +```go +err := db.Batch(func(tx *bolt.Tx) error { + ... + return nil +}) +``` + +Concurrent Batch calls are opportunistically combined into larger +transactions. Batch is only useful when there are multiple goroutines +calling it. + +The trade-off is that `Batch` can call the given +function multiple times, if parts of the transaction fail. The +function must be idempotent and side effects must take effect only +after a successful return from `DB.Batch()`. + +For example: don't display messages from inside the function, instead +set variables in the enclosing scope: + +```go +var id uint64 +err := db.Batch(func(tx *bolt.Tx) error { + // Find last key in bucket, decode as bigendian uint64, increment + // by one, encode back to []byte, and add new key. + ... + id = newValue + return nil +}) +if err != nil { + return ... +} +fmt.Println("Allocated ID %d", id) +``` + + +#### Managing transactions manually + +The `DB.View()` and `DB.Update()` functions are wrappers around the `DB.Begin()` +function. These helper functions will start the transaction, execute a function, +and then safely close your transaction if an error is returned. This is the +recommended way to use Bolt transactions. + +However, sometimes you may want to manually start and end your transactions. +You can use the `DB.Begin()` function directly but **please** be sure to close +the transaction. + +```go +// Start a writable transaction. +tx, err := db.Begin(true) +if err != nil { + return err +} +defer tx.Rollback() + +// Use the transaction... +_, err := tx.CreateBucket([]byte("MyBucket")) +if err != nil { + return err +} + +// Commit the transaction and check for error. +if err := tx.Commit(); err != nil { + return err +} +``` + +The first argument to `DB.Begin()` is a boolean stating if the transaction +should be writable. + + +### Using buckets + +Buckets are collections of key/value pairs within the database. All keys in a +bucket must be unique. You can create a bucket using the `DB.CreateBucket()` +function: + +```go +db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("MyBucket")) + if err != nil { + return fmt.Errorf("create bucket: %s", err) + } + return nil +}) +``` + +You can also create a bucket only if it doesn't exist by using the +`Tx.CreateBucketIfNotExists()` function. It's a common pattern to call this +function for all your top-level buckets after you open your database so you can +guarantee that they exist for future transactions. + +To delete a bucket, simply call the `Tx.DeleteBucket()` function. + + +### Using key/value pairs + +To save a key/value pair to a bucket, use the `Bucket.Put()` function: + +```go +db.Update(func(tx *bolt.Tx) error { + b := tx.Bucket([]byte("MyBucket")) + err := b.Put([]byte("answer"), []byte("42")) + return err +}) +``` + +This will set the value of the `"answer"` key to `"42"` in the `MyBucket` +bucket. To retrieve this value, we can use the `Bucket.Get()` function: + +```go +db.View(func(tx *bolt.Tx) error { + b := tx.Bucket([]byte("MyBucket")) + v := b.Get([]byte("answer")) + fmt.Printf("The answer is: %s\n", v) + return nil +}) +``` + +The `Get()` function does not return an error because its operation is +guaranteed to work (unless there is some kind of system failure). If the key +exists then it will return its byte slice value. If it doesn't exist then it +will return `nil`. It's important to note that you can have a zero-length value +set to a key which is different than the key not existing. + +Use the `Bucket.Delete()` function to delete a key from the bucket. + +Please note that values returned from `Get()` are only valid while the +transaction is open. If you need to use a value outside of the transaction +then you must use `copy()` to copy it to another byte slice. + + +### Autoincrementing integer for the bucket +By using the `NextSequence()` function, you can let Bolt determine a sequence +which can be used as the unique identifier for your key/value pairs. See the +example below. + +```go +// CreateUser saves u to the store. The new user ID is set on u once the data is persisted. +func (s *Store) CreateUser(u *User) error { + return s.db.Update(func(tx *bolt.Tx) error { + // Retrieve the users bucket. + // This should be created when the DB is first opened. + b := tx.Bucket([]byte("users")) + + // Generate ID for the user. + // This returns an error only if the Tx is closed or not writeable. + // That can't happen in an Update() call so I ignore the error check. + id, _ := b.NextSequence() + u.ID = int(id) + + // Marshal user data into bytes. + buf, err := json.Marshal(u) + if err != nil { + return err + } + + // Persist bytes to users bucket. + return b.Put(itob(u.ID), buf) + }) +} + +// itob returns an 8-byte big endian representation of v. +func itob(v int) []byte { + b := make([]byte, 8) + binary.BigEndian.PutUint64(b, uint64(v)) + return b +} + +type User struct { + ID int + ... +} +``` + +### Iterating over keys + +Bolt stores its keys in byte-sorted order within a bucket. This makes sequential +iteration over these keys extremely fast. To iterate over keys we'll use a +`Cursor`: + +```go +db.View(func(tx *bolt.Tx) error { + // Assume bucket exists and has keys + b := tx.Bucket([]byte("MyBucket")) + + c := b.Cursor() + + for k, v := c.First(); k != nil; k, v = c.Next() { + fmt.Printf("key=%s, value=%s\n", k, v) + } + + return nil +}) +``` + +The cursor allows you to move to a specific point in the list of keys and move +forward or backward through the keys one at a time. + +The following functions are available on the cursor: + +``` +First() Move to the first key. +Last() Move to the last key. +Seek() Move to a specific key. +Next() Move to the next key. +Prev() Move to the previous key. +``` + +Each of those functions has a return signature of `(key []byte, value []byte)`. +When you have iterated to the end of the cursor then `Next()` will return a +`nil` key. You must seek to a position using `First()`, `Last()`, or `Seek()` +before calling `Next()` or `Prev()`. If you do not seek to a position then +these functions will return a `nil` key. + +During iteration, if the key is non-`nil` but the value is `nil`, that means +the key refers to a bucket rather than a value. Use `Bucket.Bucket()` to +access the sub-bucket. + + +#### Prefix scans + +To iterate over a key prefix, you can combine `Seek()` and `bytes.HasPrefix()`: + +```go +db.View(func(tx *bolt.Tx) error { + // Assume bucket exists and has keys + c := tx.Bucket([]byte("MyBucket")).Cursor() + + prefix := []byte("1234") + for k, v := c.Seek(prefix); k != nil && bytes.HasPrefix(k, prefix); k, v = c.Next() { + fmt.Printf("key=%s, value=%s\n", k, v) + } + + return nil +}) +``` + +#### Range scans + +Another common use case is scanning over a range such as a time range. If you +use a sortable time encoding such as RFC3339 then you can query a specific +date range like this: + +```go +db.View(func(tx *bolt.Tx) error { + // Assume our events bucket exists and has RFC3339 encoded time keys. + c := tx.Bucket([]byte("Events")).Cursor() + + // Our time range spans the 90's decade. + min := []byte("1990-01-01T00:00:00Z") + max := []byte("2000-01-01T00:00:00Z") + + // Iterate over the 90's. + for k, v := c.Seek(min); k != nil && bytes.Compare(k, max) <= 0; k, v = c.Next() { + fmt.Printf("%s: %s\n", k, v) + } + + return nil +}) +``` + +Note that, while RFC3339 is sortable, the Golang implementation of RFC3339Nano does not use a fixed number of digits after the decimal point and is therefore not sortable. + + +#### ForEach() + +You can also use the function `ForEach()` if you know you'll be iterating over +all the keys in a bucket: + +```go +db.View(func(tx *bolt.Tx) error { + // Assume bucket exists and has keys + b := tx.Bucket([]byte("MyBucket")) + + b.ForEach(func(k, v []byte) error { + fmt.Printf("key=%s, value=%s\n", k, v) + return nil + }) + return nil +}) +``` + +Please note that keys and values in `ForEach()` are only valid while +the transaction is open. If you need to use a key or value outside of +the transaction, you must use `copy()` to copy it to another byte +slice. + +### Nested buckets + +You can also store a bucket in a key to create nested buckets. The API is the +same as the bucket management API on the `DB` object: + +```go +func (*Bucket) CreateBucket(key []byte) (*Bucket, error) +func (*Bucket) CreateBucketIfNotExists(key []byte) (*Bucket, error) +func (*Bucket) DeleteBucket(key []byte) error +``` + +Say you had a multi-tenant application where the root level bucket was the account bucket. Inside of this bucket was a sequence of accounts which themselves are buckets. And inside the sequence bucket you could have many buckets pertaining to the Account itself (Users, Notes, etc) isolating the information into logical groupings. + +```go + +// createUser creates a new user in the given account. +func createUser(accountID int, u *User) error { + // Start the transaction. + tx, err := db.Begin(true) + if err != nil { + return err + } + defer tx.Rollback() + + // Retrieve the root bucket for the account. + // Assume this has already been created when the account was set up. + root := tx.Bucket([]byte(strconv.FormatUint(accountID, 10))) + + // Setup the users bucket. + bkt, err := root.CreateBucketIfNotExists([]byte("USERS")) + if err != nil { + return err + } + + // Generate an ID for the new user. + userID, err := bkt.NextSequence() + if err != nil { + return err + } + u.ID = userID + + // Marshal and save the encoded user. + if buf, err := json.Marshal(u); err != nil { + return err + } else if err := bkt.Put([]byte(strconv.FormatUint(u.ID, 10)), buf); err != nil { + return err + } + + // Commit the transaction. + if err := tx.Commit(); err != nil { + return err + } + + return nil +} + +``` + + + + +### Database backups + +Bolt is a single file so it's easy to backup. You can use the `Tx.WriteTo()` +function to write a consistent view of the database to a writer. If you call +this from a read-only transaction, it will perform a hot backup and not block +your other database reads and writes. + +By default, it will use a regular file handle which will utilize the operating +system's page cache. See the [`Tx`](https://godoc.org/github.com/boltdb/bolt#Tx) +documentation for information about optimizing for larger-than-RAM datasets. + +One common use case is to backup over HTTP so you can use tools like `cURL` to +do database backups: + +```go +func BackupHandleFunc(w http.ResponseWriter, req *http.Request) { + err := db.View(func(tx *bolt.Tx) error { + w.Header().Set("Content-Type", "application/octet-stream") + w.Header().Set("Content-Disposition", `attachment; filename="my.db"`) + w.Header().Set("Content-Length", strconv.Itoa(int(tx.Size()))) + _, err := tx.WriteTo(w) + return err + }) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + } +} +``` + +Then you can backup using this command: + +```sh +$ curl http://localhost/backup > my.db +``` + +Or you can open your browser to `http://localhost/backup` and it will download +automatically. + +If you want to backup to another file you can use the `Tx.CopyFile()` helper +function. + + +### Statistics + +The database keeps a running count of many of the internal operations it +performs so you can better understand what's going on. By grabbing a snapshot +of these stats at two points in time we can see what operations were performed +in that time range. + +For example, we could start a goroutine to log stats every 10 seconds: + +```go +go func() { + // Grab the initial stats. + prev := db.Stats() + + for { + // Wait for 10s. + time.Sleep(10 * time.Second) + + // Grab the current stats and diff them. + stats := db.Stats() + diff := stats.Sub(&prev) + + // Encode stats to JSON and print to STDERR. + json.NewEncoder(os.Stderr).Encode(diff) + + // Save stats for the next loop. + prev = stats + } +}() +``` + +It's also useful to pipe these stats to a service such as statsd for monitoring +or to provide an HTTP endpoint that will perform a fixed-length sample. + + +### Read-Only Mode + +Sometimes it is useful to create a shared, read-only Bolt database. To this, +set the `Options.ReadOnly` flag when opening your database. Read-only mode +uses a shared lock to allow multiple processes to read from the database but +it will block any processes from opening the database in read-write mode. + +```go +db, err := bolt.Open("my.db", 0666, &bolt.Options{ReadOnly: true}) +if err != nil { + log.Fatal(err) +} +``` + +### Mobile Use (iOS/Android) + +Bolt is able to run on mobile devices by leveraging the binding feature of the +[gomobile](https://github.com/golang/mobile) tool. Create a struct that will +contain your database logic and a reference to a `*bolt.DB` with a initializing +constructor that takes in a filepath where the database file will be stored. +Neither Android nor iOS require extra permissions or cleanup from using this method. + +```go +func NewBoltDB(filepath string) *BoltDB { + db, err := bolt.Open(filepath+"/demo.db", 0600, nil) + if err != nil { + log.Fatal(err) + } + + return &BoltDB{db} +} + +type BoltDB struct { + db *bolt.DB + ... +} + +func (b *BoltDB) Path() string { + return b.db.Path() +} + +func (b *BoltDB) Close() { + b.db.Close() +} +``` + +Database logic should be defined as methods on this wrapper struct. + +To initialize this struct from the native language (both platforms now sync +their local storage to the cloud. These snippets disable that functionality for the +database file): + +#### Android + +```java +String path; +if (android.os.Build.VERSION.SDK_INT >=android.os.Build.VERSION_CODES.LOLLIPOP){ + path = getNoBackupFilesDir().getAbsolutePath(); +} else{ + path = getFilesDir().getAbsolutePath(); +} +Boltmobiledemo.BoltDB boltDB = Boltmobiledemo.NewBoltDB(path) +``` + +#### iOS + +```objc +- (void)demo { + NSString* path = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, + NSUserDomainMask, + YES) objectAtIndex:0]; + GoBoltmobiledemoBoltDB * demo = GoBoltmobiledemoNewBoltDB(path); + [self addSkipBackupAttributeToItemAtPath:demo.path]; + //Some DB Logic would go here + [demo close]; +} + +- (BOOL)addSkipBackupAttributeToItemAtPath:(NSString *) filePathString +{ + NSURL* URL= [NSURL fileURLWithPath: filePathString]; + assert([[NSFileManager defaultManager] fileExistsAtPath: [URL path]]); + + NSError *error = nil; + BOOL success = [URL setResourceValue: [NSNumber numberWithBool: YES] + forKey: NSURLIsExcludedFromBackupKey error: &error]; + if(!success){ + NSLog(@"Error excluding %@ from backup %@", [URL lastPathComponent], error); + } + return success; +} + +``` + +## Resources + +For more information on getting started with Bolt, check out the following articles: + +* [Intro to BoltDB: Painless Performant Persistence](http://npf.io/2014/07/intro-to-boltdb-painless-performant-persistence/) by [Nate Finch](https://github.com/natefinch). +* [Bolt -- an embedded key/value database for Go](https://www.progville.com/go/bolt-embedded-db-golang/) by Progville + + +## Comparison with other databases + +### Postgres, MySQL, & other relational databases + +Relational databases structure data into rows and are only accessible through +the use of SQL. This approach provides flexibility in how you store and query +your data but also incurs overhead in parsing and planning SQL statements. Bolt +accesses all data by a byte slice key. This makes Bolt fast to read and write +data by key but provides no built-in support for joining values together. + +Most relational databases (with the exception of SQLite) are standalone servers +that run separately from your application. This gives your systems +flexibility to connect multiple application servers to a single database +server but also adds overhead in serializing and transporting data over the +network. Bolt runs as a library included in your application so all data access +has to go through your application's process. This brings data closer to your +application but limits multi-process access to the data. + + +### LevelDB, RocksDB + +LevelDB and its derivatives (RocksDB, HyperLevelDB) are similar to Bolt in that +they are libraries bundled into the application, however, their underlying +structure is a log-structured merge-tree (LSM tree). An LSM tree optimizes +random writes by using a write ahead log and multi-tiered, sorted files called +SSTables. Bolt uses a B+tree internally and only a single file. Both approaches +have trade-offs. + +If you require a high random write throughput (>10,000 w/sec) or you need to use +spinning disks then LevelDB could be a good choice. If your application is +read-heavy or does a lot of range scans then Bolt could be a good choice. + +One other important consideration is that LevelDB does not have transactions. +It supports batch writing of key/values pairs and it supports read snapshots +but it will not give you the ability to do a compare-and-swap operation safely. +Bolt supports fully serializable ACID transactions. + + +### LMDB + +Bolt was originally a port of LMDB so it is architecturally similar. Both use +a B+tree, have ACID semantics with fully serializable transactions, and support +lock-free MVCC using a single writer and multiple readers. + +The two projects have somewhat diverged. LMDB heavily focuses on raw performance +while Bolt has focused on simplicity and ease of use. For example, LMDB allows +several unsafe actions such as direct writes for the sake of performance. Bolt +opts to disallow actions which can leave the database in a corrupted state. The +only exception to this in Bolt is `DB.NoSync`. + +There are also a few differences in API. LMDB requires a maximum mmap size when +opening an `mdb_env` whereas Bolt will handle incremental mmap resizing +automatically. LMDB overloads the getter and setter functions with multiple +flags whereas Bolt splits these specialized cases into their own functions. + + +## Caveats & Limitations + +It's important to pick the right tool for the job and Bolt is no exception. +Here are a few things to note when evaluating and using Bolt: + +* Bolt is good for read intensive workloads. Sequential write performance is + also fast but random writes can be slow. You can use `DB.Batch()` or add a + write-ahead log to help mitigate this issue. + +* Bolt uses a B+tree internally so there can be a lot of random page access. + SSDs provide a significant performance boost over spinning disks. + +* Try to avoid long running read transactions. Bolt uses copy-on-write so + old pages cannot be reclaimed while an old transaction is using them. + +* Byte slices returned from Bolt are only valid during a transaction. Once the + transaction has been committed or rolled back then the memory they point to + can be reused by a new page or can be unmapped from virtual memory and you'll + see an `unexpected fault address` panic when accessing it. + +* Bolt uses an exclusive write lock on the database file so it cannot be + shared by multiple processes. + +* Be careful when using `Bucket.FillPercent`. Setting a high fill percent for + buckets that have random inserts will cause your database to have very poor + page utilization. + +* Use larger buckets in general. Smaller buckets causes poor page utilization + once they become larger than the page size (typically 4KB). + +* Bulk loading a lot of random writes into a new bucket can be slow as the + page will not split until the transaction is committed. Randomly inserting + more than 100,000 key/value pairs into a single new bucket in a single + transaction is not advised. + +* Bolt uses a memory-mapped file so the underlying operating system handles the + caching of the data. Typically, the OS will cache as much of the file as it + can in memory and will release memory as needed to other processes. This means + that Bolt can show very high memory usage when working with large databases. + However, this is expected and the OS will release memory as needed. Bolt can + handle databases much larger than the available physical RAM, provided its + memory-map fits in the process virtual address space. It may be problematic + on 32-bits systems. + +* The data structures in the Bolt database are memory mapped so the data file + will be endian specific. This means that you cannot copy a Bolt file from a + little endian machine to a big endian machine and have it work. For most + users this is not a concern since most modern CPUs are little endian. + +* Because of the way pages are laid out on disk, Bolt cannot truncate data files + and return free pages back to the disk. Instead, Bolt maintains a free list + of unused pages within its data file. These free pages can be reused by later + transactions. This works well for many use cases as databases generally tend + to grow. However, it's important to note that deleting large chunks of data + will not allow you to reclaim that space on disk. + + For more information on page allocation, [see this comment][page-allocation]. + +[page-allocation]: https://github.com/boltdb/bolt/issues/308#issuecomment-74811638 + + +## Reading the Source + +Bolt is a relatively small code base (<3KLOC) for an embedded, serializable, +transactional key/value database so it can be a good starting point for people +interested in how databases work. + +The best places to start are the main entry points into Bolt: + +- `Open()` - Initializes the reference to the database. It's responsible for + creating the database if it doesn't exist, obtaining an exclusive lock on the + file, reading the meta pages, & memory-mapping the file. + +- `DB.Begin()` - Starts a read-only or read-write transaction depending on the + value of the `writable` argument. This requires briefly obtaining the "meta" + lock to keep track of open transactions. Only one read-write transaction can + exist at a time so the "rwlock" is acquired during the life of a read-write + transaction. + +- `Bucket.Put()` - Writes a key/value pair into a bucket. After validating the + arguments, a cursor is used to traverse the B+tree to the page and position + where they key & value will be written. Once the position is found, the bucket + materializes the underlying page and the page's parent pages into memory as + "nodes". These nodes are where mutations occur during read-write transactions. + These changes get flushed to disk during commit. + +- `Bucket.Get()` - Retrieves a key/value pair from a bucket. This uses a cursor + to move to the page & position of a key/value pair. During a read-only + transaction, the key and value data is returned as a direct reference to the + underlying mmap file so there's no allocation overhead. For read-write + transactions, this data may reference the mmap file or one of the in-memory + node values. + +- `Cursor` - This object is simply for traversing the B+tree of on-disk pages + or in-memory nodes. It can seek to a specific key, move to the first or last + value, or it can move forward or backward. The cursor handles the movement up + and down the B+tree transparently to the end user. + +- `Tx.Commit()` - Converts the in-memory dirty nodes and the list of free pages + into pages to be written to disk. Writing to disk then occurs in two phases. + First, the dirty pages are written to disk and an `fsync()` occurs. Second, a + new meta page with an incremented transaction ID is written and another + `fsync()` occurs. This two phase write ensures that partially written data + pages are ignored in the event of a crash since the meta page pointing to them + is never written. Partially written meta pages are invalidated because they + are written with a checksum. + +If you have additional notes that could be helpful for others, please submit +them via pull request. + + +## Other Projects Using Bolt + +Below is a list of public, open source projects that use Bolt: + +* [BoltDbWeb](https://github.com/evnix/boltdbweb) - A web based GUI for BoltDB files. +* [Operation Go: A Routine Mission](http://gocode.io) - An online programming game for Golang using Bolt for user accounts and a leaderboard. +* [Bazil](https://bazil.org/) - A file system that lets your data reside where it is most convenient for it to reside. +* [DVID](https://github.com/janelia-flyem/dvid) - Added Bolt as optional storage engine and testing it against Basho-tuned leveldb. +* [Skybox Analytics](https://github.com/skybox/skybox) - A standalone funnel analysis tool for web analytics. +* [Scuttlebutt](https://github.com/benbjohnson/scuttlebutt) - Uses Bolt to store and process all Twitter mentions of GitHub projects. +* [Wiki](https://github.com/peterhellberg/wiki) - A tiny wiki using Goji, BoltDB and Blackfriday. +* [ChainStore](https://github.com/pressly/chainstore) - Simple key-value interface to a variety of storage engines organized as a chain of operations. +* [MetricBase](https://github.com/msiebuhr/MetricBase) - Single-binary version of Graphite. +* [Gitchain](https://github.com/gitchain/gitchain) - Decentralized, peer-to-peer Git repositories aka "Git meets Bitcoin". +* [event-shuttle](https://github.com/sclasen/event-shuttle) - A Unix system service to collect and reliably deliver messages to Kafka. +* [ipxed](https://github.com/kelseyhightower/ipxed) - Web interface and api for ipxed. +* [BoltStore](https://github.com/yosssi/boltstore) - Session store using Bolt. +* [photosite/session](https://godoc.org/bitbucket.org/kardianos/photosite/session) - Sessions for a photo viewing site. +* [LedisDB](https://github.com/siddontang/ledisdb) - A high performance NoSQL, using Bolt as optional storage. +* [ipLocator](https://github.com/AndreasBriese/ipLocator) - A fast ip-geo-location-server using bolt with bloom filters. +* [cayley](https://github.com/google/cayley) - Cayley is an open-source graph database using Bolt as optional backend. +* [bleve](http://www.blevesearch.com/) - A pure Go search engine similar to ElasticSearch that uses Bolt as the default storage backend. +* [tentacool](https://github.com/optiflows/tentacool) - REST api server to manage system stuff (IP, DNS, Gateway...) on a linux server. +* [Seaweed File System](https://github.com/chrislusf/seaweedfs) - Highly scalable distributed key~file system with O(1) disk read. +* [InfluxDB](https://influxdata.com) - Scalable datastore for metrics, events, and real-time analytics. +* [Freehold](http://tshannon.bitbucket.org/freehold/) - An open, secure, and lightweight platform for your files and data. +* [Prometheus Annotation Server](https://github.com/oliver006/prom_annotation_server) - Annotation server for PromDash & Prometheus service monitoring system. +* [Consul](https://github.com/hashicorp/consul) - Consul is service discovery and configuration made easy. Distributed, highly available, and datacenter-aware. +* [Kala](https://github.com/ajvb/kala) - Kala is a modern job scheduler optimized to run on a single node. It is persistent, JSON over HTTP API, ISO 8601 duration notation, and dependent jobs. +* [drive](https://github.com/odeke-em/drive) - drive is an unofficial Google Drive command line client for \*NIX operating systems. +* [stow](https://github.com/djherbis/stow) - a persistence manager for objects + backed by boltdb. +* [buckets](https://github.com/joyrexus/buckets) - a bolt wrapper streamlining + simple tx and key scans. +* [mbuckets](https://github.com/abhigupta912/mbuckets) - A Bolt wrapper that allows easy operations on multi level (nested) buckets. +* [Request Baskets](https://github.com/darklynx/request-baskets) - A web service to collect arbitrary HTTP requests and inspect them via REST API or simple web UI, similar to [RequestBin](http://requestb.in/) service +* [Go Report Card](https://goreportcard.com/) - Go code quality report cards as a (free and open source) service. +* [Boltdb Boilerplate](https://github.com/bobintornado/boltdb-boilerplate) - Boilerplate wrapper around bolt aiming to make simple calls one-liners. +* [lru](https://github.com/crowdriff/lru) - Easy to use Bolt-backed Least-Recently-Used (LRU) read-through cache with chainable remote stores. +* [Storm](https://github.com/asdine/storm) - Simple and powerful ORM for BoltDB. +* [GoWebApp](https://github.com/josephspurrier/gowebapp) - A basic MVC web application in Go using BoltDB. +* [SimpleBolt](https://github.com/xyproto/simplebolt) - A simple way to use BoltDB. Deals mainly with strings. +* [Algernon](https://github.com/xyproto/algernon) - A HTTP/2 web server with built-in support for Lua. Uses BoltDB as the default database backend. +* [MuLiFS](https://github.com/dankomiocevic/mulifs) - Music Library Filesystem creates a filesystem to organise your music files. +* [GoShort](https://github.com/pankajkhairnar/goShort) - GoShort is a URL shortener written in Golang and BoltDB for persistent key/value storage and for routing it's using high performent HTTPRouter. +* [torrent](https://github.com/anacrolix/torrent) - Full-featured BitTorrent client package and utilities in Go. BoltDB is a storage backend in development. +* [gopherpit](https://github.com/gopherpit/gopherpit) - A web service to manage Go remote import paths with custom domains +* [bolter](https://github.com/hasit/bolter) - Command-line app for viewing BoltDB file in your terminal. +* [btcwallet](https://github.com/btcsuite/btcwallet) - A bitcoin wallet. +* [dcrwallet](https://github.com/decred/dcrwallet) - A wallet for the Decred cryptocurrency. +* [Ironsmith](https://github.com/timshannon/ironsmith) - A simple, script-driven continuous integration (build - > test -> release) tool, with no external dependencies +* [BoltHold](https://github.com/timshannon/bolthold) - An embeddable NoSQL store for Go types built on BoltDB +* [Ponzu CMS](https://ponzu-cms.org) - Headless CMS + automatic JSON API with auto-HTTPS, HTTP/2 Server Push, and flexible server framework. + +If you are using Bolt in a project please send a pull request to add it to the list. diff --git a/vendor/github.com/boltdb/bolt/appveyor.yml b/vendor/github.com/boltdb/bolt/appveyor.yml new file mode 100644 index 00000000..6e26e941 --- /dev/null +++ b/vendor/github.com/boltdb/bolt/appveyor.yml @@ -0,0 +1,18 @@ +version: "{build}" + +os: Windows Server 2012 R2 + +clone_folder: c:\gopath\src\github.com\boltdb\bolt + +environment: + GOPATH: c:\gopath + +install: + - echo %PATH% + - echo %GOPATH% + - go version + - go env + - go get -v -t ./... + +build_script: + - go test -v ./... diff --git a/vendor/github.com/boltdb/bolt/bolt_386.go b/vendor/github.com/boltdb/bolt/bolt_386.go new file mode 100644 index 00000000..820d533c --- /dev/null +++ b/vendor/github.com/boltdb/bolt/bolt_386.go @@ -0,0 +1,10 @@ +package bolt + +// maxMapSize represents the largest mmap size supported by Bolt. +const maxMapSize = 0x7FFFFFFF // 2GB + +// maxAllocSize is the size used when creating array pointers. +const maxAllocSize = 0xFFFFFFF + +// Are unaligned load/stores broken on this arch? +var brokenUnaligned = false diff --git a/vendor/github.com/boltdb/bolt/bolt_amd64.go b/vendor/github.com/boltdb/bolt/bolt_amd64.go new file mode 100644 index 00000000..98fafdb4 --- /dev/null +++ b/vendor/github.com/boltdb/bolt/bolt_amd64.go @@ -0,0 +1,10 @@ +package bolt + +// maxMapSize represents the largest mmap size supported by Bolt. +const maxMapSize = 0xFFFFFFFFFFFF // 256TB + +// maxAllocSize is the size used when creating array pointers. +const maxAllocSize = 0x7FFFFFFF + +// Are unaligned load/stores broken on this arch? +var brokenUnaligned = false diff --git a/vendor/github.com/boltdb/bolt/bolt_arm.go b/vendor/github.com/boltdb/bolt/bolt_arm.go new file mode 100644 index 00000000..7e5cb4b9 --- /dev/null +++ b/vendor/github.com/boltdb/bolt/bolt_arm.go @@ -0,0 +1,28 @@ +package bolt + +import "unsafe" + +// maxMapSize represents the largest mmap size supported by Bolt. +const maxMapSize = 0x7FFFFFFF // 2GB + +// maxAllocSize is the size used when creating array pointers. +const maxAllocSize = 0xFFFFFFF + +// Are unaligned load/stores broken on this arch? +var brokenUnaligned bool + +func init() { + // Simple check to see whether this arch handles unaligned load/stores + // correctly. + + // ARM9 and older devices require load/stores to be from/to aligned + // addresses. If not, the lower 2 bits are cleared and that address is + // read in a jumbled up order. + + // See http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka15414.html + + raw := [6]byte{0xfe, 0xef, 0x11, 0x22, 0x22, 0x11} + val := *(*uint32)(unsafe.Pointer(uintptr(unsafe.Pointer(&raw)) + 2)) + + brokenUnaligned = val != 0x11222211 +} diff --git a/vendor/github.com/boltdb/bolt/bolt_arm64.go b/vendor/github.com/boltdb/bolt/bolt_arm64.go new file mode 100644 index 00000000..b26d84f9 --- /dev/null +++ b/vendor/github.com/boltdb/bolt/bolt_arm64.go @@ -0,0 +1,12 @@ +// +build arm64 + +package bolt + +// maxMapSize represents the largest mmap size supported by Bolt. +const maxMapSize = 0xFFFFFFFFFFFF // 256TB + +// maxAllocSize is the size used when creating array pointers. +const maxAllocSize = 0x7FFFFFFF + +// Are unaligned load/stores broken on this arch? +var brokenUnaligned = false diff --git a/vendor/github.com/boltdb/bolt/bolt_linux.go b/vendor/github.com/boltdb/bolt/bolt_linux.go new file mode 100644 index 00000000..2b676661 --- /dev/null +++ b/vendor/github.com/boltdb/bolt/bolt_linux.go @@ -0,0 +1,10 @@ +package bolt + +import ( + "syscall" +) + +// fdatasync flushes written data to a file descriptor. +func fdatasync(db *DB) error { + return syscall.Fdatasync(int(db.file.Fd())) +} diff --git a/vendor/github.com/boltdb/bolt/bolt_openbsd.go b/vendor/github.com/boltdb/bolt/bolt_openbsd.go new file mode 100644 index 00000000..7058c3d7 --- /dev/null +++ b/vendor/github.com/boltdb/bolt/bolt_openbsd.go @@ -0,0 +1,27 @@ +package bolt + +import ( + "syscall" + "unsafe" +) + +const ( + msAsync = 1 << iota // perform asynchronous writes + msSync // perform synchronous writes + msInvalidate // invalidate cached data +) + +func msync(db *DB) error { + _, _, errno := syscall.Syscall(syscall.SYS_MSYNC, uintptr(unsafe.Pointer(db.data)), uintptr(db.datasz), msInvalidate) + if errno != 0 { + return errno + } + return nil +} + +func fdatasync(db *DB) error { + if db.data != nil { + return msync(db) + } + return db.file.Sync() +} diff --git a/vendor/github.com/boltdb/bolt/bolt_ppc.go b/vendor/github.com/boltdb/bolt/bolt_ppc.go new file mode 100644 index 00000000..645ddc3e --- /dev/null +++ b/vendor/github.com/boltdb/bolt/bolt_ppc.go @@ -0,0 +1,9 @@ +// +build ppc + +package bolt + +// maxMapSize represents the largest mmap size supported by Bolt. +const maxMapSize = 0x7FFFFFFF // 2GB + +// maxAllocSize is the size used when creating array pointers. +const maxAllocSize = 0xFFFFFFF diff --git a/vendor/github.com/boltdb/bolt/bolt_ppc64.go b/vendor/github.com/boltdb/bolt/bolt_ppc64.go new file mode 100644 index 00000000..9331d977 --- /dev/null +++ b/vendor/github.com/boltdb/bolt/bolt_ppc64.go @@ -0,0 +1,12 @@ +// +build ppc64 + +package bolt + +// maxMapSize represents the largest mmap size supported by Bolt. +const maxMapSize = 0xFFFFFFFFFFFF // 256TB + +// maxAllocSize is the size used when creating array pointers. +const maxAllocSize = 0x7FFFFFFF + +// Are unaligned load/stores broken on this arch? +var brokenUnaligned = false diff --git a/vendor/github.com/boltdb/bolt/bolt_ppc64le.go b/vendor/github.com/boltdb/bolt/bolt_ppc64le.go new file mode 100644 index 00000000..8c143bc5 --- /dev/null +++ b/vendor/github.com/boltdb/bolt/bolt_ppc64le.go @@ -0,0 +1,12 @@ +// +build ppc64le + +package bolt + +// maxMapSize represents the largest mmap size supported by Bolt. +const maxMapSize = 0xFFFFFFFFFFFF // 256TB + +// maxAllocSize is the size used when creating array pointers. +const maxAllocSize = 0x7FFFFFFF + +// Are unaligned load/stores broken on this arch? +var brokenUnaligned = false diff --git a/vendor/github.com/boltdb/bolt/bolt_s390x.go b/vendor/github.com/boltdb/bolt/bolt_s390x.go new file mode 100644 index 00000000..d7c39af9 --- /dev/null +++ b/vendor/github.com/boltdb/bolt/bolt_s390x.go @@ -0,0 +1,12 @@ +// +build s390x + +package bolt + +// maxMapSize represents the largest mmap size supported by Bolt. +const maxMapSize = 0xFFFFFFFFFFFF // 256TB + +// maxAllocSize is the size used when creating array pointers. +const maxAllocSize = 0x7FFFFFFF + +// Are unaligned load/stores broken on this arch? +var brokenUnaligned = false diff --git a/vendor/github.com/boltdb/bolt/bolt_unix.go b/vendor/github.com/boltdb/bolt/bolt_unix.go new file mode 100644 index 00000000..cad62dda --- /dev/null +++ b/vendor/github.com/boltdb/bolt/bolt_unix.go @@ -0,0 +1,89 @@ +// +build !windows,!plan9,!solaris + +package bolt + +import ( + "fmt" + "os" + "syscall" + "time" + "unsafe" +) + +// flock acquires an advisory lock on a file descriptor. +func flock(db *DB, mode os.FileMode, exclusive bool, timeout time.Duration) error { + var t time.Time + for { + // If we're beyond our timeout then return an error. + // This can only occur after we've attempted a flock once. + if t.IsZero() { + t = time.Now() + } else if timeout > 0 && time.Since(t) > timeout { + return ErrTimeout + } + flag := syscall.LOCK_SH + if exclusive { + flag = syscall.LOCK_EX + } + + // Otherwise attempt to obtain an exclusive lock. + err := syscall.Flock(int(db.file.Fd()), flag|syscall.LOCK_NB) + if err == nil { + return nil + } else if err != syscall.EWOULDBLOCK { + return err + } + + // Wait for a bit and try again. + time.Sleep(50 * time.Millisecond) + } +} + +// funlock releases an advisory lock on a file descriptor. +func funlock(db *DB) error { + return syscall.Flock(int(db.file.Fd()), syscall.LOCK_UN) +} + +// mmap memory maps a DB's data file. +func mmap(db *DB, sz int) error { + // Map the data file to memory. + b, err := syscall.Mmap(int(db.file.Fd()), 0, sz, syscall.PROT_READ, syscall.MAP_SHARED|db.MmapFlags) + if err != nil { + return err + } + + // Advise the kernel that the mmap is accessed randomly. + if err := madvise(b, syscall.MADV_RANDOM); err != nil { + return fmt.Errorf("madvise: %s", err) + } + + // Save the original byte slice and convert to a byte array pointer. + db.dataref = b + db.data = (*[maxMapSize]byte)(unsafe.Pointer(&b[0])) + db.datasz = sz + return nil +} + +// munmap unmaps a DB's data file from memory. +func munmap(db *DB) error { + // Ignore the unmap if we have no mapped data. + if db.dataref == nil { + return nil + } + + // Unmap using the original byte slice. + err := syscall.Munmap(db.dataref) + db.dataref = nil + db.data = nil + db.datasz = 0 + return err +} + +// NOTE: This function is copied from stdlib because it is not available on darwin. +func madvise(b []byte, advice int) (err error) { + _, _, e1 := syscall.Syscall(syscall.SYS_MADVISE, uintptr(unsafe.Pointer(&b[0])), uintptr(len(b)), uintptr(advice)) + if e1 != 0 { + err = e1 + } + return +} diff --git a/vendor/github.com/boltdb/bolt/bolt_unix_solaris.go b/vendor/github.com/boltdb/bolt/bolt_unix_solaris.go new file mode 100644 index 00000000..307bf2b3 --- /dev/null +++ b/vendor/github.com/boltdb/bolt/bolt_unix_solaris.go @@ -0,0 +1,90 @@ +package bolt + +import ( + "fmt" + "os" + "syscall" + "time" + "unsafe" + + "golang.org/x/sys/unix" +) + +// flock acquires an advisory lock on a file descriptor. +func flock(db *DB, mode os.FileMode, exclusive bool, timeout time.Duration) error { + var t time.Time + for { + // If we're beyond our timeout then return an error. + // This can only occur after we've attempted a flock once. + if t.IsZero() { + t = time.Now() + } else if timeout > 0 && time.Since(t) > timeout { + return ErrTimeout + } + var lock syscall.Flock_t + lock.Start = 0 + lock.Len = 0 + lock.Pid = 0 + lock.Whence = 0 + lock.Pid = 0 + if exclusive { + lock.Type = syscall.F_WRLCK + } else { + lock.Type = syscall.F_RDLCK + } + err := syscall.FcntlFlock(db.file.Fd(), syscall.F_SETLK, &lock) + if err == nil { + return nil + } else if err != syscall.EAGAIN { + return err + } + + // Wait for a bit and try again. + time.Sleep(50 * time.Millisecond) + } +} + +// funlock releases an advisory lock on a file descriptor. +func funlock(db *DB) error { + var lock syscall.Flock_t + lock.Start = 0 + lock.Len = 0 + lock.Type = syscall.F_UNLCK + lock.Whence = 0 + return syscall.FcntlFlock(uintptr(db.file.Fd()), syscall.F_SETLK, &lock) +} + +// mmap memory maps a DB's data file. +func mmap(db *DB, sz int) error { + // Map the data file to memory. + b, err := unix.Mmap(int(db.file.Fd()), 0, sz, syscall.PROT_READ, syscall.MAP_SHARED|db.MmapFlags) + if err != nil { + return err + } + + // Advise the kernel that the mmap is accessed randomly. + if err := unix.Madvise(b, syscall.MADV_RANDOM); err != nil { + return fmt.Errorf("madvise: %s", err) + } + + // Save the original byte slice and convert to a byte array pointer. + db.dataref = b + db.data = (*[maxMapSize]byte)(unsafe.Pointer(&b[0])) + db.datasz = sz + return nil +} + +// munmap unmaps a DB's data file from memory. +func munmap(db *DB) error { + // Ignore the unmap if we have no mapped data. + if db.dataref == nil { + return nil + } + + // Unmap using the original byte slice. + err := unix.Munmap(db.dataref) + db.dataref = nil + db.data = nil + db.datasz = 0 + return err +} diff --git a/vendor/github.com/boltdb/bolt/bolt_windows.go b/vendor/github.com/boltdb/bolt/bolt_windows.go new file mode 100644 index 00000000..b00fb072 --- /dev/null +++ b/vendor/github.com/boltdb/bolt/bolt_windows.go @@ -0,0 +1,144 @@ +package bolt + +import ( + "fmt" + "os" + "syscall" + "time" + "unsafe" +) + +// LockFileEx code derived from golang build filemutex_windows.go @ v1.5.1 +var ( + modkernel32 = syscall.NewLazyDLL("kernel32.dll") + procLockFileEx = modkernel32.NewProc("LockFileEx") + procUnlockFileEx = modkernel32.NewProc("UnlockFileEx") +) + +const ( + lockExt = ".lock" + + // see https://msdn.microsoft.com/en-us/library/windows/desktop/aa365203(v=vs.85).aspx + flagLockExclusive = 2 + flagLockFailImmediately = 1 + + // see https://msdn.microsoft.com/en-us/library/windows/desktop/ms681382(v=vs.85).aspx + errLockViolation syscall.Errno = 0x21 +) + +func lockFileEx(h syscall.Handle, flags, reserved, locklow, lockhigh uint32, ol *syscall.Overlapped) (err error) { + r, _, err := procLockFileEx.Call(uintptr(h), uintptr(flags), uintptr(reserved), uintptr(locklow), uintptr(lockhigh), uintptr(unsafe.Pointer(ol))) + if r == 0 { + return err + } + return nil +} + +func unlockFileEx(h syscall.Handle, reserved, locklow, lockhigh uint32, ol *syscall.Overlapped) (err error) { + r, _, err := procUnlockFileEx.Call(uintptr(h), uintptr(reserved), uintptr(locklow), uintptr(lockhigh), uintptr(unsafe.Pointer(ol)), 0) + if r == 0 { + return err + } + return nil +} + +// fdatasync flushes written data to a file descriptor. +func fdatasync(db *DB) error { + return db.file.Sync() +} + +// flock acquires an advisory lock on a file descriptor. +func flock(db *DB, mode os.FileMode, exclusive bool, timeout time.Duration) error { + // Create a separate lock file on windows because a process + // cannot share an exclusive lock on the same file. This is + // needed during Tx.WriteTo(). + f, err := os.OpenFile(db.path+lockExt, os.O_CREATE, mode) + if err != nil { + return err + } + db.lockfile = f + + var t time.Time + for { + // If we're beyond our timeout then return an error. + // This can only occur after we've attempted a flock once. + if t.IsZero() { + t = time.Now() + } else if timeout > 0 && time.Since(t) > timeout { + return ErrTimeout + } + + var flag uint32 = flagLockFailImmediately + if exclusive { + flag |= flagLockExclusive + } + + err := lockFileEx(syscall.Handle(db.lockfile.Fd()), flag, 0, 1, 0, &syscall.Overlapped{}) + if err == nil { + return nil + } else if err != errLockViolation { + return err + } + + // Wait for a bit and try again. + time.Sleep(50 * time.Millisecond) + } +} + +// funlock releases an advisory lock on a file descriptor. +func funlock(db *DB) error { + err := unlockFileEx(syscall.Handle(db.lockfile.Fd()), 0, 1, 0, &syscall.Overlapped{}) + db.lockfile.Close() + os.Remove(db.path + lockExt) + return err +} + +// mmap memory maps a DB's data file. +// Based on: https://github.com/edsrzf/mmap-go +func mmap(db *DB, sz int) error { + if !db.readOnly { + // Truncate the database to the size of the mmap. + if err := db.file.Truncate(int64(sz)); err != nil { + return fmt.Errorf("truncate: %s", err) + } + } + + // Open a file mapping handle. + sizelo := uint32(sz >> 32) + sizehi := uint32(sz) & 0xffffffff + h, errno := syscall.CreateFileMapping(syscall.Handle(db.file.Fd()), nil, syscall.PAGE_READONLY, sizelo, sizehi, nil) + if h == 0 { + return os.NewSyscallError("CreateFileMapping", errno) + } + + // Create the memory map. + addr, errno := syscall.MapViewOfFile(h, syscall.FILE_MAP_READ, 0, 0, uintptr(sz)) + if addr == 0 { + return os.NewSyscallError("MapViewOfFile", errno) + } + + // Close mapping handle. + if err := syscall.CloseHandle(syscall.Handle(h)); err != nil { + return os.NewSyscallError("CloseHandle", err) + } + + // Convert to a byte array. + db.data = ((*[maxMapSize]byte)(unsafe.Pointer(addr))) + db.datasz = sz + + return nil +} + +// munmap unmaps a pointer from a file. +// Based on: https://github.com/edsrzf/mmap-go +func munmap(db *DB) error { + if db.data == nil { + return nil + } + + addr := (uintptr)(unsafe.Pointer(&db.data[0])) + if err := syscall.UnmapViewOfFile(addr); err != nil { + return os.NewSyscallError("UnmapViewOfFile", err) + } + return nil +} diff --git a/vendor/github.com/boltdb/bolt/boltsync_unix.go b/vendor/github.com/boltdb/bolt/boltsync_unix.go new file mode 100644 index 00000000..f5044252 --- /dev/null +++ b/vendor/github.com/boltdb/bolt/boltsync_unix.go @@ -0,0 +1,8 @@ +// +build !windows,!plan9,!linux,!openbsd + +package bolt + +// fdatasync flushes written data to a file descriptor. +func fdatasync(db *DB) error { + return db.file.Sync() +} diff --git a/vendor/github.com/boltdb/bolt/bucket.go b/vendor/github.com/boltdb/bolt/bucket.go new file mode 100644 index 00000000..0c5bf274 --- /dev/null +++ b/vendor/github.com/boltdb/bolt/bucket.go @@ -0,0 +1,777 @@ +package bolt + +import ( + "bytes" + "fmt" + "unsafe" +) + +const ( + // MaxKeySize is the maximum length of a key, in bytes. + MaxKeySize = 32768 + + // MaxValueSize is the maximum length of a value, in bytes. + MaxValueSize = (1 << 31) - 2 +) + +const ( + maxUint = ^uint(0) + minUint = 0 + maxInt = int(^uint(0) >> 1) + minInt = -maxInt - 1 +) + +const bucketHeaderSize = int(unsafe.Sizeof(bucket{})) + +const ( + minFillPercent = 0.1 + maxFillPercent = 1.0 +) + +// DefaultFillPercent is the percentage that split pages are filled. +// This value can be changed by setting Bucket.FillPercent. +const DefaultFillPercent = 0.5 + +// Bucket represents a collection of key/value pairs inside the database. +type Bucket struct { + *bucket + tx *Tx // the associated transaction + buckets map[string]*Bucket // subbucket cache + page *page // inline page reference + rootNode *node // materialized node for the root page. + nodes map[pgid]*node // node cache + + // Sets the threshold for filling nodes when they split. By default, + // the bucket will fill to 50% but it can be useful to increase this + // amount if you know that your write workloads are mostly append-only. + // + // This is non-persisted across transactions so it must be set in every Tx. + FillPercent float64 +} + +// bucket represents the on-file representation of a bucket. +// This is stored as the "value" of a bucket key. If the bucket is small enough, +// then its root page can be stored inline in the "value", after the bucket +// header. In the case of inline buckets, the "root" will be 0. +type bucket struct { + root pgid // page id of the bucket's root-level page + sequence uint64 // monotonically incrementing, used by NextSequence() +} + +// newBucket returns a new bucket associated with a transaction. +func newBucket(tx *Tx) Bucket { + var b = Bucket{tx: tx, FillPercent: DefaultFillPercent} + if tx.writable { + b.buckets = make(map[string]*Bucket) + b.nodes = make(map[pgid]*node) + } + return b +} + +// Tx returns the tx of the bucket. +func (b *Bucket) Tx() *Tx { + return b.tx +} + +// Root returns the root of the bucket. +func (b *Bucket) Root() pgid { + return b.root +} + +// Writable returns whether the bucket is writable. +func (b *Bucket) Writable() bool { + return b.tx.writable +} + +// Cursor creates a cursor associated with the bucket. +// The cursor is only valid as long as the transaction is open. +// Do not use a cursor after the transaction is closed. +func (b *Bucket) Cursor() *Cursor { + // Update transaction statistics. + b.tx.stats.CursorCount++ + + // Allocate and return a cursor. + return &Cursor{ + bucket: b, + stack: make([]elemRef, 0), + } +} + +// Bucket retrieves a nested bucket by name. +// Returns nil if the bucket does not exist. +// The bucket instance is only valid for the lifetime of the transaction. +func (b *Bucket) Bucket(name []byte) *Bucket { + if b.buckets != nil { + if child := b.buckets[string(name)]; child != nil { + return child + } + } + + // Move cursor to key. + c := b.Cursor() + k, v, flags := c.seek(name) + + // Return nil if the key doesn't exist or it is not a bucket. + if !bytes.Equal(name, k) || (flags&bucketLeafFlag) == 0 { + return nil + } + + // Otherwise create a bucket and cache it. + var child = b.openBucket(v) + if b.buckets != nil { + b.buckets[string(name)] = child + } + + return child +} + +// Helper method that re-interprets a sub-bucket value +// from a parent into a Bucket +func (b *Bucket) openBucket(value []byte) *Bucket { + var child = newBucket(b.tx) + + // If unaligned load/stores are broken on this arch and value is + // unaligned simply clone to an aligned byte array. + unaligned := brokenUnaligned && uintptr(unsafe.Pointer(&value[0]))&3 != 0 + + if unaligned { + value = cloneBytes(value) + } + + // If this is a writable transaction then we need to copy the bucket entry. + // Read-only transactions can point directly at the mmap entry. + if b.tx.writable && !unaligned { + child.bucket = &bucket{} + *child.bucket = *(*bucket)(unsafe.Pointer(&value[0])) + } else { + child.bucket = (*bucket)(unsafe.Pointer(&value[0])) + } + + // Save a reference to the inline page if the bucket is inline. + if child.root == 0 { + child.page = (*page)(unsafe.Pointer(&value[bucketHeaderSize])) + } + + return &child +} + +// CreateBucket creates a new bucket at the given key and returns the new bucket. +// Returns an error if the key already exists, if the bucket name is blank, or if the bucket name is too long. +// The bucket instance is only valid for the lifetime of the transaction. +func (b *Bucket) CreateBucket(key []byte) (*Bucket, error) { + if b.tx.db == nil { + return nil, ErrTxClosed + } else if !b.tx.writable { + return nil, ErrTxNotWritable + } else if len(key) == 0 { + return nil, ErrBucketNameRequired + } + + // Move cursor to correct position. + c := b.Cursor() + k, _, flags := c.seek(key) + + // Return an error if there is an existing key. + if bytes.Equal(key, k) { + if (flags & bucketLeafFlag) != 0 { + return nil, ErrBucketExists + } + return nil, ErrIncompatibleValue + } + + // Create empty, inline bucket. + var bucket = Bucket{ + bucket: &bucket{}, + rootNode: &node{isLeaf: true}, + FillPercent: DefaultFillPercent, + } + var value = bucket.write() + + // Insert into node. + key = cloneBytes(key) + c.node().put(key, key, value, 0, bucketLeafFlag) + + // Since subbuckets are not allowed on inline buckets, we need to + // dereference the inline page, if it exists. This will cause the bucket + // to be treated as a regular, non-inline bucket for the rest of the tx. + b.page = nil + + return b.Bucket(key), nil +} + +// CreateBucketIfNotExists creates a new bucket if it doesn't already exist and returns a reference to it. +// Returns an error if the bucket name is blank, or if the bucket name is too long. +// The bucket instance is only valid for the lifetime of the transaction. +func (b *Bucket) CreateBucketIfNotExists(key []byte) (*Bucket, error) { + child, err := b.CreateBucket(key) + if err == ErrBucketExists { + return b.Bucket(key), nil + } else if err != nil { + return nil, err + } + return child, nil +} + +// DeleteBucket deletes a bucket at the given key. +// Returns an error if the bucket does not exists, or if the key represents a non-bucket value. +func (b *Bucket) DeleteBucket(key []byte) error { + if b.tx.db == nil { + return ErrTxClosed + } else if !b.Writable() { + return ErrTxNotWritable + } + + // Move cursor to correct position. + c := b.Cursor() + k, _, flags := c.seek(key) + + // Return an error if bucket doesn't exist or is not a bucket. + if !bytes.Equal(key, k) { + return ErrBucketNotFound + } else if (flags & bucketLeafFlag) == 0 { + return ErrIncompatibleValue + } + + // Recursively delete all child buckets. + child := b.Bucket(key) + err := child.ForEach(func(k, v []byte) error { + if v == nil { + if err := child.DeleteBucket(k); err != nil { + return fmt.Errorf("delete bucket: %s", err) + } + } + return nil + }) + if err != nil { + return err + } + + // Remove cached copy. + delete(b.buckets, string(key)) + + // Release all bucket pages to freelist. + child.nodes = nil + child.rootNode = nil + child.free() + + // Delete the node if we have a matching key. + c.node().del(key) + + return nil +} + +// Get retrieves the value for a key in the bucket. +// Returns a nil value if the key does not exist or if the key is a nested bucket. +// The returned value is only valid for the life of the transaction. +func (b *Bucket) Get(key []byte) []byte { + k, v, flags := b.Cursor().seek(key) + + // Return nil if this is a bucket. + if (flags & bucketLeafFlag) != 0 { + return nil + } + + // If our target node isn't the same key as what's passed in then return nil. + if !bytes.Equal(key, k) { + return nil + } + return v +} + +// Put sets the value for a key in the bucket. +// If the key exist then its previous value will be overwritten. +// Supplied value must remain valid for the life of the transaction. +// Returns an error if the bucket was created from a read-only transaction, if the key is blank, if the key is too large, or if the value is too large. +func (b *Bucket) Put(key []byte, value []byte) error { + if b.tx.db == nil { + return ErrTxClosed + } else if !b.Writable() { + return ErrTxNotWritable + } else if len(key) == 0 { + return ErrKeyRequired + } else if len(key) > MaxKeySize { + return ErrKeyTooLarge + } else if int64(len(value)) > MaxValueSize { + return ErrValueTooLarge + } + + // Move cursor to correct position. + c := b.Cursor() + k, _, flags := c.seek(key) + + // Return an error if there is an existing key with a bucket value. + if bytes.Equal(key, k) && (flags&bucketLeafFlag) != 0 { + return ErrIncompatibleValue + } + + // Insert into node. + key = cloneBytes(key) + c.node().put(key, key, value, 0, 0) + + return nil +} + +// Delete removes a key from the bucket. +// If the key does not exist then nothing is done and a nil error is returned. +// Returns an error if the bucket was created from a read-only transaction. +func (b *Bucket) Delete(key []byte) error { + if b.tx.db == nil { + return ErrTxClosed + } else if !b.Writable() { + return ErrTxNotWritable + } + + // Move cursor to correct position. + c := b.Cursor() + _, _, flags := c.seek(key) + + // Return an error if there is already existing bucket value. + if (flags & bucketLeafFlag) != 0 { + return ErrIncompatibleValue + } + + // Delete the node if we have a matching key. + c.node().del(key) + + return nil +} + +// Sequence returns the current integer for the bucket without incrementing it. +func (b *Bucket) Sequence() uint64 { return b.bucket.sequence } + +// SetSequence updates the sequence number for the bucket. +func (b *Bucket) SetSequence(v uint64) error { + if b.tx.db == nil { + return ErrTxClosed + } else if !b.Writable() { + return ErrTxNotWritable + } + + // Materialize the root node if it hasn't been already so that the + // bucket will be saved during commit. + if b.rootNode == nil { + _ = b.node(b.root, nil) + } + + // Increment and return the sequence. + b.bucket.sequence = v + return nil +} + +// NextSequence returns an autoincrementing integer for the bucket. +func (b *Bucket) NextSequence() (uint64, error) { + if b.tx.db == nil { + return 0, ErrTxClosed + } else if !b.Writable() { + return 0, ErrTxNotWritable + } + + // Materialize the root node if it hasn't been already so that the + // bucket will be saved during commit. + if b.rootNode == nil { + _ = b.node(b.root, nil) + } + + // Increment and return the sequence. + b.bucket.sequence++ + return b.bucket.sequence, nil +} + +// ForEach executes a function for each key/value pair in a bucket. +// If the provided function returns an error then the iteration is stopped and +// the error is returned to the caller. The provided function must not modify +// the bucket; this will result in undefined behavior. +func (b *Bucket) ForEach(fn func(k, v []byte) error) error { + if b.tx.db == nil { + return ErrTxClosed + } + c := b.Cursor() + for k, v := c.First(); k != nil; k, v = c.Next() { + if err := fn(k, v); err != nil { + return err + } + } + return nil +} + +// Stat returns stats on a bucket. +func (b *Bucket) Stats() BucketStats { + var s, subStats BucketStats + pageSize := b.tx.db.pageSize + s.BucketN += 1 + if b.root == 0 { + s.InlineBucketN += 1 + } + b.forEachPage(func(p *page, depth int) { + if (p.flags & leafPageFlag) != 0 { + s.KeyN += int(p.count) + + // used totals the used bytes for the page + used := pageHeaderSize + + if p.count != 0 { + // If page has any elements, add all element headers. + used += leafPageElementSize * int(p.count-1) + + // Add all element key, value sizes. + // The computation takes advantage of the fact that the position + // of the last element's key/value equals to the total of the sizes + // of all previous elements' keys and values. + // It also includes the last element's header. + lastElement := p.leafPageElement(p.count - 1) + used += int(lastElement.pos + lastElement.ksize + lastElement.vsize) + } + + if b.root == 0 { + // For inlined bucket just update the inline stats + s.InlineBucketInuse += used + } else { + // For non-inlined bucket update all the leaf stats + s.LeafPageN++ + s.LeafInuse += used + s.LeafOverflowN += int(p.overflow) + + // Collect stats from sub-buckets. + // Do that by iterating over all element headers + // looking for the ones with the bucketLeafFlag. + for i := uint16(0); i < p.count; i++ { + e := p.leafPageElement(i) + if (e.flags & bucketLeafFlag) != 0 { + // For any bucket element, open the element value + // and recursively call Stats on the contained bucket. + subStats.Add(b.openBucket(e.value()).Stats()) + } + } + } + } else if (p.flags & branchPageFlag) != 0 { + s.BranchPageN++ + lastElement := p.branchPageElement(p.count - 1) + + // used totals the used bytes for the page + // Add header and all element headers. + used := pageHeaderSize + (branchPageElementSize * int(p.count-1)) + + // Add size of all keys and values. + // Again, use the fact that last element's position equals to + // the total of key, value sizes of all previous elements. + used += int(lastElement.pos + lastElement.ksize) + s.BranchInuse += used + s.BranchOverflowN += int(p.overflow) + } + + // Keep track of maximum page depth. + if depth+1 > s.Depth { + s.Depth = (depth + 1) + } + }) + + // Alloc stats can be computed from page counts and pageSize. + s.BranchAlloc = (s.BranchPageN + s.BranchOverflowN) * pageSize + s.LeafAlloc = (s.LeafPageN + s.LeafOverflowN) * pageSize + + // Add the max depth of sub-buckets to get total nested depth. + s.Depth += subStats.Depth + // Add the stats for all sub-buckets + s.Add(subStats) + return s +} + +// forEachPage iterates over every page in a bucket, including inline pages. +func (b *Bucket) forEachPage(fn func(*page, int)) { + // If we have an inline page then just use that. + if b.page != nil { + fn(b.page, 0) + return + } + + // Otherwise traverse the page hierarchy. + b.tx.forEachPage(b.root, 0, fn) +} + +// forEachPageNode iterates over every page (or node) in a bucket. +// This also includes inline pages. +func (b *Bucket) forEachPageNode(fn func(*page, *node, int)) { + // If we have an inline page or root node then just use that. + if b.page != nil { + fn(b.page, nil, 0) + return + } + b._forEachPageNode(b.root, 0, fn) +} + +func (b *Bucket) _forEachPageNode(pgid pgid, depth int, fn func(*page, *node, int)) { + var p, n = b.pageNode(pgid) + + // Execute function. + fn(p, n, depth) + + // Recursively loop over children. + if p != nil { + if (p.flags & branchPageFlag) != 0 { + for i := 0; i < int(p.count); i++ { + elem := p.branchPageElement(uint16(i)) + b._forEachPageNode(elem.pgid, depth+1, fn) + } + } + } else { + if !n.isLeaf { + for _, inode := range n.inodes { + b._forEachPageNode(inode.pgid, depth+1, fn) + } + } + } +} + +// spill writes all the nodes for this bucket to dirty pages. +func (b *Bucket) spill() error { + // Spill all child buckets first. + for name, child := range b.buckets { + // If the child bucket is small enough and it has no child buckets then + // write it inline into the parent bucket's page. Otherwise spill it + // like a normal bucket and make the parent value a pointer to the page. + var value []byte + if child.inlineable() { + child.free() + value = child.write() + } else { + if err := child.spill(); err != nil { + return err + } + + // Update the child bucket header in this bucket. + value = make([]byte, unsafe.Sizeof(bucket{})) + var bucket = (*bucket)(unsafe.Pointer(&value[0])) + *bucket = *child.bucket + } + + // Skip writing the bucket if there are no materialized nodes. + if child.rootNode == nil { + continue + } + + // Update parent node. + var c = b.Cursor() + k, _, flags := c.seek([]byte(name)) + if !bytes.Equal([]byte(name), k) { + panic(fmt.Sprintf("misplaced bucket header: %x -> %x", []byte(name), k)) + } + if flags&bucketLeafFlag == 0 { + panic(fmt.Sprintf("unexpected bucket header flag: %x", flags)) + } + c.node().put([]byte(name), []byte(name), value, 0, bucketLeafFlag) + } + + // Ignore if there's not a materialized root node. + if b.rootNode == nil { + return nil + } + + // Spill nodes. + if err := b.rootNode.spill(); err != nil { + return err + } + b.rootNode = b.rootNode.root() + + // Update the root node for this bucket. + if b.rootNode.pgid >= b.tx.meta.pgid { + panic(fmt.Sprintf("pgid (%d) above high water mark (%d)", b.rootNode.pgid, b.tx.meta.pgid)) + } + b.root = b.rootNode.pgid + + return nil +} + +// inlineable returns true if a bucket is small enough to be written inline +// and if it contains no subbuckets. Otherwise returns false. +func (b *Bucket) inlineable() bool { + var n = b.rootNode + + // Bucket must only contain a single leaf node. + if n == nil || !n.isLeaf { + return false + } + + // Bucket is not inlineable if it contains subbuckets or if it goes beyond + // our threshold for inline bucket size. + var size = pageHeaderSize + for _, inode := range n.inodes { + size += leafPageElementSize + len(inode.key) + len(inode.value) + + if inode.flags&bucketLeafFlag != 0 { + return false + } else if size > b.maxInlineBucketSize() { + return false + } + } + + return true +} + +// Returns the maximum total size of a bucket to make it a candidate for inlining. +func (b *Bucket) maxInlineBucketSize() int { + return b.tx.db.pageSize / 4 +} + +// write allocates and writes a bucket to a byte slice. +func (b *Bucket) write() []byte { + // Allocate the appropriate size. + var n = b.rootNode + var value = make([]byte, bucketHeaderSize+n.size()) + + // Write a bucket header. + var bucket = (*bucket)(unsafe.Pointer(&value[0])) + *bucket = *b.bucket + + // Convert byte slice to a fake page and write the root node. + var p = (*page)(unsafe.Pointer(&value[bucketHeaderSize])) + n.write(p) + + return value +} + +// rebalance attempts to balance all nodes. +func (b *Bucket) rebalance() { + for _, n := range b.nodes { + n.rebalance() + } + for _, child := range b.buckets { + child.rebalance() + } +} + +// node creates a node from a page and associates it with a given parent. +func (b *Bucket) node(pgid pgid, parent *node) *node { + _assert(b.nodes != nil, "nodes map expected") + + // Retrieve node if it's already been created. + if n := b.nodes[pgid]; n != nil { + return n + } + + // Otherwise create a node and cache it. + n := &node{bucket: b, parent: parent} + if parent == nil { + b.rootNode = n + } else { + parent.children = append(parent.children, n) + } + + // Use the inline page if this is an inline bucket. + var p = b.page + if p == nil { + p = b.tx.page(pgid) + } + + // Read the page into the node and cache it. + n.read(p) + b.nodes[pgid] = n + + // Update statistics. + b.tx.stats.NodeCount++ + + return n +} + +// free recursively frees all pages in the bucket. +func (b *Bucket) free() { + if b.root == 0 { + return + } + + var tx = b.tx + b.forEachPageNode(func(p *page, n *node, _ int) { + if p != nil { + tx.db.freelist.free(tx.meta.txid, p) + } else { + n.free() + } + }) + b.root = 0 +} + +// dereference removes all references to the old mmap. +func (b *Bucket) dereference() { + if b.rootNode != nil { + b.rootNode.root().dereference() + } + + for _, child := range b.buckets { + child.dereference() + } +} + +// pageNode returns the in-memory node, if it exists. +// Otherwise returns the underlying page. +func (b *Bucket) pageNode(id pgid) (*page, *node) { + // Inline buckets have a fake page embedded in their value so treat them + // differently. We'll return the rootNode (if available) or the fake page. + if b.root == 0 { + if id != 0 { + panic(fmt.Sprintf("inline bucket non-zero page access(2): %d != 0", id)) + } + if b.rootNode != nil { + return nil, b.rootNode + } + return b.page, nil + } + + // Check the node cache for non-inline buckets. + if b.nodes != nil { + if n := b.nodes[id]; n != nil { + return nil, n + } + } + + // Finally lookup the page from the transaction if no node is materialized. + return b.tx.page(id), nil +} + +// BucketStats records statistics about resources used by a bucket. +type BucketStats struct { + // Page count statistics. + BranchPageN int // number of logical branch pages + BranchOverflowN int // number of physical branch overflow pages + LeafPageN int // number of logical leaf pages + LeafOverflowN int // number of physical leaf overflow pages + + // Tree statistics. + KeyN int // number of keys/value pairs + Depth int // number of levels in B+tree + + // Page size utilization. + BranchAlloc int // bytes allocated for physical branch pages + BranchInuse int // bytes actually used for branch data + LeafAlloc int // bytes allocated for physical leaf pages + LeafInuse int // bytes actually used for leaf data + + // Bucket statistics + BucketN int // total number of buckets including the top bucket + InlineBucketN int // total number on inlined buckets + InlineBucketInuse int // bytes used for inlined buckets (also accounted for in LeafInuse) +} + +func (s *BucketStats) Add(other BucketStats) { + s.BranchPageN += other.BranchPageN + s.BranchOverflowN += other.BranchOverflowN + s.LeafPageN += other.LeafPageN + s.LeafOverflowN += other.LeafOverflowN + s.KeyN += other.KeyN + if s.Depth < other.Depth { + s.Depth = other.Depth + } + s.BranchAlloc += other.BranchAlloc + s.BranchInuse += other.BranchInuse + s.LeafAlloc += other.LeafAlloc + s.LeafInuse += other.LeafInuse + + s.BucketN += other.BucketN + s.InlineBucketN += other.InlineBucketN + s.InlineBucketInuse += other.InlineBucketInuse +} + +// cloneBytes returns a copy of a given slice. +func cloneBytes(v []byte) []byte { + var clone = make([]byte, len(v)) + copy(clone, v) + return clone +} diff --git a/vendor/github.com/boltdb/bolt/bucket_test.go b/vendor/github.com/boltdb/bolt/bucket_test.go new file mode 100644 index 00000000..cddbe271 --- /dev/null +++ b/vendor/github.com/boltdb/bolt/bucket_test.go @@ -0,0 +1,1909 @@ +package bolt_test + +import ( + "bytes" + "encoding/binary" + "errors" + "fmt" + "log" + "math/rand" + "os" + "strconv" + "strings" + "testing" + "testing/quick" + + "github.com/boltdb/bolt" +) + +// Ensure that a bucket that gets a non-existent key returns nil. +func TestBucket_Get_NonExistent(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + if v := b.Get([]byte("foo")); v != nil { + t.Fatal("expected nil value") + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that a bucket can read a value that is not flushed yet. +func TestBucket_Get_FromNode(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("foo"), []byte("bar")); err != nil { + t.Fatal(err) + } + if v := b.Get([]byte("foo")); !bytes.Equal(v, []byte("bar")) { + t.Fatalf("unexpected value: %v", v) + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that a bucket retrieved via Get() returns a nil. +func TestBucket_Get_IncompatibleValue(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + if err := db.Update(func(tx *bolt.Tx) error { + _, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + + if _, err := tx.Bucket([]byte("widgets")).CreateBucket([]byte("foo")); err != nil { + t.Fatal(err) + } + + if tx.Bucket([]byte("widgets")).Get([]byte("foo")) != nil { + t.Fatal("expected nil value") + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that a slice returned from a bucket has a capacity equal to its length. +// This also allows slices to be appended to since it will require a realloc by Go. +// +// https://github.com/boltdb/bolt/issues/544 +func TestBucket_Get_Capacity(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + // Write key to a bucket. + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("bucket")) + if err != nil { + return err + } + return b.Put([]byte("key"), []byte("val")) + }); err != nil { + t.Fatal(err) + } + + // Retrieve value and attempt to append to it. + if err := db.Update(func(tx *bolt.Tx) error { + k, v := tx.Bucket([]byte("bucket")).Cursor().First() + + // Verify capacity. + if len(k) != cap(k) { + t.Fatalf("unexpected key slice capacity: %d", cap(k)) + } else if len(v) != cap(v) { + t.Fatalf("unexpected value slice capacity: %d", cap(v)) + } + + // Ensure slice can be appended to without a segfault. + k = append(k, []byte("123")...) + v = append(v, []byte("123")...) + + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that a bucket can write a key/value. +func TestBucket_Put(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("foo"), []byte("bar")); err != nil { + t.Fatal(err) + } + + v := tx.Bucket([]byte("widgets")).Get([]byte("foo")) + if !bytes.Equal([]byte("bar"), v) { + t.Fatalf("unexpected value: %v", v) + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that a bucket can rewrite a key in the same transaction. +func TestBucket_Put_Repeat(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("foo"), []byte("bar")); err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("foo"), []byte("baz")); err != nil { + t.Fatal(err) + } + + value := tx.Bucket([]byte("widgets")).Get([]byte("foo")) + if !bytes.Equal([]byte("baz"), value) { + t.Fatalf("unexpected value: %v", value) + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that a bucket can write a bunch of large values. +func TestBucket_Put_Large(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + count, factor := 100, 200 + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + for i := 1; i < count; i++ { + if err := b.Put([]byte(strings.Repeat("0", i*factor)), []byte(strings.Repeat("X", (count-i)*factor))); err != nil { + t.Fatal(err) + } + } + return nil + }); err != nil { + t.Fatal(err) + } + + if err := db.View(func(tx *bolt.Tx) error { + b := tx.Bucket([]byte("widgets")) + for i := 1; i < count; i++ { + value := b.Get([]byte(strings.Repeat("0", i*factor))) + if !bytes.Equal(value, []byte(strings.Repeat("X", (count-i)*factor))) { + t.Fatalf("unexpected value: %v", value) + } + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that a database can perform multiple large appends safely. +func TestDB_Put_VeryLarge(t *testing.T) { + if testing.Short() { + t.Skip("skipping test in short mode.") + } + + n, batchN := 400000, 200000 + ksize, vsize := 8, 500 + + db := MustOpenDB() + defer db.MustClose() + + for i := 0; i < n; i += batchN { + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucketIfNotExists([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + for j := 0; j < batchN; j++ { + k, v := make([]byte, ksize), make([]byte, vsize) + binary.BigEndian.PutUint32(k, uint32(i+j)) + if err := b.Put(k, v); err != nil { + t.Fatal(err) + } + } + return nil + }); err != nil { + t.Fatal(err) + } + } +} + +// Ensure that a setting a value on a key with a bucket value returns an error. +func TestBucket_Put_IncompatibleValue(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + if err := db.Update(func(tx *bolt.Tx) error { + b0, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + + if _, err := tx.Bucket([]byte("widgets")).CreateBucket([]byte("foo")); err != nil { + t.Fatal(err) + } + if err := b0.Put([]byte("foo"), []byte("bar")); err != bolt.ErrIncompatibleValue { + t.Fatalf("unexpected error: %s", err) + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that a setting a value while the transaction is closed returns an error. +func TestBucket_Put_Closed(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + tx, err := db.Begin(true) + if err != nil { + t.Fatal(err) + } + + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + + if err := tx.Rollback(); err != nil { + t.Fatal(err) + } + + if err := b.Put([]byte("foo"), []byte("bar")); err != bolt.ErrTxClosed { + t.Fatalf("unexpected error: %s", err) + } +} + +// Ensure that setting a value on a read-only bucket returns an error. +func TestBucket_Put_ReadOnly(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + if err := db.Update(func(tx *bolt.Tx) error { + if _, err := tx.CreateBucket([]byte("widgets")); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + + if err := db.View(func(tx *bolt.Tx) error { + b := tx.Bucket([]byte("widgets")) + if err := b.Put([]byte("foo"), []byte("bar")); err != bolt.ErrTxNotWritable { + t.Fatalf("unexpected error: %s", err) + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that a bucket can delete an existing key. +func TestBucket_Delete(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("foo"), []byte("bar")); err != nil { + t.Fatal(err) + } + if err := b.Delete([]byte("foo")); err != nil { + t.Fatal(err) + } + if v := b.Get([]byte("foo")); v != nil { + t.Fatalf("unexpected value: %v", v) + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that deleting a large set of keys will work correctly. +func TestBucket_Delete_Large(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + + for i := 0; i < 100; i++ { + if err := b.Put([]byte(strconv.Itoa(i)), []byte(strings.Repeat("*", 1024))); err != nil { + t.Fatal(err) + } + } + + return nil + }); err != nil { + t.Fatal(err) + } + + if err := db.Update(func(tx *bolt.Tx) error { + b := tx.Bucket([]byte("widgets")) + for i := 0; i < 100; i++ { + if err := b.Delete([]byte(strconv.Itoa(i))); err != nil { + t.Fatal(err) + } + } + return nil + }); err != nil { + t.Fatal(err) + } + + if err := db.View(func(tx *bolt.Tx) error { + b := tx.Bucket([]byte("widgets")) + for i := 0; i < 100; i++ { + if v := b.Get([]byte(strconv.Itoa(i))); v != nil { + t.Fatalf("unexpected value: %v, i=%d", v, i) + } + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Deleting a very large list of keys will cause the freelist to use overflow. +func TestBucket_Delete_FreelistOverflow(t *testing.T) { + if testing.Short() { + t.Skip("skipping test in short mode.") + } + + db := MustOpenDB() + defer db.MustClose() + + k := make([]byte, 16) + for i := uint64(0); i < 10000; i++ { + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucketIfNotExists([]byte("0")) + if err != nil { + t.Fatalf("bucket error: %s", err) + } + + for j := uint64(0); j < 1000; j++ { + binary.BigEndian.PutUint64(k[:8], i) + binary.BigEndian.PutUint64(k[8:], j) + if err := b.Put(k, nil); err != nil { + t.Fatalf("put error: %s", err) + } + } + + return nil + }); err != nil { + t.Fatal(err) + } + } + + // Delete all of them in one large transaction + if err := db.Update(func(tx *bolt.Tx) error { + b := tx.Bucket([]byte("0")) + c := b.Cursor() + for k, _ := c.First(); k != nil; k, _ = c.Next() { + if err := c.Delete(); err != nil { + t.Fatal(err) + } + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that accessing and updating nested buckets is ok across transactions. +func TestBucket_Nested(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + if err := db.Update(func(tx *bolt.Tx) error { + // Create a widgets bucket. + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + + // Create a widgets/foo bucket. + _, err = b.CreateBucket([]byte("foo")) + if err != nil { + t.Fatal(err) + } + + // Create a widgets/bar key. + if err := b.Put([]byte("bar"), []byte("0000")); err != nil { + t.Fatal(err) + } + + return nil + }); err != nil { + t.Fatal(err) + } + db.MustCheck() + + // Update widgets/bar. + if err := db.Update(func(tx *bolt.Tx) error { + b := tx.Bucket([]byte("widgets")) + if err := b.Put([]byte("bar"), []byte("xxxx")); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + db.MustCheck() + + // Cause a split. + if err := db.Update(func(tx *bolt.Tx) error { + var b = tx.Bucket([]byte("widgets")) + for i := 0; i < 10000; i++ { + if err := b.Put([]byte(strconv.Itoa(i)), []byte(strconv.Itoa(i))); err != nil { + t.Fatal(err) + } + } + return nil + }); err != nil { + t.Fatal(err) + } + db.MustCheck() + + // Insert into widgets/foo/baz. + if err := db.Update(func(tx *bolt.Tx) error { + var b = tx.Bucket([]byte("widgets")) + if err := b.Bucket([]byte("foo")).Put([]byte("baz"), []byte("yyyy")); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + db.MustCheck() + + // Verify. + if err := db.View(func(tx *bolt.Tx) error { + var b = tx.Bucket([]byte("widgets")) + if v := b.Bucket([]byte("foo")).Get([]byte("baz")); !bytes.Equal(v, []byte("yyyy")) { + t.Fatalf("unexpected value: %v", v) + } + if v := b.Get([]byte("bar")); !bytes.Equal(v, []byte("xxxx")) { + t.Fatalf("unexpected value: %v", v) + } + for i := 0; i < 10000; i++ { + if v := b.Get([]byte(strconv.Itoa(i))); !bytes.Equal(v, []byte(strconv.Itoa(i))) { + t.Fatalf("unexpected value: %v", v) + } + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that deleting a bucket using Delete() returns an error. +func TestBucket_Delete_Bucket(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + if _, err := b.CreateBucket([]byte("foo")); err != nil { + t.Fatal(err) + } + if err := b.Delete([]byte("foo")); err != bolt.ErrIncompatibleValue { + t.Fatalf("unexpected error: %s", err) + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that deleting a key on a read-only bucket returns an error. +func TestBucket_Delete_ReadOnly(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + if err := db.Update(func(tx *bolt.Tx) error { + if _, err := tx.CreateBucket([]byte("widgets")); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + + if err := db.View(func(tx *bolt.Tx) error { + if err := tx.Bucket([]byte("widgets")).Delete([]byte("foo")); err != bolt.ErrTxNotWritable { + t.Fatalf("unexpected error: %s", err) + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that a deleting value while the transaction is closed returns an error. +func TestBucket_Delete_Closed(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + tx, err := db.Begin(true) + if err != nil { + t.Fatal(err) + } + + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + + if err := tx.Rollback(); err != nil { + t.Fatal(err) + } + if err := b.Delete([]byte("foo")); err != bolt.ErrTxClosed { + t.Fatalf("unexpected error: %s", err) + } +} + +// Ensure that deleting a bucket causes nested buckets to be deleted. +func TestBucket_DeleteBucket_Nested(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + if err := db.Update(func(tx *bolt.Tx) error { + widgets, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + + foo, err := widgets.CreateBucket([]byte("foo")) + if err != nil { + t.Fatal(err) + } + + bar, err := foo.CreateBucket([]byte("bar")) + if err != nil { + t.Fatal(err) + } + if err := bar.Put([]byte("baz"), []byte("bat")); err != nil { + t.Fatal(err) + } + if err := tx.Bucket([]byte("widgets")).DeleteBucket([]byte("foo")); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that deleting a bucket causes nested buckets to be deleted after they have been committed. +func TestBucket_DeleteBucket_Nested2(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + if err := db.Update(func(tx *bolt.Tx) error { + widgets, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + + foo, err := widgets.CreateBucket([]byte("foo")) + if err != nil { + t.Fatal(err) + } + + bar, err := foo.CreateBucket([]byte("bar")) + if err != nil { + t.Fatal(err) + } + + if err := bar.Put([]byte("baz"), []byte("bat")); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + + if err := db.Update(func(tx *bolt.Tx) error { + widgets := tx.Bucket([]byte("widgets")) + if widgets == nil { + t.Fatal("expected widgets bucket") + } + + foo := widgets.Bucket([]byte("foo")) + if foo == nil { + t.Fatal("expected foo bucket") + } + + bar := foo.Bucket([]byte("bar")) + if bar == nil { + t.Fatal("expected bar bucket") + } + + if v := bar.Get([]byte("baz")); !bytes.Equal(v, []byte("bat")) { + t.Fatalf("unexpected value: %v", v) + } + if err := tx.DeleteBucket([]byte("widgets")); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + + if err := db.View(func(tx *bolt.Tx) error { + if tx.Bucket([]byte("widgets")) != nil { + t.Fatal("expected bucket to be deleted") + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that deleting a child bucket with multiple pages causes all pages to get collected. +// NOTE: Consistency check in bolt_test.DB.Close() will panic if pages not freed properly. +func TestBucket_DeleteBucket_Large(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + if err := db.Update(func(tx *bolt.Tx) error { + widgets, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + + foo, err := widgets.CreateBucket([]byte("foo")) + if err != nil { + t.Fatal(err) + } + + for i := 0; i < 1000; i++ { + if err := foo.Put([]byte(fmt.Sprintf("%d", i)), []byte(fmt.Sprintf("%0100d", i))); err != nil { + t.Fatal(err) + } + } + return nil + }); err != nil { + t.Fatal(err) + } + + if err := db.Update(func(tx *bolt.Tx) error { + if err := tx.DeleteBucket([]byte("widgets")); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that a simple value retrieved via Bucket() returns a nil. +func TestBucket_Bucket_IncompatibleValue(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + if err := db.Update(func(tx *bolt.Tx) error { + widgets, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + + if err := widgets.Put([]byte("foo"), []byte("bar")); err != nil { + t.Fatal(err) + } + if b := tx.Bucket([]byte("widgets")).Bucket([]byte("foo")); b != nil { + t.Fatal("expected nil bucket") + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that creating a bucket on an existing non-bucket key returns an error. +func TestBucket_CreateBucket_IncompatibleValue(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + if err := db.Update(func(tx *bolt.Tx) error { + widgets, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + + if err := widgets.Put([]byte("foo"), []byte("bar")); err != nil { + t.Fatal(err) + } + if _, err := widgets.CreateBucket([]byte("foo")); err != bolt.ErrIncompatibleValue { + t.Fatalf("unexpected error: %s", err) + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that deleting a bucket on an existing non-bucket key returns an error. +func TestBucket_DeleteBucket_IncompatibleValue(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + if err := db.Update(func(tx *bolt.Tx) error { + widgets, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + if err := widgets.Put([]byte("foo"), []byte("bar")); err != nil { + t.Fatal(err) + } + if err := tx.Bucket([]byte("widgets")).DeleteBucket([]byte("foo")); err != bolt.ErrIncompatibleValue { + t.Fatalf("unexpected error: %s", err) + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure bucket can set and update its sequence number. +func TestBucket_Sequence(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + if err := db.Update(func(tx *bolt.Tx) error { + bkt, err := tx.CreateBucket([]byte("0")) + if err != nil { + t.Fatal(err) + } + + // Retrieve sequence. + if v := bkt.Sequence(); v != 0 { + t.Fatalf("unexpected sequence: %d", v) + } + + // Update sequence. + if err := bkt.SetSequence(1000); err != nil { + t.Fatal(err) + } + + // Read sequence again. + if v := bkt.Sequence(); v != 1000 { + t.Fatalf("unexpected sequence: %d", v) + } + + return nil + }); err != nil { + t.Fatal(err) + } + + // Verify sequence in separate transaction. + if err := db.View(func(tx *bolt.Tx) error { + if v := tx.Bucket([]byte("0")).Sequence(); v != 1000 { + t.Fatalf("unexpected sequence: %d", v) + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that a bucket can return an autoincrementing sequence. +func TestBucket_NextSequence(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + if err := db.Update(func(tx *bolt.Tx) error { + widgets, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + woojits, err := tx.CreateBucket([]byte("woojits")) + if err != nil { + t.Fatal(err) + } + + // Make sure sequence increments. + if seq, err := widgets.NextSequence(); err != nil { + t.Fatal(err) + } else if seq != 1 { + t.Fatalf("unexpecte sequence: %d", seq) + } + + if seq, err := widgets.NextSequence(); err != nil { + t.Fatal(err) + } else if seq != 2 { + t.Fatalf("unexpected sequence: %d", seq) + } + + // Buckets should be separate. + if seq, err := woojits.NextSequence(); err != nil { + t.Fatal(err) + } else if seq != 1 { + t.Fatalf("unexpected sequence: %d", 1) + } + + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that a bucket will persist an autoincrementing sequence even if its +// the only thing updated on the bucket. +// https://github.com/boltdb/bolt/issues/296 +func TestBucket_NextSequence_Persist(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + if err := db.Update(func(tx *bolt.Tx) error { + if _, err := tx.CreateBucket([]byte("widgets")); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + + if err := db.Update(func(tx *bolt.Tx) error { + if _, err := tx.Bucket([]byte("widgets")).NextSequence(); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + + if err := db.Update(func(tx *bolt.Tx) error { + seq, err := tx.Bucket([]byte("widgets")).NextSequence() + if err != nil { + t.Fatalf("unexpected error: %s", err) + } else if seq != 2 { + t.Fatalf("unexpected sequence: %d", seq) + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that retrieving the next sequence on a read-only bucket returns an error. +func TestBucket_NextSequence_ReadOnly(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + if err := db.Update(func(tx *bolt.Tx) error { + if _, err := tx.CreateBucket([]byte("widgets")); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + + if err := db.View(func(tx *bolt.Tx) error { + _, err := tx.Bucket([]byte("widgets")).NextSequence() + if err != bolt.ErrTxNotWritable { + t.Fatalf("unexpected error: %s", err) + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that retrieving the next sequence for a bucket on a closed database return an error. +func TestBucket_NextSequence_Closed(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + tx, err := db.Begin(true) + if err != nil { + t.Fatal(err) + } + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + if err := tx.Rollback(); err != nil { + t.Fatal(err) + } + if _, err := b.NextSequence(); err != bolt.ErrTxClosed { + t.Fatal(err) + } +} + +// Ensure a user can loop over all key/value pairs in a bucket. +func TestBucket_ForEach(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("foo"), []byte("0000")); err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("baz"), []byte("0001")); err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("bar"), []byte("0002")); err != nil { + t.Fatal(err) + } + + var index int + if err := b.ForEach(func(k, v []byte) error { + switch index { + case 0: + if !bytes.Equal(k, []byte("bar")) { + t.Fatalf("unexpected key: %v", k) + } else if !bytes.Equal(v, []byte("0002")) { + t.Fatalf("unexpected value: %v", v) + } + case 1: + if !bytes.Equal(k, []byte("baz")) { + t.Fatalf("unexpected key: %v", k) + } else if !bytes.Equal(v, []byte("0001")) { + t.Fatalf("unexpected value: %v", v) + } + case 2: + if !bytes.Equal(k, []byte("foo")) { + t.Fatalf("unexpected key: %v", k) + } else if !bytes.Equal(v, []byte("0000")) { + t.Fatalf("unexpected value: %v", v) + } + } + index++ + return nil + }); err != nil { + t.Fatal(err) + } + + if index != 3 { + t.Fatalf("unexpected index: %d", index) + } + + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure a database can stop iteration early. +func TestBucket_ForEach_ShortCircuit(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("bar"), []byte("0000")); err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("baz"), []byte("0000")); err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("foo"), []byte("0000")); err != nil { + t.Fatal(err) + } + + var index int + if err := tx.Bucket([]byte("widgets")).ForEach(func(k, v []byte) error { + index++ + if bytes.Equal(k, []byte("baz")) { + return errors.New("marker") + } + return nil + }); err == nil || err.Error() != "marker" { + t.Fatalf("unexpected error: %s", err) + } + if index != 2 { + t.Fatalf("unexpected index: %d", index) + } + + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that looping over a bucket on a closed database returns an error. +func TestBucket_ForEach_Closed(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + tx, err := db.Begin(true) + if err != nil { + t.Fatal(err) + } + + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + + if err := tx.Rollback(); err != nil { + t.Fatal(err) + } + + if err := b.ForEach(func(k, v []byte) error { return nil }); err != bolt.ErrTxClosed { + t.Fatalf("unexpected error: %s", err) + } +} + +// Ensure that an error is returned when inserting with an empty key. +func TestBucket_Put_EmptyKey(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + if err := b.Put([]byte(""), []byte("bar")); err != bolt.ErrKeyRequired { + t.Fatalf("unexpected error: %s", err) + } + if err := b.Put(nil, []byte("bar")); err != bolt.ErrKeyRequired { + t.Fatalf("unexpected error: %s", err) + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that an error is returned when inserting with a key that's too large. +func TestBucket_Put_KeyTooLarge(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + if err := b.Put(make([]byte, 32769), []byte("bar")); err != bolt.ErrKeyTooLarge { + t.Fatalf("unexpected error: %s", err) + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that an error is returned when inserting a value that's too large. +func TestBucket_Put_ValueTooLarge(t *testing.T) { + // Skip this test on DroneCI because the machine is resource constrained. + if os.Getenv("DRONE") == "true" { + t.Skip("not enough RAM for test") + } + + db := MustOpenDB() + defer db.MustClose() + + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("foo"), make([]byte, bolt.MaxValueSize+1)); err != bolt.ErrValueTooLarge { + t.Fatalf("unexpected error: %s", err) + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure a bucket can calculate stats. +func TestBucket_Stats(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + // Add bucket with fewer keys but one big value. + bigKey := []byte("really-big-value") + for i := 0; i < 500; i++ { + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucketIfNotExists([]byte("woojits")) + if err != nil { + t.Fatal(err) + } + + if err := b.Put([]byte(fmt.Sprintf("%03d", i)), []byte(strconv.Itoa(i))); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + } + if err := db.Update(func(tx *bolt.Tx) error { + if err := tx.Bucket([]byte("woojits")).Put(bigKey, []byte(strings.Repeat("*", 10000))); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + + db.MustCheck() + + if err := db.View(func(tx *bolt.Tx) error { + stats := tx.Bucket([]byte("woojits")).Stats() + if stats.BranchPageN != 1 { + t.Fatalf("unexpected BranchPageN: %d", stats.BranchPageN) + } else if stats.BranchOverflowN != 0 { + t.Fatalf("unexpected BranchOverflowN: %d", stats.BranchOverflowN) + } else if stats.LeafPageN != 7 { + t.Fatalf("unexpected LeafPageN: %d", stats.LeafPageN) + } else if stats.LeafOverflowN != 2 { + t.Fatalf("unexpected LeafOverflowN: %d", stats.LeafOverflowN) + } else if stats.KeyN != 501 { + t.Fatalf("unexpected KeyN: %d", stats.KeyN) + } else if stats.Depth != 2 { + t.Fatalf("unexpected Depth: %d", stats.Depth) + } + + branchInuse := 16 // branch page header + branchInuse += 7 * 16 // branch elements + branchInuse += 7 * 3 // branch keys (6 3-byte keys) + if stats.BranchInuse != branchInuse { + t.Fatalf("unexpected BranchInuse: %d", stats.BranchInuse) + } + + leafInuse := 7 * 16 // leaf page header + leafInuse += 501 * 16 // leaf elements + leafInuse += 500*3 + len(bigKey) // leaf keys + leafInuse += 1*10 + 2*90 + 3*400 + 10000 // leaf values + if stats.LeafInuse != leafInuse { + t.Fatalf("unexpected LeafInuse: %d", stats.LeafInuse) + } + + // Only check allocations for 4KB pages. + if os.Getpagesize() == 4096 { + if stats.BranchAlloc != 4096 { + t.Fatalf("unexpected BranchAlloc: %d", stats.BranchAlloc) + } else if stats.LeafAlloc != 36864 { + t.Fatalf("unexpected LeafAlloc: %d", stats.LeafAlloc) + } + } + + if stats.BucketN != 1 { + t.Fatalf("unexpected BucketN: %d", stats.BucketN) + } else if stats.InlineBucketN != 0 { + t.Fatalf("unexpected InlineBucketN: %d", stats.InlineBucketN) + } else if stats.InlineBucketInuse != 0 { + t.Fatalf("unexpected InlineBucketInuse: %d", stats.InlineBucketInuse) + } + + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure a bucket with random insertion utilizes fill percentage correctly. +func TestBucket_Stats_RandomFill(t *testing.T) { + if testing.Short() { + t.Skip("skipping test in short mode.") + } else if os.Getpagesize() != 4096 { + t.Skip("invalid page size for test") + } + + db := MustOpenDB() + defer db.MustClose() + + // Add a set of values in random order. It will be the same random + // order so we can maintain consistency between test runs. + var count int + rand := rand.New(rand.NewSource(42)) + for _, i := range rand.Perm(1000) { + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucketIfNotExists([]byte("woojits")) + if err != nil { + t.Fatal(err) + } + b.FillPercent = 0.9 + for _, j := range rand.Perm(100) { + index := (j * 10000) + i + if err := b.Put([]byte(fmt.Sprintf("%d000000000000000", index)), []byte("0000000000")); err != nil { + t.Fatal(err) + } + count++ + } + return nil + }); err != nil { + t.Fatal(err) + } + } + + db.MustCheck() + + if err := db.View(func(tx *bolt.Tx) error { + stats := tx.Bucket([]byte("woojits")).Stats() + if stats.KeyN != 100000 { + t.Fatalf("unexpected KeyN: %d", stats.KeyN) + } + + if stats.BranchPageN != 98 { + t.Fatalf("unexpected BranchPageN: %d", stats.BranchPageN) + } else if stats.BranchOverflowN != 0 { + t.Fatalf("unexpected BranchOverflowN: %d", stats.BranchOverflowN) + } else if stats.BranchInuse != 130984 { + t.Fatalf("unexpected BranchInuse: %d", stats.BranchInuse) + } else if stats.BranchAlloc != 401408 { + t.Fatalf("unexpected BranchAlloc: %d", stats.BranchAlloc) + } + + if stats.LeafPageN != 3412 { + t.Fatalf("unexpected LeafPageN: %d", stats.LeafPageN) + } else if stats.LeafOverflowN != 0 { + t.Fatalf("unexpected LeafOverflowN: %d", stats.LeafOverflowN) + } else if stats.LeafInuse != 4742482 { + t.Fatalf("unexpected LeafInuse: %d", stats.LeafInuse) + } else if stats.LeafAlloc != 13975552 { + t.Fatalf("unexpected LeafAlloc: %d", stats.LeafAlloc) + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure a bucket can calculate stats. +func TestBucket_Stats_Small(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + if err := db.Update(func(tx *bolt.Tx) error { + // Add a bucket that fits on a single root leaf. + b, err := tx.CreateBucket([]byte("whozawhats")) + if err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("foo"), []byte("bar")); err != nil { + t.Fatal(err) + } + + return nil + }); err != nil { + t.Fatal(err) + } + + db.MustCheck() + + if err := db.View(func(tx *bolt.Tx) error { + b := tx.Bucket([]byte("whozawhats")) + stats := b.Stats() + if stats.BranchPageN != 0 { + t.Fatalf("unexpected BranchPageN: %d", stats.BranchPageN) + } else if stats.BranchOverflowN != 0 { + t.Fatalf("unexpected BranchOverflowN: %d", stats.BranchOverflowN) + } else if stats.LeafPageN != 0 { + t.Fatalf("unexpected LeafPageN: %d", stats.LeafPageN) + } else if stats.LeafOverflowN != 0 { + t.Fatalf("unexpected LeafOverflowN: %d", stats.LeafOverflowN) + } else if stats.KeyN != 1 { + t.Fatalf("unexpected KeyN: %d", stats.KeyN) + } else if stats.Depth != 1 { + t.Fatalf("unexpected Depth: %d", stats.Depth) + } else if stats.BranchInuse != 0 { + t.Fatalf("unexpected BranchInuse: %d", stats.BranchInuse) + } else if stats.LeafInuse != 0 { + t.Fatalf("unexpected LeafInuse: %d", stats.LeafInuse) + } + + if os.Getpagesize() == 4096 { + if stats.BranchAlloc != 0 { + t.Fatalf("unexpected BranchAlloc: %d", stats.BranchAlloc) + } else if stats.LeafAlloc != 0 { + t.Fatalf("unexpected LeafAlloc: %d", stats.LeafAlloc) + } + } + + if stats.BucketN != 1 { + t.Fatalf("unexpected BucketN: %d", stats.BucketN) + } else if stats.InlineBucketN != 1 { + t.Fatalf("unexpected InlineBucketN: %d", stats.InlineBucketN) + } else if stats.InlineBucketInuse != 16+16+6 { + t.Fatalf("unexpected InlineBucketInuse: %d", stats.InlineBucketInuse) + } + + return nil + }); err != nil { + t.Fatal(err) + } +} + +func TestBucket_Stats_EmptyBucket(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + if err := db.Update(func(tx *bolt.Tx) error { + // Add a bucket that fits on a single root leaf. + if _, err := tx.CreateBucket([]byte("whozawhats")); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + + db.MustCheck() + + if err := db.View(func(tx *bolt.Tx) error { + b := tx.Bucket([]byte("whozawhats")) + stats := b.Stats() + if stats.BranchPageN != 0 { + t.Fatalf("unexpected BranchPageN: %d", stats.BranchPageN) + } else if stats.BranchOverflowN != 0 { + t.Fatalf("unexpected BranchOverflowN: %d", stats.BranchOverflowN) + } else if stats.LeafPageN != 0 { + t.Fatalf("unexpected LeafPageN: %d", stats.LeafPageN) + } else if stats.LeafOverflowN != 0 { + t.Fatalf("unexpected LeafOverflowN: %d", stats.LeafOverflowN) + } else if stats.KeyN != 0 { + t.Fatalf("unexpected KeyN: %d", stats.KeyN) + } else if stats.Depth != 1 { + t.Fatalf("unexpected Depth: %d", stats.Depth) + } else if stats.BranchInuse != 0 { + t.Fatalf("unexpected BranchInuse: %d", stats.BranchInuse) + } else if stats.LeafInuse != 0 { + t.Fatalf("unexpected LeafInuse: %d", stats.LeafInuse) + } + + if os.Getpagesize() == 4096 { + if stats.BranchAlloc != 0 { + t.Fatalf("unexpected BranchAlloc: %d", stats.BranchAlloc) + } else if stats.LeafAlloc != 0 { + t.Fatalf("unexpected LeafAlloc: %d", stats.LeafAlloc) + } + } + + if stats.BucketN != 1 { + t.Fatalf("unexpected BucketN: %d", stats.BucketN) + } else if stats.InlineBucketN != 1 { + t.Fatalf("unexpected InlineBucketN: %d", stats.InlineBucketN) + } else if stats.InlineBucketInuse != 16 { + t.Fatalf("unexpected InlineBucketInuse: %d", stats.InlineBucketInuse) + } + + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure a bucket can calculate stats. +func TestBucket_Stats_Nested(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("foo")) + if err != nil { + t.Fatal(err) + } + for i := 0; i < 100; i++ { + if err := b.Put([]byte(fmt.Sprintf("%02d", i)), []byte(fmt.Sprintf("%02d", i))); err != nil { + t.Fatal(err) + } + } + + bar, err := b.CreateBucket([]byte("bar")) + if err != nil { + t.Fatal(err) + } + for i := 0; i < 10; i++ { + if err := bar.Put([]byte(strconv.Itoa(i)), []byte(strconv.Itoa(i))); err != nil { + t.Fatal(err) + } + } + + baz, err := bar.CreateBucket([]byte("baz")) + if err != nil { + t.Fatal(err) + } + for i := 0; i < 10; i++ { + if err := baz.Put([]byte(strconv.Itoa(i)), []byte(strconv.Itoa(i))); err != nil { + t.Fatal(err) + } + } + + return nil + }); err != nil { + t.Fatal(err) + } + + db.MustCheck() + + if err := db.View(func(tx *bolt.Tx) error { + b := tx.Bucket([]byte("foo")) + stats := b.Stats() + if stats.BranchPageN != 0 { + t.Fatalf("unexpected BranchPageN: %d", stats.BranchPageN) + } else if stats.BranchOverflowN != 0 { + t.Fatalf("unexpected BranchOverflowN: %d", stats.BranchOverflowN) + } else if stats.LeafPageN != 2 { + t.Fatalf("unexpected LeafPageN: %d", stats.LeafPageN) + } else if stats.LeafOverflowN != 0 { + t.Fatalf("unexpected LeafOverflowN: %d", stats.LeafOverflowN) + } else if stats.KeyN != 122 { + t.Fatalf("unexpected KeyN: %d", stats.KeyN) + } else if stats.Depth != 3 { + t.Fatalf("unexpected Depth: %d", stats.Depth) + } else if stats.BranchInuse != 0 { + t.Fatalf("unexpected BranchInuse: %d", stats.BranchInuse) + } + + foo := 16 // foo (pghdr) + foo += 101 * 16 // foo leaf elements + foo += 100*2 + 100*2 // foo leaf key/values + foo += 3 + 16 // foo -> bar key/value + + bar := 16 // bar (pghdr) + bar += 11 * 16 // bar leaf elements + bar += 10 + 10 // bar leaf key/values + bar += 3 + 16 // bar -> baz key/value + + baz := 16 // baz (inline) (pghdr) + baz += 10 * 16 // baz leaf elements + baz += 10 + 10 // baz leaf key/values + + if stats.LeafInuse != foo+bar+baz { + t.Fatalf("unexpected LeafInuse: %d", stats.LeafInuse) + } + + if os.Getpagesize() == 4096 { + if stats.BranchAlloc != 0 { + t.Fatalf("unexpected BranchAlloc: %d", stats.BranchAlloc) + } else if stats.LeafAlloc != 8192 { + t.Fatalf("unexpected LeafAlloc: %d", stats.LeafAlloc) + } + } + + if stats.BucketN != 3 { + t.Fatalf("unexpected BucketN: %d", stats.BucketN) + } else if stats.InlineBucketN != 1 { + t.Fatalf("unexpected InlineBucketN: %d", stats.InlineBucketN) + } else if stats.InlineBucketInuse != baz { + t.Fatalf("unexpected InlineBucketInuse: %d", stats.InlineBucketInuse) + } + + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure a large bucket can calculate stats. +func TestBucket_Stats_Large(t *testing.T) { + if testing.Short() { + t.Skip("skipping test in short mode.") + } + + db := MustOpenDB() + defer db.MustClose() + + var index int + for i := 0; i < 100; i++ { + // Add bucket with lots of keys. + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucketIfNotExists([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + for i := 0; i < 1000; i++ { + if err := b.Put([]byte(strconv.Itoa(index)), []byte(strconv.Itoa(index))); err != nil { + t.Fatal(err) + } + index++ + } + return nil + }); err != nil { + t.Fatal(err) + } + } + + db.MustCheck() + + if err := db.View(func(tx *bolt.Tx) error { + stats := tx.Bucket([]byte("widgets")).Stats() + if stats.BranchPageN != 13 { + t.Fatalf("unexpected BranchPageN: %d", stats.BranchPageN) + } else if stats.BranchOverflowN != 0 { + t.Fatalf("unexpected BranchOverflowN: %d", stats.BranchOverflowN) + } else if stats.LeafPageN != 1196 { + t.Fatalf("unexpected LeafPageN: %d", stats.LeafPageN) + } else if stats.LeafOverflowN != 0 { + t.Fatalf("unexpected LeafOverflowN: %d", stats.LeafOverflowN) + } else if stats.KeyN != 100000 { + t.Fatalf("unexpected KeyN: %d", stats.KeyN) + } else if stats.Depth != 3 { + t.Fatalf("unexpected Depth: %d", stats.Depth) + } else if stats.BranchInuse != 25257 { + t.Fatalf("unexpected BranchInuse: %d", stats.BranchInuse) + } else if stats.LeafInuse != 2596916 { + t.Fatalf("unexpected LeafInuse: %d", stats.LeafInuse) + } + + if os.Getpagesize() == 4096 { + if stats.BranchAlloc != 53248 { + t.Fatalf("unexpected BranchAlloc: %d", stats.BranchAlloc) + } else if stats.LeafAlloc != 4898816 { + t.Fatalf("unexpected LeafAlloc: %d", stats.LeafAlloc) + } + } + + if stats.BucketN != 1 { + t.Fatalf("unexpected BucketN: %d", stats.BucketN) + } else if stats.InlineBucketN != 0 { + t.Fatalf("unexpected InlineBucketN: %d", stats.InlineBucketN) + } else if stats.InlineBucketInuse != 0 { + t.Fatalf("unexpected InlineBucketInuse: %d", stats.InlineBucketInuse) + } + + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that a bucket can write random keys and values across multiple transactions. +func TestBucket_Put_Single(t *testing.T) { + if testing.Short() { + t.Skip("skipping test in short mode.") + } + + index := 0 + if err := quick.Check(func(items testdata) bool { + db := MustOpenDB() + defer db.MustClose() + + m := make(map[string][]byte) + + if err := db.Update(func(tx *bolt.Tx) error { + if _, err := tx.CreateBucket([]byte("widgets")); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + + for _, item := range items { + if err := db.Update(func(tx *bolt.Tx) error { + if err := tx.Bucket([]byte("widgets")).Put(item.Key, item.Value); err != nil { + panic("put error: " + err.Error()) + } + m[string(item.Key)] = item.Value + return nil + }); err != nil { + t.Fatal(err) + } + + // Verify all key/values so far. + if err := db.View(func(tx *bolt.Tx) error { + i := 0 + for k, v := range m { + value := tx.Bucket([]byte("widgets")).Get([]byte(k)) + if !bytes.Equal(value, v) { + t.Logf("value mismatch [run %d] (%d of %d):\nkey: %x\ngot: %x\nexp: %x", index, i, len(m), []byte(k), value, v) + db.CopyTempFile() + t.FailNow() + } + i++ + } + return nil + }); err != nil { + t.Fatal(err) + } + } + + index++ + return true + }, nil); err != nil { + t.Error(err) + } +} + +// Ensure that a transaction can insert multiple key/value pairs at once. +func TestBucket_Put_Multiple(t *testing.T) { + if testing.Short() { + t.Skip("skipping test in short mode.") + } + + if err := quick.Check(func(items testdata) bool { + db := MustOpenDB() + defer db.MustClose() + + // Bulk insert all values. + if err := db.Update(func(tx *bolt.Tx) error { + if _, err := tx.CreateBucket([]byte("widgets")); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + + if err := db.Update(func(tx *bolt.Tx) error { + b := tx.Bucket([]byte("widgets")) + for _, item := range items { + if err := b.Put(item.Key, item.Value); err != nil { + t.Fatal(err) + } + } + return nil + }); err != nil { + t.Fatal(err) + } + + // Verify all items exist. + if err := db.View(func(tx *bolt.Tx) error { + b := tx.Bucket([]byte("widgets")) + for _, item := range items { + value := b.Get(item.Key) + if !bytes.Equal(item.Value, value) { + db.CopyTempFile() + t.Fatalf("exp=%x; got=%x", item.Value, value) + } + } + return nil + }); err != nil { + t.Fatal(err) + } + + return true + }, qconfig()); err != nil { + t.Error(err) + } +} + +// Ensure that a transaction can delete all key/value pairs and return to a single leaf page. +func TestBucket_Delete_Quick(t *testing.T) { + if testing.Short() { + t.Skip("skipping test in short mode.") + } + + if err := quick.Check(func(items testdata) bool { + db := MustOpenDB() + defer db.MustClose() + + // Bulk insert all values. + if err := db.Update(func(tx *bolt.Tx) error { + if _, err := tx.CreateBucket([]byte("widgets")); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + + if err := db.Update(func(tx *bolt.Tx) error { + b := tx.Bucket([]byte("widgets")) + for _, item := range items { + if err := b.Put(item.Key, item.Value); err != nil { + t.Fatal(err) + } + } + return nil + }); err != nil { + t.Fatal(err) + } + + // Remove items one at a time and check consistency. + for _, item := range items { + if err := db.Update(func(tx *bolt.Tx) error { + return tx.Bucket([]byte("widgets")).Delete(item.Key) + }); err != nil { + t.Fatal(err) + } + } + + // Anything before our deletion index should be nil. + if err := db.View(func(tx *bolt.Tx) error { + if err := tx.Bucket([]byte("widgets")).ForEach(func(k, v []byte) error { + t.Fatalf("bucket should be empty; found: %06x", trunc(k, 3)) + return nil + }); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + + return true + }, qconfig()); err != nil { + t.Error(err) + } +} + +func ExampleBucket_Put() { + // Open the database. + db, err := bolt.Open(tempfile(), 0666, nil) + if err != nil { + log.Fatal(err) + } + defer os.Remove(db.Path()) + + // Start a write transaction. + if err := db.Update(func(tx *bolt.Tx) error { + // Create a bucket. + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + return err + } + + // Set the value "bar" for the key "foo". + if err := b.Put([]byte("foo"), []byte("bar")); err != nil { + return err + } + return nil + }); err != nil { + log.Fatal(err) + } + + // Read value back in a different read-only transaction. + if err := db.View(func(tx *bolt.Tx) error { + value := tx.Bucket([]byte("widgets")).Get([]byte("foo")) + fmt.Printf("The value of 'foo' is: %s\n", value) + return nil + }); err != nil { + log.Fatal(err) + } + + // Close database to release file lock. + if err := db.Close(); err != nil { + log.Fatal(err) + } + + // Output: + // The value of 'foo' is: bar +} + +func ExampleBucket_Delete() { + // Open the database. + db, err := bolt.Open(tempfile(), 0666, nil) + if err != nil { + log.Fatal(err) + } + defer os.Remove(db.Path()) + + // Start a write transaction. + if err := db.Update(func(tx *bolt.Tx) error { + // Create a bucket. + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + return err + } + + // Set the value "bar" for the key "foo". + if err := b.Put([]byte("foo"), []byte("bar")); err != nil { + return err + } + + // Retrieve the key back from the database and verify it. + value := b.Get([]byte("foo")) + fmt.Printf("The value of 'foo' was: %s\n", value) + + return nil + }); err != nil { + log.Fatal(err) + } + + // Delete the key in a different write transaction. + if err := db.Update(func(tx *bolt.Tx) error { + return tx.Bucket([]byte("widgets")).Delete([]byte("foo")) + }); err != nil { + log.Fatal(err) + } + + // Retrieve the key again. + if err := db.View(func(tx *bolt.Tx) error { + value := tx.Bucket([]byte("widgets")).Get([]byte("foo")) + if value == nil { + fmt.Printf("The value of 'foo' is now: nil\n") + } + return nil + }); err != nil { + log.Fatal(err) + } + + // Close database to release file lock. + if err := db.Close(); err != nil { + log.Fatal(err) + } + + // Output: + // The value of 'foo' was: bar + // The value of 'foo' is now: nil +} + +func ExampleBucket_ForEach() { + // Open the database. + db, err := bolt.Open(tempfile(), 0666, nil) + if err != nil { + log.Fatal(err) + } + defer os.Remove(db.Path()) + + // Insert data into a bucket. + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("animals")) + if err != nil { + return err + } + + if err := b.Put([]byte("dog"), []byte("fun")); err != nil { + return err + } + if err := b.Put([]byte("cat"), []byte("lame")); err != nil { + return err + } + if err := b.Put([]byte("liger"), []byte("awesome")); err != nil { + return err + } + + // Iterate over items in sorted key order. + if err := b.ForEach(func(k, v []byte) error { + fmt.Printf("A %s is %s.\n", k, v) + return nil + }); err != nil { + return err + } + + return nil + }); err != nil { + log.Fatal(err) + } + + // Close database to release file lock. + if err := db.Close(); err != nil { + log.Fatal(err) + } + + // Output: + // A cat is lame. + // A dog is fun. + // A liger is awesome. +} diff --git a/vendor/github.com/boltdb/bolt/cmd/bolt/main.go b/vendor/github.com/boltdb/bolt/cmd/bolt/main.go new file mode 100644 index 00000000..057eca50 --- /dev/null +++ b/vendor/github.com/boltdb/bolt/cmd/bolt/main.go @@ -0,0 +1,1740 @@ +package main + +import ( + "bytes" + "encoding/binary" + "errors" + "flag" + "fmt" + "io" + "io/ioutil" + "math/rand" + "os" + "runtime" + "runtime/pprof" + "strconv" + "strings" + "time" + "unicode" + "unicode/utf8" + "unsafe" + + "github.com/boltdb/bolt" +) + +var ( + // ErrUsage is returned when a usage message was printed and the process + // should simply exit with an error. + ErrUsage = errors.New("usage") + + // ErrUnknownCommand is returned when a CLI command is not specified. + ErrUnknownCommand = errors.New("unknown command") + + // ErrPathRequired is returned when the path to a Bolt database is not specified. + ErrPathRequired = errors.New("path required") + + // ErrFileNotFound is returned when a Bolt database does not exist. + ErrFileNotFound = errors.New("file not found") + + // ErrInvalidValue is returned when a benchmark reads an unexpected value. + ErrInvalidValue = errors.New("invalid value") + + // ErrCorrupt is returned when a checking a data file finds errors. + ErrCorrupt = errors.New("invalid value") + + // ErrNonDivisibleBatchSize is returned when the batch size can't be evenly + // divided by the iteration count. + ErrNonDivisibleBatchSize = errors.New("number of iterations must be divisible by the batch size") + + // ErrPageIDRequired is returned when a required page id is not specified. + ErrPageIDRequired = errors.New("page id required") + + // ErrPageNotFound is returned when specifying a page above the high water mark. + ErrPageNotFound = errors.New("page not found") + + // ErrPageFreed is returned when reading a page that has already been freed. + ErrPageFreed = errors.New("page freed") +) + +// PageHeaderSize represents the size of the bolt.page header. +const PageHeaderSize = 16 + +func main() { + m := NewMain() + if err := m.Run(os.Args[1:]...); err == ErrUsage { + os.Exit(2) + } else if err != nil { + fmt.Println(err.Error()) + os.Exit(1) + } +} + +// Main represents the main program execution. +type Main struct { + Stdin io.Reader + Stdout io.Writer + Stderr io.Writer +} + +// NewMain returns a new instance of Main connect to the standard input/output. +func NewMain() *Main { + return &Main{ + Stdin: os.Stdin, + Stdout: os.Stdout, + Stderr: os.Stderr, + } +} + +// Run executes the program. +func (m *Main) Run(args ...string) error { + // Require a command at the beginning. + if len(args) == 0 || strings.HasPrefix(args[0], "-") { + fmt.Fprintln(m.Stderr, m.Usage()) + return ErrUsage + } + + // Execute command. + switch args[0] { + case "help": + fmt.Fprintln(m.Stderr, m.Usage()) + return ErrUsage + case "bench": + return newBenchCommand(m).Run(args[1:]...) + case "check": + return newCheckCommand(m).Run(args[1:]...) + case "compact": + return newCompactCommand(m).Run(args[1:]...) + case "dump": + return newDumpCommand(m).Run(args[1:]...) + case "info": + return newInfoCommand(m).Run(args[1:]...) + case "page": + return newPageCommand(m).Run(args[1:]...) + case "pages": + return newPagesCommand(m).Run(args[1:]...) + case "stats": + return newStatsCommand(m).Run(args[1:]...) + default: + return ErrUnknownCommand + } +} + +// Usage returns the help message. +func (m *Main) Usage() string { + return strings.TrimLeft(` +Bolt is a tool for inspecting bolt databases. + +Usage: + + bolt command [arguments] + +The commands are: + + bench run synthetic benchmark against bolt + check verifies integrity of bolt database + compact copies a bolt database, compacting it in the process + info print basic info + help print this screen + pages print list of pages with their types + stats iterate over all pages and generate usage stats + +Use "bolt [command] -h" for more information about a command. +`, "\n") +} + +// CheckCommand represents the "check" command execution. +type CheckCommand struct { + Stdin io.Reader + Stdout io.Writer + Stderr io.Writer +} + +// NewCheckCommand returns a CheckCommand. +func newCheckCommand(m *Main) *CheckCommand { + return &CheckCommand{ + Stdin: m.Stdin, + Stdout: m.Stdout, + Stderr: m.Stderr, + } +} + +// Run executes the command. +func (cmd *CheckCommand) Run(args ...string) error { + // Parse flags. + fs := flag.NewFlagSet("", flag.ContinueOnError) + help := fs.Bool("h", false, "") + if err := fs.Parse(args); err != nil { + return err + } else if *help { + fmt.Fprintln(cmd.Stderr, cmd.Usage()) + return ErrUsage + } + + // Require database path. + path := fs.Arg(0) + if path == "" { + return ErrPathRequired + } else if _, err := os.Stat(path); os.IsNotExist(err) { + return ErrFileNotFound + } + + // Open database. + db, err := bolt.Open(path, 0666, nil) + if err != nil { + return err + } + defer db.Close() + + // Perform consistency check. + return db.View(func(tx *bolt.Tx) error { + var count int + ch := tx.Check() + loop: + for { + select { + case err, ok := <-ch: + if !ok { + break loop + } + fmt.Fprintln(cmd.Stdout, err) + count++ + } + } + + // Print summary of errors. + if count > 0 { + fmt.Fprintf(cmd.Stdout, "%d errors found\n", count) + return ErrCorrupt + } + + // Notify user that database is valid. + fmt.Fprintln(cmd.Stdout, "OK") + return nil + }) +} + +// Usage returns the help message. +func (cmd *CheckCommand) Usage() string { + return strings.TrimLeft(` +usage: bolt check PATH + +Check opens a database at PATH and runs an exhaustive check to verify that +all pages are accessible or are marked as freed. It also verifies that no +pages are double referenced. + +Verification errors will stream out as they are found and the process will +return after all pages have been checked. +`, "\n") +} + +// InfoCommand represents the "info" command execution. +type InfoCommand struct { + Stdin io.Reader + Stdout io.Writer + Stderr io.Writer +} + +// NewInfoCommand returns a InfoCommand. +func newInfoCommand(m *Main) *InfoCommand { + return &InfoCommand{ + Stdin: m.Stdin, + Stdout: m.Stdout, + Stderr: m.Stderr, + } +} + +// Run executes the command. +func (cmd *InfoCommand) Run(args ...string) error { + // Parse flags. + fs := flag.NewFlagSet("", flag.ContinueOnError) + help := fs.Bool("h", false, "") + if err := fs.Parse(args); err != nil { + return err + } else if *help { + fmt.Fprintln(cmd.Stderr, cmd.Usage()) + return ErrUsage + } + + // Require database path. + path := fs.Arg(0) + if path == "" { + return ErrPathRequired + } else if _, err := os.Stat(path); os.IsNotExist(err) { + return ErrFileNotFound + } + + // Open the database. + db, err := bolt.Open(path, 0666, nil) + if err != nil { + return err + } + defer db.Close() + + // Print basic database info. + info := db.Info() + fmt.Fprintf(cmd.Stdout, "Page Size: %d\n", info.PageSize) + + return nil +} + +// Usage returns the help message. +func (cmd *InfoCommand) Usage() string { + return strings.TrimLeft(` +usage: bolt info PATH + +Info prints basic information about the Bolt database at PATH. +`, "\n") +} + +// DumpCommand represents the "dump" command execution. +type DumpCommand struct { + Stdin io.Reader + Stdout io.Writer + Stderr io.Writer +} + +// newDumpCommand returns a DumpCommand. +func newDumpCommand(m *Main) *DumpCommand { + return &DumpCommand{ + Stdin: m.Stdin, + Stdout: m.Stdout, + Stderr: m.Stderr, + } +} + +// Run executes the command. +func (cmd *DumpCommand) Run(args ...string) error { + // Parse flags. + fs := flag.NewFlagSet("", flag.ContinueOnError) + help := fs.Bool("h", false, "") + if err := fs.Parse(args); err != nil { + return err + } else if *help { + fmt.Fprintln(cmd.Stderr, cmd.Usage()) + return ErrUsage + } + + // Require database path and page id. + path := fs.Arg(0) + if path == "" { + return ErrPathRequired + } else if _, err := os.Stat(path); os.IsNotExist(err) { + return ErrFileNotFound + } + + // Read page ids. + pageIDs, err := atois(fs.Args()[1:]) + if err != nil { + return err + } else if len(pageIDs) == 0 { + return ErrPageIDRequired + } + + // Open database to retrieve page size. + pageSize, err := ReadPageSize(path) + if err != nil { + return err + } + + // Open database file handler. + f, err := os.Open(path) + if err != nil { + return err + } + defer func() { _ = f.Close() }() + + // Print each page listed. + for i, pageID := range pageIDs { + // Print a separator. + if i > 0 { + fmt.Fprintln(cmd.Stdout, "===============================================") + } + + // Print page to stdout. + if err := cmd.PrintPage(cmd.Stdout, f, pageID, pageSize); err != nil { + return err + } + } + + return nil +} + +// PrintPage prints a given page as hexadecimal. +func (cmd *DumpCommand) PrintPage(w io.Writer, r io.ReaderAt, pageID int, pageSize int) error { + const bytesPerLineN = 16 + + // Read page into buffer. + buf := make([]byte, pageSize) + addr := pageID * pageSize + if n, err := r.ReadAt(buf, int64(addr)); err != nil { + return err + } else if n != pageSize { + return io.ErrUnexpectedEOF + } + + // Write out to writer in 16-byte lines. + var prev []byte + var skipped bool + for offset := 0; offset < pageSize; offset += bytesPerLineN { + // Retrieve current 16-byte line. + line := buf[offset : offset+bytesPerLineN] + isLastLine := (offset == (pageSize - bytesPerLineN)) + + // If it's the same as the previous line then print a skip. + if bytes.Equal(line, prev) && !isLastLine { + if !skipped { + fmt.Fprintf(w, "%07x *\n", addr+offset) + skipped = true + } + } else { + // Print line as hexadecimal in 2-byte groups. + fmt.Fprintf(w, "%07x %04x %04x %04x %04x %04x %04x %04x %04x\n", addr+offset, + line[0:2], line[2:4], line[4:6], line[6:8], + line[8:10], line[10:12], line[12:14], line[14:16], + ) + + skipped = false + } + + // Save the previous line. + prev = line + } + fmt.Fprint(w, "\n") + + return nil +} + +// Usage returns the help message. +func (cmd *DumpCommand) Usage() string { + return strings.TrimLeft(` +usage: bolt dump -page PAGEID PATH + +Dump prints a hexadecimal dump of a single page. +`, "\n") +} + +// PageCommand represents the "page" command execution. +type PageCommand struct { + Stdin io.Reader + Stdout io.Writer + Stderr io.Writer +} + +// newPageCommand returns a PageCommand. +func newPageCommand(m *Main) *PageCommand { + return &PageCommand{ + Stdin: m.Stdin, + Stdout: m.Stdout, + Stderr: m.Stderr, + } +} + +// Run executes the command. +func (cmd *PageCommand) Run(args ...string) error { + // Parse flags. + fs := flag.NewFlagSet("", flag.ContinueOnError) + help := fs.Bool("h", false, "") + if err := fs.Parse(args); err != nil { + return err + } else if *help { + fmt.Fprintln(cmd.Stderr, cmd.Usage()) + return ErrUsage + } + + // Require database path and page id. + path := fs.Arg(0) + if path == "" { + return ErrPathRequired + } else if _, err := os.Stat(path); os.IsNotExist(err) { + return ErrFileNotFound + } + + // Read page ids. + pageIDs, err := atois(fs.Args()[1:]) + if err != nil { + return err + } else if len(pageIDs) == 0 { + return ErrPageIDRequired + } + + // Open database file handler. + f, err := os.Open(path) + if err != nil { + return err + } + defer func() { _ = f.Close() }() + + // Print each page listed. + for i, pageID := range pageIDs { + // Print a separator. + if i > 0 { + fmt.Fprintln(cmd.Stdout, "===============================================") + } + + // Retrieve page info and page size. + p, buf, err := ReadPage(path, pageID) + if err != nil { + return err + } + + // Print basic page info. + fmt.Fprintf(cmd.Stdout, "Page ID: %d\n", p.id) + fmt.Fprintf(cmd.Stdout, "Page Type: %s\n", p.Type()) + fmt.Fprintf(cmd.Stdout, "Total Size: %d bytes\n", len(buf)) + + // Print type-specific data. + switch p.Type() { + case "meta": + err = cmd.PrintMeta(cmd.Stdout, buf) + case "leaf": + err = cmd.PrintLeaf(cmd.Stdout, buf) + case "branch": + err = cmd.PrintBranch(cmd.Stdout, buf) + case "freelist": + err = cmd.PrintFreelist(cmd.Stdout, buf) + } + if err != nil { + return err + } + } + + return nil +} + +// PrintMeta prints the data from the meta page. +func (cmd *PageCommand) PrintMeta(w io.Writer, buf []byte) error { + m := (*meta)(unsafe.Pointer(&buf[PageHeaderSize])) + fmt.Fprintf(w, "Version: %d\n", m.version) + fmt.Fprintf(w, "Page Size: %d bytes\n", m.pageSize) + fmt.Fprintf(w, "Flags: %08x\n", m.flags) + fmt.Fprintf(w, "Root: \n", m.root.root) + fmt.Fprintf(w, "Freelist: \n", m.freelist) + fmt.Fprintf(w, "HWM: \n", m.pgid) + fmt.Fprintf(w, "Txn ID: %d\n", m.txid) + fmt.Fprintf(w, "Checksum: %016x\n", m.checksum) + fmt.Fprintf(w, "\n") + return nil +} + +// PrintLeaf prints the data for a leaf page. +func (cmd *PageCommand) PrintLeaf(w io.Writer, buf []byte) error { + p := (*page)(unsafe.Pointer(&buf[0])) + + // Print number of items. + fmt.Fprintf(w, "Item Count: %d\n", p.count) + fmt.Fprintf(w, "\n") + + // Print each key/value. + for i := uint16(0); i < p.count; i++ { + e := p.leafPageElement(i) + + // Format key as string. + var k string + if isPrintable(string(e.key())) { + k = fmt.Sprintf("%q", string(e.key())) + } else { + k = fmt.Sprintf("%x", string(e.key())) + } + + // Format value as string. + var v string + if (e.flags & uint32(bucketLeafFlag)) != 0 { + b := (*bucket)(unsafe.Pointer(&e.value()[0])) + v = fmt.Sprintf("", b.root, b.sequence) + } else if isPrintable(string(e.value())) { + v = fmt.Sprintf("%q", string(e.value())) + } else { + v = fmt.Sprintf("%x", string(e.value())) + } + + fmt.Fprintf(w, "%s: %s\n", k, v) + } + fmt.Fprintf(w, "\n") + return nil +} + +// PrintBranch prints the data for a leaf page. +func (cmd *PageCommand) PrintBranch(w io.Writer, buf []byte) error { + p := (*page)(unsafe.Pointer(&buf[0])) + + // Print number of items. + fmt.Fprintf(w, "Item Count: %d\n", p.count) + fmt.Fprintf(w, "\n") + + // Print each key/value. + for i := uint16(0); i < p.count; i++ { + e := p.branchPageElement(i) + + // Format key as string. + var k string + if isPrintable(string(e.key())) { + k = fmt.Sprintf("%q", string(e.key())) + } else { + k = fmt.Sprintf("%x", string(e.key())) + } + + fmt.Fprintf(w, "%s: \n", k, e.pgid) + } + fmt.Fprintf(w, "\n") + return nil +} + +// PrintFreelist prints the data for a freelist page. +func (cmd *PageCommand) PrintFreelist(w io.Writer, buf []byte) error { + p := (*page)(unsafe.Pointer(&buf[0])) + + // Print number of items. + fmt.Fprintf(w, "Item Count: %d\n", p.count) + fmt.Fprintf(w, "\n") + + // Print each page in the freelist. + ids := (*[maxAllocSize]pgid)(unsafe.Pointer(&p.ptr)) + for i := uint16(0); i < p.count; i++ { + fmt.Fprintf(w, "%d\n", ids[i]) + } + fmt.Fprintf(w, "\n") + return nil +} + +// PrintPage prints a given page as hexadecimal. +func (cmd *PageCommand) PrintPage(w io.Writer, r io.ReaderAt, pageID int, pageSize int) error { + const bytesPerLineN = 16 + + // Read page into buffer. + buf := make([]byte, pageSize) + addr := pageID * pageSize + if n, err := r.ReadAt(buf, int64(addr)); err != nil { + return err + } else if n != pageSize { + return io.ErrUnexpectedEOF + } + + // Write out to writer in 16-byte lines. + var prev []byte + var skipped bool + for offset := 0; offset < pageSize; offset += bytesPerLineN { + // Retrieve current 16-byte line. + line := buf[offset : offset+bytesPerLineN] + isLastLine := (offset == (pageSize - bytesPerLineN)) + + // If it's the same as the previous line then print a skip. + if bytes.Equal(line, prev) && !isLastLine { + if !skipped { + fmt.Fprintf(w, "%07x *\n", addr+offset) + skipped = true + } + } else { + // Print line as hexadecimal in 2-byte groups. + fmt.Fprintf(w, "%07x %04x %04x %04x %04x %04x %04x %04x %04x\n", addr+offset, + line[0:2], line[2:4], line[4:6], line[6:8], + line[8:10], line[10:12], line[12:14], line[14:16], + ) + + skipped = false + } + + // Save the previous line. + prev = line + } + fmt.Fprint(w, "\n") + + return nil +} + +// Usage returns the help message. +func (cmd *PageCommand) Usage() string { + return strings.TrimLeft(` +usage: bolt page -page PATH pageid [pageid...] + +Page prints one or more pages in human readable format. +`, "\n") +} + +// PagesCommand represents the "pages" command execution. +type PagesCommand struct { + Stdin io.Reader + Stdout io.Writer + Stderr io.Writer +} + +// NewPagesCommand returns a PagesCommand. +func newPagesCommand(m *Main) *PagesCommand { + return &PagesCommand{ + Stdin: m.Stdin, + Stdout: m.Stdout, + Stderr: m.Stderr, + } +} + +// Run executes the command. +func (cmd *PagesCommand) Run(args ...string) error { + // Parse flags. + fs := flag.NewFlagSet("", flag.ContinueOnError) + help := fs.Bool("h", false, "") + if err := fs.Parse(args); err != nil { + return err + } else if *help { + fmt.Fprintln(cmd.Stderr, cmd.Usage()) + return ErrUsage + } + + // Require database path. + path := fs.Arg(0) + if path == "" { + return ErrPathRequired + } else if _, err := os.Stat(path); os.IsNotExist(err) { + return ErrFileNotFound + } + + // Open database. + db, err := bolt.Open(path, 0666, nil) + if err != nil { + return err + } + defer func() { _ = db.Close() }() + + // Write header. + fmt.Fprintln(cmd.Stdout, "ID TYPE ITEMS OVRFLW") + fmt.Fprintln(cmd.Stdout, "======== ========== ====== ======") + + return db.Update(func(tx *bolt.Tx) error { + var id int + for { + p, err := tx.Page(id) + if err != nil { + return &PageError{ID: id, Err: err} + } else if p == nil { + break + } + + // Only display count and overflow if this is a non-free page. + var count, overflow string + if p.Type != "free" { + count = strconv.Itoa(p.Count) + if p.OverflowCount > 0 { + overflow = strconv.Itoa(p.OverflowCount) + } + } + + // Print table row. + fmt.Fprintf(cmd.Stdout, "%-8d %-10s %-6s %-6s\n", p.ID, p.Type, count, overflow) + + // Move to the next non-overflow page. + id += 1 + if p.Type != "free" { + id += p.OverflowCount + } + } + return nil + }) +} + +// Usage returns the help message. +func (cmd *PagesCommand) Usage() string { + return strings.TrimLeft(` +usage: bolt pages PATH + +Pages prints a table of pages with their type (meta, leaf, branch, freelist). +Leaf and branch pages will show a key count in the "items" column while the +freelist will show the number of free pages in the "items" column. + +The "overflow" column shows the number of blocks that the page spills over +into. Normally there is no overflow but large keys and values can cause +a single page to take up multiple blocks. +`, "\n") +} + +// StatsCommand represents the "stats" command execution. +type StatsCommand struct { + Stdin io.Reader + Stdout io.Writer + Stderr io.Writer +} + +// NewStatsCommand returns a StatsCommand. +func newStatsCommand(m *Main) *StatsCommand { + return &StatsCommand{ + Stdin: m.Stdin, + Stdout: m.Stdout, + Stderr: m.Stderr, + } +} + +// Run executes the command. +func (cmd *StatsCommand) Run(args ...string) error { + // Parse flags. + fs := flag.NewFlagSet("", flag.ContinueOnError) + help := fs.Bool("h", false, "") + if err := fs.Parse(args); err != nil { + return err + } else if *help { + fmt.Fprintln(cmd.Stderr, cmd.Usage()) + return ErrUsage + } + + // Require database path. + path, prefix := fs.Arg(0), fs.Arg(1) + if path == "" { + return ErrPathRequired + } else if _, err := os.Stat(path); os.IsNotExist(err) { + return ErrFileNotFound + } + + // Open database. + db, err := bolt.Open(path, 0666, nil) + if err != nil { + return err + } + defer db.Close() + + return db.View(func(tx *bolt.Tx) error { + var s bolt.BucketStats + var count int + if err := tx.ForEach(func(name []byte, b *bolt.Bucket) error { + if bytes.HasPrefix(name, []byte(prefix)) { + s.Add(b.Stats()) + count += 1 + } + return nil + }); err != nil { + return err + } + + fmt.Fprintf(cmd.Stdout, "Aggregate statistics for %d buckets\n\n", count) + + fmt.Fprintln(cmd.Stdout, "Page count statistics") + fmt.Fprintf(cmd.Stdout, "\tNumber of logical branch pages: %d\n", s.BranchPageN) + fmt.Fprintf(cmd.Stdout, "\tNumber of physical branch overflow pages: %d\n", s.BranchOverflowN) + fmt.Fprintf(cmd.Stdout, "\tNumber of logical leaf pages: %d\n", s.LeafPageN) + fmt.Fprintf(cmd.Stdout, "\tNumber of physical leaf overflow pages: %d\n", s.LeafOverflowN) + + fmt.Fprintln(cmd.Stdout, "Tree statistics") + fmt.Fprintf(cmd.Stdout, "\tNumber of keys/value pairs: %d\n", s.KeyN) + fmt.Fprintf(cmd.Stdout, "\tNumber of levels in B+tree: %d\n", s.Depth) + + fmt.Fprintln(cmd.Stdout, "Page size utilization") + fmt.Fprintf(cmd.Stdout, "\tBytes allocated for physical branch pages: %d\n", s.BranchAlloc) + var percentage int + if s.BranchAlloc != 0 { + percentage = int(float32(s.BranchInuse) * 100.0 / float32(s.BranchAlloc)) + } + fmt.Fprintf(cmd.Stdout, "\tBytes actually used for branch data: %d (%d%%)\n", s.BranchInuse, percentage) + fmt.Fprintf(cmd.Stdout, "\tBytes allocated for physical leaf pages: %d\n", s.LeafAlloc) + percentage = 0 + if s.LeafAlloc != 0 { + percentage = int(float32(s.LeafInuse) * 100.0 / float32(s.LeafAlloc)) + } + fmt.Fprintf(cmd.Stdout, "\tBytes actually used for leaf data: %d (%d%%)\n", s.LeafInuse, percentage) + + fmt.Fprintln(cmd.Stdout, "Bucket statistics") + fmt.Fprintf(cmd.Stdout, "\tTotal number of buckets: %d\n", s.BucketN) + percentage = 0 + if s.BucketN != 0 { + percentage = int(float32(s.InlineBucketN) * 100.0 / float32(s.BucketN)) + } + fmt.Fprintf(cmd.Stdout, "\tTotal number on inlined buckets: %d (%d%%)\n", s.InlineBucketN, percentage) + percentage = 0 + if s.LeafInuse != 0 { + percentage = int(float32(s.InlineBucketInuse) * 100.0 / float32(s.LeafInuse)) + } + fmt.Fprintf(cmd.Stdout, "\tBytes used for inlined buckets: %d (%d%%)\n", s.InlineBucketInuse, percentage) + + return nil + }) +} + +// Usage returns the help message. +func (cmd *StatsCommand) Usage() string { + return strings.TrimLeft(` +usage: bolt stats PATH + +Stats performs an extensive search of the database to track every page +reference. It starts at the current meta page and recursively iterates +through every accessible bucket. + +The following errors can be reported: + + already freed + The page is referenced more than once in the freelist. + + unreachable unfreed + The page is not referenced by a bucket or in the freelist. + + reachable freed + The page is referenced by a bucket but is also in the freelist. + + out of bounds + A page is referenced that is above the high water mark. + + multiple references + A page is referenced by more than one other page. + + invalid type + The page type is not "meta", "leaf", "branch", or "freelist". + +No errors should occur in your database. However, if for some reason you +experience corruption, please submit a ticket to the Bolt project page: + + https://github.com/boltdb/bolt/issues +`, "\n") +} + +var benchBucketName = []byte("bench") + +// BenchCommand represents the "bench" command execution. +type BenchCommand struct { + Stdin io.Reader + Stdout io.Writer + Stderr io.Writer +} + +// NewBenchCommand returns a BenchCommand using the +func newBenchCommand(m *Main) *BenchCommand { + return &BenchCommand{ + Stdin: m.Stdin, + Stdout: m.Stdout, + Stderr: m.Stderr, + } +} + +// Run executes the "bench" command. +func (cmd *BenchCommand) Run(args ...string) error { + // Parse CLI arguments. + options, err := cmd.ParseFlags(args) + if err != nil { + return err + } + + // Remove path if "-work" is not set. Otherwise keep path. + if options.Work { + fmt.Fprintf(cmd.Stdout, "work: %s\n", options.Path) + } else { + defer os.Remove(options.Path) + } + + // Create database. + db, err := bolt.Open(options.Path, 0666, nil) + if err != nil { + return err + } + db.NoSync = options.NoSync + defer db.Close() + + // Write to the database. + var results BenchResults + if err := cmd.runWrites(db, options, &results); err != nil { + return fmt.Errorf("write: %v", err) + } + + // Read from the database. + if err := cmd.runReads(db, options, &results); err != nil { + return fmt.Errorf("bench: read: %s", err) + } + + // Print results. + fmt.Fprintf(os.Stderr, "# Write\t%v\t(%v/op)\t(%v op/sec)\n", results.WriteDuration, results.WriteOpDuration(), results.WriteOpsPerSecond()) + fmt.Fprintf(os.Stderr, "# Read\t%v\t(%v/op)\t(%v op/sec)\n", results.ReadDuration, results.ReadOpDuration(), results.ReadOpsPerSecond()) + fmt.Fprintln(os.Stderr, "") + return nil +} + +// ParseFlags parses the command line flags. +func (cmd *BenchCommand) ParseFlags(args []string) (*BenchOptions, error) { + var options BenchOptions + + // Parse flagset. + fs := flag.NewFlagSet("", flag.ContinueOnError) + fs.StringVar(&options.ProfileMode, "profile-mode", "rw", "") + fs.StringVar(&options.WriteMode, "write-mode", "seq", "") + fs.StringVar(&options.ReadMode, "read-mode", "seq", "") + fs.IntVar(&options.Iterations, "count", 1000, "") + fs.IntVar(&options.BatchSize, "batch-size", 0, "") + fs.IntVar(&options.KeySize, "key-size", 8, "") + fs.IntVar(&options.ValueSize, "value-size", 32, "") + fs.StringVar(&options.CPUProfile, "cpuprofile", "", "") + fs.StringVar(&options.MemProfile, "memprofile", "", "") + fs.StringVar(&options.BlockProfile, "blockprofile", "", "") + fs.Float64Var(&options.FillPercent, "fill-percent", bolt.DefaultFillPercent, "") + fs.BoolVar(&options.NoSync, "no-sync", false, "") + fs.BoolVar(&options.Work, "work", false, "") + fs.StringVar(&options.Path, "path", "", "") + fs.SetOutput(cmd.Stderr) + if err := fs.Parse(args); err != nil { + return nil, err + } + + // Set batch size to iteration size if not set. + // Require that batch size can be evenly divided by the iteration count. + if options.BatchSize == 0 { + options.BatchSize = options.Iterations + } else if options.Iterations%options.BatchSize != 0 { + return nil, ErrNonDivisibleBatchSize + } + + // Generate temp path if one is not passed in. + if options.Path == "" { + f, err := ioutil.TempFile("", "bolt-bench-") + if err != nil { + return nil, fmt.Errorf("temp file: %s", err) + } + f.Close() + os.Remove(f.Name()) + options.Path = f.Name() + } + + return &options, nil +} + +// Writes to the database. +func (cmd *BenchCommand) runWrites(db *bolt.DB, options *BenchOptions, results *BenchResults) error { + // Start profiling for writes. + if options.ProfileMode == "rw" || options.ProfileMode == "w" { + cmd.startProfiling(options) + } + + t := time.Now() + + var err error + switch options.WriteMode { + case "seq": + err = cmd.runWritesSequential(db, options, results) + case "rnd": + err = cmd.runWritesRandom(db, options, results) + case "seq-nest": + err = cmd.runWritesSequentialNested(db, options, results) + case "rnd-nest": + err = cmd.runWritesRandomNested(db, options, results) + default: + return fmt.Errorf("invalid write mode: %s", options.WriteMode) + } + + // Save time to write. + results.WriteDuration = time.Since(t) + + // Stop profiling for writes only. + if options.ProfileMode == "w" { + cmd.stopProfiling() + } + + return err +} + +func (cmd *BenchCommand) runWritesSequential(db *bolt.DB, options *BenchOptions, results *BenchResults) error { + var i = uint32(0) + return cmd.runWritesWithSource(db, options, results, func() uint32 { i++; return i }) +} + +func (cmd *BenchCommand) runWritesRandom(db *bolt.DB, options *BenchOptions, results *BenchResults) error { + r := rand.New(rand.NewSource(time.Now().UnixNano())) + return cmd.runWritesWithSource(db, options, results, func() uint32 { return r.Uint32() }) +} + +func (cmd *BenchCommand) runWritesSequentialNested(db *bolt.DB, options *BenchOptions, results *BenchResults) error { + var i = uint32(0) + return cmd.runWritesWithSource(db, options, results, func() uint32 { i++; return i }) +} + +func (cmd *BenchCommand) runWritesRandomNested(db *bolt.DB, options *BenchOptions, results *BenchResults) error { + r := rand.New(rand.NewSource(time.Now().UnixNano())) + return cmd.runWritesWithSource(db, options, results, func() uint32 { return r.Uint32() }) +} + +func (cmd *BenchCommand) runWritesWithSource(db *bolt.DB, options *BenchOptions, results *BenchResults, keySource func() uint32) error { + results.WriteOps = options.Iterations + + for i := 0; i < options.Iterations; i += options.BatchSize { + if err := db.Update(func(tx *bolt.Tx) error { + b, _ := tx.CreateBucketIfNotExists(benchBucketName) + b.FillPercent = options.FillPercent + + for j := 0; j < options.BatchSize; j++ { + key := make([]byte, options.KeySize) + value := make([]byte, options.ValueSize) + + // Write key as uint32. + binary.BigEndian.PutUint32(key, keySource()) + + // Insert key/value. + if err := b.Put(key, value); err != nil { + return err + } + } + + return nil + }); err != nil { + return err + } + } + return nil +} + +func (cmd *BenchCommand) runWritesNestedWithSource(db *bolt.DB, options *BenchOptions, results *BenchResults, keySource func() uint32) error { + results.WriteOps = options.Iterations + + for i := 0; i < options.Iterations; i += options.BatchSize { + if err := db.Update(func(tx *bolt.Tx) error { + top, err := tx.CreateBucketIfNotExists(benchBucketName) + if err != nil { + return err + } + top.FillPercent = options.FillPercent + + // Create bucket key. + name := make([]byte, options.KeySize) + binary.BigEndian.PutUint32(name, keySource()) + + // Create bucket. + b, err := top.CreateBucketIfNotExists(name) + if err != nil { + return err + } + b.FillPercent = options.FillPercent + + for j := 0; j < options.BatchSize; j++ { + var key = make([]byte, options.KeySize) + var value = make([]byte, options.ValueSize) + + // Generate key as uint32. + binary.BigEndian.PutUint32(key, keySource()) + + // Insert value into subbucket. + if err := b.Put(key, value); err != nil { + return err + } + } + + return nil + }); err != nil { + return err + } + } + return nil +} + +// Reads from the database. +func (cmd *BenchCommand) runReads(db *bolt.DB, options *BenchOptions, results *BenchResults) error { + // Start profiling for reads. + if options.ProfileMode == "r" { + cmd.startProfiling(options) + } + + t := time.Now() + + var err error + switch options.ReadMode { + case "seq": + switch options.WriteMode { + case "seq-nest", "rnd-nest": + err = cmd.runReadsSequentialNested(db, options, results) + default: + err = cmd.runReadsSequential(db, options, results) + } + default: + return fmt.Errorf("invalid read mode: %s", options.ReadMode) + } + + // Save read time. + results.ReadDuration = time.Since(t) + + // Stop profiling for reads. + if options.ProfileMode == "rw" || options.ProfileMode == "r" { + cmd.stopProfiling() + } + + return err +} + +func (cmd *BenchCommand) runReadsSequential(db *bolt.DB, options *BenchOptions, results *BenchResults) error { + return db.View(func(tx *bolt.Tx) error { + t := time.Now() + + for { + var count int + + c := tx.Bucket(benchBucketName).Cursor() + for k, v := c.First(); k != nil; k, v = c.Next() { + if v == nil { + return errors.New("invalid value") + } + count++ + } + + if options.WriteMode == "seq" && count != options.Iterations { + return fmt.Errorf("read seq: iter mismatch: expected %d, got %d", options.Iterations, count) + } + + results.ReadOps += count + + // Make sure we do this for at least a second. + if time.Since(t) >= time.Second { + break + } + } + + return nil + }) +} + +func (cmd *BenchCommand) runReadsSequentialNested(db *bolt.DB, options *BenchOptions, results *BenchResults) error { + return db.View(func(tx *bolt.Tx) error { + t := time.Now() + + for { + var count int + var top = tx.Bucket(benchBucketName) + if err := top.ForEach(func(name, _ []byte) error { + c := top.Bucket(name).Cursor() + for k, v := c.First(); k != nil; k, v = c.Next() { + if v == nil { + return ErrInvalidValue + } + count++ + } + return nil + }); err != nil { + return err + } + + if options.WriteMode == "seq-nest" && count != options.Iterations { + return fmt.Errorf("read seq-nest: iter mismatch: expected %d, got %d", options.Iterations, count) + } + + results.ReadOps += count + + // Make sure we do this for at least a second. + if time.Since(t) >= time.Second { + break + } + } + + return nil + }) +} + +// File handlers for the various profiles. +var cpuprofile, memprofile, blockprofile *os.File + +// Starts all profiles set on the options. +func (cmd *BenchCommand) startProfiling(options *BenchOptions) { + var err error + + // Start CPU profiling. + if options.CPUProfile != "" { + cpuprofile, err = os.Create(options.CPUProfile) + if err != nil { + fmt.Fprintf(cmd.Stderr, "bench: could not create cpu profile %q: %v\n", options.CPUProfile, err) + os.Exit(1) + } + pprof.StartCPUProfile(cpuprofile) + } + + // Start memory profiling. + if options.MemProfile != "" { + memprofile, err = os.Create(options.MemProfile) + if err != nil { + fmt.Fprintf(cmd.Stderr, "bench: could not create memory profile %q: %v\n", options.MemProfile, err) + os.Exit(1) + } + runtime.MemProfileRate = 4096 + } + + // Start fatal profiling. + if options.BlockProfile != "" { + blockprofile, err = os.Create(options.BlockProfile) + if err != nil { + fmt.Fprintf(cmd.Stderr, "bench: could not create block profile %q: %v\n", options.BlockProfile, err) + os.Exit(1) + } + runtime.SetBlockProfileRate(1) + } +} + +// Stops all profiles. +func (cmd *BenchCommand) stopProfiling() { + if cpuprofile != nil { + pprof.StopCPUProfile() + cpuprofile.Close() + cpuprofile = nil + } + + if memprofile != nil { + pprof.Lookup("heap").WriteTo(memprofile, 0) + memprofile.Close() + memprofile = nil + } + + if blockprofile != nil { + pprof.Lookup("block").WriteTo(blockprofile, 0) + blockprofile.Close() + blockprofile = nil + runtime.SetBlockProfileRate(0) + } +} + +// BenchOptions represents the set of options that can be passed to "bolt bench". +type BenchOptions struct { + ProfileMode string + WriteMode string + ReadMode string + Iterations int + BatchSize int + KeySize int + ValueSize int + CPUProfile string + MemProfile string + BlockProfile string + StatsInterval time.Duration + FillPercent float64 + NoSync bool + Work bool + Path string +} + +// BenchResults represents the performance results of the benchmark. +type BenchResults struct { + WriteOps int + WriteDuration time.Duration + ReadOps int + ReadDuration time.Duration +} + +// Returns the duration for a single write operation. +func (r *BenchResults) WriteOpDuration() time.Duration { + if r.WriteOps == 0 { + return 0 + } + return r.WriteDuration / time.Duration(r.WriteOps) +} + +// Returns average number of write operations that can be performed per second. +func (r *BenchResults) WriteOpsPerSecond() int { + var op = r.WriteOpDuration() + if op == 0 { + return 0 + } + return int(time.Second) / int(op) +} + +// Returns the duration for a single read operation. +func (r *BenchResults) ReadOpDuration() time.Duration { + if r.ReadOps == 0 { + return 0 + } + return r.ReadDuration / time.Duration(r.ReadOps) +} + +// Returns average number of read operations that can be performed per second. +func (r *BenchResults) ReadOpsPerSecond() int { + var op = r.ReadOpDuration() + if op == 0 { + return 0 + } + return int(time.Second) / int(op) +} + +type PageError struct { + ID int + Err error +} + +func (e *PageError) Error() string { + return fmt.Sprintf("page error: id=%d, err=%s", e.ID, e.Err) +} + +// isPrintable returns true if the string is valid unicode and contains only printable runes. +func isPrintable(s string) bool { + if !utf8.ValidString(s) { + return false + } + for _, ch := range s { + if !unicode.IsPrint(ch) { + return false + } + } + return true +} + +// ReadPage reads page info & full page data from a path. +// This is not transactionally safe. +func ReadPage(path string, pageID int) (*page, []byte, error) { + // Find page size. + pageSize, err := ReadPageSize(path) + if err != nil { + return nil, nil, fmt.Errorf("read page size: %s", err) + } + + // Open database file. + f, err := os.Open(path) + if err != nil { + return nil, nil, err + } + defer f.Close() + + // Read one block into buffer. + buf := make([]byte, pageSize) + if n, err := f.ReadAt(buf, int64(pageID*pageSize)); err != nil { + return nil, nil, err + } else if n != len(buf) { + return nil, nil, io.ErrUnexpectedEOF + } + + // Determine total number of blocks. + p := (*page)(unsafe.Pointer(&buf[0])) + overflowN := p.overflow + + // Re-read entire page (with overflow) into buffer. + buf = make([]byte, (int(overflowN)+1)*pageSize) + if n, err := f.ReadAt(buf, int64(pageID*pageSize)); err != nil { + return nil, nil, err + } else if n != len(buf) { + return nil, nil, io.ErrUnexpectedEOF + } + p = (*page)(unsafe.Pointer(&buf[0])) + + return p, buf, nil +} + +// ReadPageSize reads page size a path. +// This is not transactionally safe. +func ReadPageSize(path string) (int, error) { + // Open database file. + f, err := os.Open(path) + if err != nil { + return 0, err + } + defer f.Close() + + // Read 4KB chunk. + buf := make([]byte, 4096) + if _, err := io.ReadFull(f, buf); err != nil { + return 0, err + } + + // Read page size from metadata. + m := (*meta)(unsafe.Pointer(&buf[PageHeaderSize])) + return int(m.pageSize), nil +} + +// atois parses a slice of strings into integers. +func atois(strs []string) ([]int, error) { + var a []int + for _, str := range strs { + i, err := strconv.Atoi(str) + if err != nil { + return nil, err + } + a = append(a, i) + } + return a, nil +} + +// DO NOT EDIT. Copied from the "bolt" package. +const maxAllocSize = 0xFFFFFFF + +// DO NOT EDIT. Copied from the "bolt" package. +const ( + branchPageFlag = 0x01 + leafPageFlag = 0x02 + metaPageFlag = 0x04 + freelistPageFlag = 0x10 +) + +// DO NOT EDIT. Copied from the "bolt" package. +const bucketLeafFlag = 0x01 + +// DO NOT EDIT. Copied from the "bolt" package. +type pgid uint64 + +// DO NOT EDIT. Copied from the "bolt" package. +type txid uint64 + +// DO NOT EDIT. Copied from the "bolt" package. +type meta struct { + magic uint32 + version uint32 + pageSize uint32 + flags uint32 + root bucket + freelist pgid + pgid pgid + txid txid + checksum uint64 +} + +// DO NOT EDIT. Copied from the "bolt" package. +type bucket struct { + root pgid + sequence uint64 +} + +// DO NOT EDIT. Copied from the "bolt" package. +type page struct { + id pgid + flags uint16 + count uint16 + overflow uint32 + ptr uintptr +} + +// DO NOT EDIT. Copied from the "bolt" package. +func (p *page) Type() string { + if (p.flags & branchPageFlag) != 0 { + return "branch" + } else if (p.flags & leafPageFlag) != 0 { + return "leaf" + } else if (p.flags & metaPageFlag) != 0 { + return "meta" + } else if (p.flags & freelistPageFlag) != 0 { + return "freelist" + } + return fmt.Sprintf("unknown<%02x>", p.flags) +} + +// DO NOT EDIT. Copied from the "bolt" package. +func (p *page) leafPageElement(index uint16) *leafPageElement { + n := &((*[0x7FFFFFF]leafPageElement)(unsafe.Pointer(&p.ptr)))[index] + return n +} + +// DO NOT EDIT. Copied from the "bolt" package. +func (p *page) branchPageElement(index uint16) *branchPageElement { + return &((*[0x7FFFFFF]branchPageElement)(unsafe.Pointer(&p.ptr)))[index] +} + +// DO NOT EDIT. Copied from the "bolt" package. +type branchPageElement struct { + pos uint32 + ksize uint32 + pgid pgid +} + +// DO NOT EDIT. Copied from the "bolt" package. +func (n *branchPageElement) key() []byte { + buf := (*[maxAllocSize]byte)(unsafe.Pointer(n)) + return buf[n.pos : n.pos+n.ksize] +} + +// DO NOT EDIT. Copied from the "bolt" package. +type leafPageElement struct { + flags uint32 + pos uint32 + ksize uint32 + vsize uint32 +} + +// DO NOT EDIT. Copied from the "bolt" package. +func (n *leafPageElement) key() []byte { + buf := (*[maxAllocSize]byte)(unsafe.Pointer(n)) + return buf[n.pos : n.pos+n.ksize] +} + +// DO NOT EDIT. Copied from the "bolt" package. +func (n *leafPageElement) value() []byte { + buf := (*[maxAllocSize]byte)(unsafe.Pointer(n)) + return buf[n.pos+n.ksize : n.pos+n.ksize+n.vsize] +} + +// CompactCommand represents the "compact" command execution. +type CompactCommand struct { + Stdin io.Reader + Stdout io.Writer + Stderr io.Writer + + SrcPath string + DstPath string + TxMaxSize int64 +} + +// newCompactCommand returns a CompactCommand. +func newCompactCommand(m *Main) *CompactCommand { + return &CompactCommand{ + Stdin: m.Stdin, + Stdout: m.Stdout, + Stderr: m.Stderr, + } +} + +// Run executes the command. +func (cmd *CompactCommand) Run(args ...string) (err error) { + // Parse flags. + fs := flag.NewFlagSet("", flag.ContinueOnError) + fs.SetOutput(ioutil.Discard) + fs.StringVar(&cmd.DstPath, "o", "", "") + fs.Int64Var(&cmd.TxMaxSize, "tx-max-size", 65536, "") + if err := fs.Parse(args); err == flag.ErrHelp { + fmt.Fprintln(cmd.Stderr, cmd.Usage()) + return ErrUsage + } else if err != nil { + return err + } else if cmd.DstPath == "" { + return fmt.Errorf("output file required") + } + + // Require database paths. + cmd.SrcPath = fs.Arg(0) + if cmd.SrcPath == "" { + return ErrPathRequired + } + + // Ensure source file exists. + fi, err := os.Stat(cmd.SrcPath) + if os.IsNotExist(err) { + return ErrFileNotFound + } else if err != nil { + return err + } + initialSize := fi.Size() + + // Open source database. + src, err := bolt.Open(cmd.SrcPath, 0444, nil) + if err != nil { + return err + } + defer src.Close() + + // Open destination database. + dst, err := bolt.Open(cmd.DstPath, fi.Mode(), nil) + if err != nil { + return err + } + defer dst.Close() + + // Run compaction. + if err := cmd.compact(dst, src); err != nil { + return err + } + + // Report stats on new size. + fi, err = os.Stat(cmd.DstPath) + if err != nil { + return err + } else if fi.Size() == 0 { + return fmt.Errorf("zero db size") + } + fmt.Fprintf(cmd.Stdout, "%d -> %d bytes (gain=%.2fx)\n", initialSize, fi.Size(), float64(initialSize)/float64(fi.Size())) + + return nil +} + +func (cmd *CompactCommand) compact(dst, src *bolt.DB) error { + // commit regularly, or we'll run out of memory for large datasets if using one transaction. + var size int64 + tx, err := dst.Begin(true) + if err != nil { + return err + } + defer tx.Rollback() + + if err := cmd.walk(src, func(keys [][]byte, k, v []byte, seq uint64) error { + // On each key/value, check if we have exceeded tx size. + sz := int64(len(k) + len(v)) + if size+sz > cmd.TxMaxSize && cmd.TxMaxSize != 0 { + // Commit previous transaction. + if err := tx.Commit(); err != nil { + return err + } + + // Start new transaction. + tx, err = dst.Begin(true) + if err != nil { + return err + } + size = 0 + } + size += sz + + // Create bucket on the root transaction if this is the first level. + nk := len(keys) + if nk == 0 { + bkt, err := tx.CreateBucket(k) + if err != nil { + return err + } + if err := bkt.SetSequence(seq); err != nil { + return err + } + return nil + } + + // Create buckets on subsequent levels, if necessary. + b := tx.Bucket(keys[0]) + if nk > 1 { + for _, k := range keys[1:] { + b = b.Bucket(k) + } + } + + // If there is no value then this is a bucket call. + if v == nil { + bkt, err := b.CreateBucket(k) + if err != nil { + return err + } + if err := bkt.SetSequence(seq); err != nil { + return err + } + return nil + } + + // Otherwise treat it as a key/value pair. + return b.Put(k, v) + }); err != nil { + return err + } + + return tx.Commit() +} + +// walkFunc is the type of the function called for keys (buckets and "normal" +// values) discovered by Walk. keys is the list of keys to descend to the bucket +// owning the discovered key/value pair k/v. +type walkFunc func(keys [][]byte, k, v []byte, seq uint64) error + +// walk walks recursively the bolt database db, calling walkFn for each key it finds. +func (cmd *CompactCommand) walk(db *bolt.DB, walkFn walkFunc) error { + return db.View(func(tx *bolt.Tx) error { + return tx.ForEach(func(name []byte, b *bolt.Bucket) error { + return cmd.walkBucket(b, nil, name, nil, b.Sequence(), walkFn) + }) + }) +} + +func (cmd *CompactCommand) walkBucket(b *bolt.Bucket, keypath [][]byte, k, v []byte, seq uint64, fn walkFunc) error { + // Execute callback. + if err := fn(keypath, k, v, seq); err != nil { + return err + } + + // If this is not a bucket then stop. + if v != nil { + return nil + } + + // Iterate over each child key/value. + keypath = append(keypath, k) + return b.ForEach(func(k, v []byte) error { + if v == nil { + bkt := b.Bucket(k) + return cmd.walkBucket(bkt, keypath, k, nil, bkt.Sequence(), fn) + } + return cmd.walkBucket(b, keypath, k, v, b.Sequence(), fn) + }) +} + +// Usage returns the help message. +func (cmd *CompactCommand) Usage() string { + return strings.TrimLeft(` +usage: bolt compact [options] -o DST SRC + +Compact opens a database at SRC path and walks it recursively, copying keys +as they are found from all buckets, to a newly created database at DST path. + +The original database is left untouched. + +Additional options include: + + -tx-max-size NUM + Specifies the maximum size of individual transactions. + Defaults to 64KB. +`, "\n") +} diff --git a/vendor/github.com/boltdb/bolt/cmd/bolt/main_test.go b/vendor/github.com/boltdb/bolt/cmd/bolt/main_test.go new file mode 100644 index 00000000..0a11ff33 --- /dev/null +++ b/vendor/github.com/boltdb/bolt/cmd/bolt/main_test.go @@ -0,0 +1,356 @@ +package main_test + +import ( + "bytes" + crypto "crypto/rand" + "encoding/binary" + "fmt" + "io" + "io/ioutil" + "math/rand" + "os" + "strconv" + "testing" + + "github.com/boltdb/bolt" + "github.com/boltdb/bolt/cmd/bolt" +) + +// Ensure the "info" command can print information about a database. +func TestInfoCommand_Run(t *testing.T) { + db := MustOpen(0666, nil) + db.DB.Close() + defer db.Close() + + // Run the info command. + m := NewMain() + if err := m.Run("info", db.Path); err != nil { + t.Fatal(err) + } +} + +// Ensure the "stats" command executes correctly with an empty database. +func TestStatsCommand_Run_EmptyDatabase(t *testing.T) { + // Ignore + if os.Getpagesize() != 4096 { + t.Skip("system does not use 4KB page size") + } + + db := MustOpen(0666, nil) + defer db.Close() + db.DB.Close() + + // Generate expected result. + exp := "Aggregate statistics for 0 buckets\n\n" + + "Page count statistics\n" + + "\tNumber of logical branch pages: 0\n" + + "\tNumber of physical branch overflow pages: 0\n" + + "\tNumber of logical leaf pages: 0\n" + + "\tNumber of physical leaf overflow pages: 0\n" + + "Tree statistics\n" + + "\tNumber of keys/value pairs: 0\n" + + "\tNumber of levels in B+tree: 0\n" + + "Page size utilization\n" + + "\tBytes allocated for physical branch pages: 0\n" + + "\tBytes actually used for branch data: 0 (0%)\n" + + "\tBytes allocated for physical leaf pages: 0\n" + + "\tBytes actually used for leaf data: 0 (0%)\n" + + "Bucket statistics\n" + + "\tTotal number of buckets: 0\n" + + "\tTotal number on inlined buckets: 0 (0%)\n" + + "\tBytes used for inlined buckets: 0 (0%)\n" + + // Run the command. + m := NewMain() + if err := m.Run("stats", db.Path); err != nil { + t.Fatal(err) + } else if m.Stdout.String() != exp { + t.Fatalf("unexpected stdout:\n\n%s", m.Stdout.String()) + } +} + +// Ensure the "stats" command can execute correctly. +func TestStatsCommand_Run(t *testing.T) { + // Ignore + if os.Getpagesize() != 4096 { + t.Skip("system does not use 4KB page size") + } + + db := MustOpen(0666, nil) + defer db.Close() + + if err := db.Update(func(tx *bolt.Tx) error { + // Create "foo" bucket. + b, err := tx.CreateBucket([]byte("foo")) + if err != nil { + return err + } + for i := 0; i < 10; i++ { + if err := b.Put([]byte(strconv.Itoa(i)), []byte(strconv.Itoa(i))); err != nil { + return err + } + } + + // Create "bar" bucket. + b, err = tx.CreateBucket([]byte("bar")) + if err != nil { + return err + } + for i := 0; i < 100; i++ { + if err := b.Put([]byte(strconv.Itoa(i)), []byte(strconv.Itoa(i))); err != nil { + return err + } + } + + // Create "baz" bucket. + b, err = tx.CreateBucket([]byte("baz")) + if err != nil { + return err + } + if err := b.Put([]byte("key"), []byte("value")); err != nil { + return err + } + + return nil + }); err != nil { + t.Fatal(err) + } + db.DB.Close() + + // Generate expected result. + exp := "Aggregate statistics for 3 buckets\n\n" + + "Page count statistics\n" + + "\tNumber of logical branch pages: 0\n" + + "\tNumber of physical branch overflow pages: 0\n" + + "\tNumber of logical leaf pages: 1\n" + + "\tNumber of physical leaf overflow pages: 0\n" + + "Tree statistics\n" + + "\tNumber of keys/value pairs: 111\n" + + "\tNumber of levels in B+tree: 1\n" + + "Page size utilization\n" + + "\tBytes allocated for physical branch pages: 0\n" + + "\tBytes actually used for branch data: 0 (0%)\n" + + "\tBytes allocated for physical leaf pages: 4096\n" + + "\tBytes actually used for leaf data: 1996 (48%)\n" + + "Bucket statistics\n" + + "\tTotal number of buckets: 3\n" + + "\tTotal number on inlined buckets: 2 (66%)\n" + + "\tBytes used for inlined buckets: 236 (11%)\n" + + // Run the command. + m := NewMain() + if err := m.Run("stats", db.Path); err != nil { + t.Fatal(err) + } else if m.Stdout.String() != exp { + t.Fatalf("unexpected stdout:\n\n%s", m.Stdout.String()) + } +} + +// Main represents a test wrapper for main.Main that records output. +type Main struct { + *main.Main + Stdin bytes.Buffer + Stdout bytes.Buffer + Stderr bytes.Buffer +} + +// NewMain returns a new instance of Main. +func NewMain() *Main { + m := &Main{Main: main.NewMain()} + m.Main.Stdin = &m.Stdin + m.Main.Stdout = &m.Stdout + m.Main.Stderr = &m.Stderr + return m +} + +// MustOpen creates a Bolt database in a temporary location. +func MustOpen(mode os.FileMode, options *bolt.Options) *DB { + // Create temporary path. + f, _ := ioutil.TempFile("", "bolt-") + f.Close() + os.Remove(f.Name()) + + db, err := bolt.Open(f.Name(), mode, options) + if err != nil { + panic(err.Error()) + } + return &DB{DB: db, Path: f.Name()} +} + +// DB is a test wrapper for bolt.DB. +type DB struct { + *bolt.DB + Path string +} + +// Close closes and removes the database. +func (db *DB) Close() error { + defer os.Remove(db.Path) + return db.DB.Close() +} + +func TestCompactCommand_Run(t *testing.T) { + var s int64 + if err := binary.Read(crypto.Reader, binary.BigEndian, &s); err != nil { + t.Fatal(err) + } + rand.Seed(s) + + dstdb := MustOpen(0666, nil) + dstdb.Close() + + // fill the db + db := MustOpen(0666, nil) + if err := db.Update(func(tx *bolt.Tx) error { + n := 2 + rand.Intn(5) + for i := 0; i < n; i++ { + k := []byte(fmt.Sprintf("b%d", i)) + b, err := tx.CreateBucketIfNotExists(k) + if err != nil { + return err + } + if err := b.SetSequence(uint64(i)); err != nil { + return err + } + if err := fillBucket(b, append(k, '.')); err != nil { + return err + } + } + return nil + }); err != nil { + db.Close() + t.Fatal(err) + } + + // make the db grow by adding large values, and delete them. + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucketIfNotExists([]byte("large_vals")) + if err != nil { + return err + } + n := 5 + rand.Intn(5) + for i := 0; i < n; i++ { + v := make([]byte, 1000*1000*(1+rand.Intn(5))) + _, err := crypto.Read(v) + if err != nil { + return err + } + if err := b.Put([]byte(fmt.Sprintf("l%d", i)), v); err != nil { + return err + } + } + return nil + }); err != nil { + db.Close() + t.Fatal(err) + } + if err := db.Update(func(tx *bolt.Tx) error { + c := tx.Bucket([]byte("large_vals")).Cursor() + for k, _ := c.First(); k != nil; k, _ = c.Next() { + if err := c.Delete(); err != nil { + return err + } + } + return tx.DeleteBucket([]byte("large_vals")) + }); err != nil { + db.Close() + t.Fatal(err) + } + db.DB.Close() + defer db.Close() + defer dstdb.Close() + + dbChk, err := chkdb(db.Path) + if err != nil { + t.Fatal(err) + } + + m := NewMain() + if err := m.Run("compact", "-o", dstdb.Path, db.Path); err != nil { + t.Fatal(err) + } + + dbChkAfterCompact, err := chkdb(db.Path) + if err != nil { + t.Fatal(err) + } + + dstdbChk, err := chkdb(dstdb.Path) + if err != nil { + t.Fatal(err) + } + + if !bytes.Equal(dbChk, dbChkAfterCompact) { + t.Error("the original db has been touched") + } + if !bytes.Equal(dbChk, dstdbChk) { + t.Error("the compacted db data isn't the same than the original db") + } +} + +func fillBucket(b *bolt.Bucket, prefix []byte) error { + n := 10 + rand.Intn(50) + for i := 0; i < n; i++ { + v := make([]byte, 10*(1+rand.Intn(4))) + _, err := crypto.Read(v) + if err != nil { + return err + } + k := append(prefix, []byte(fmt.Sprintf("k%d", i))...) + if err := b.Put(k, v); err != nil { + return err + } + } + // limit depth of subbuckets + s := 2 + rand.Intn(4) + if len(prefix) > (2*s + 1) { + return nil + } + n = 1 + rand.Intn(3) + for i := 0; i < n; i++ { + k := append(prefix, []byte(fmt.Sprintf("b%d", i))...) + sb, err := b.CreateBucket(k) + if err != nil { + return err + } + if err := fillBucket(sb, append(k, '.')); err != nil { + return err + } + } + return nil +} + +func chkdb(path string) ([]byte, error) { + db, err := bolt.Open(path, 0666, nil) + if err != nil { + return nil, err + } + defer db.Close() + var buf bytes.Buffer + err = db.View(func(tx *bolt.Tx) error { + return tx.ForEach(func(name []byte, b *bolt.Bucket) error { + return walkBucket(b, name, nil, &buf) + }) + }) + if err != nil { + return nil, err + } + return buf.Bytes(), nil +} + +func walkBucket(parent *bolt.Bucket, k []byte, v []byte, w io.Writer) error { + if _, err := fmt.Fprintf(w, "%d:%x=%x\n", parent.Sequence(), k, v); err != nil { + return err + } + + // not a bucket, exit. + if v != nil { + return nil + } + return parent.ForEach(func(k, v []byte) error { + if v == nil { + return walkBucket(parent.Bucket(k), k, nil, w) + } + return walkBucket(parent, k, v, w) + }) +} diff --git a/vendor/github.com/boltdb/bolt/cursor.go b/vendor/github.com/boltdb/bolt/cursor.go new file mode 100644 index 00000000..1be9f35e --- /dev/null +++ b/vendor/github.com/boltdb/bolt/cursor.go @@ -0,0 +1,400 @@ +package bolt + +import ( + "bytes" + "fmt" + "sort" +) + +// Cursor represents an iterator that can traverse over all key/value pairs in a bucket in sorted order. +// Cursors see nested buckets with value == nil. +// Cursors can be obtained from a transaction and are valid as long as the transaction is open. +// +// Keys and values returned from the cursor are only valid for the life of the transaction. +// +// Changing data while traversing with a cursor may cause it to be invalidated +// and return unexpected keys and/or values. You must reposition your cursor +// after mutating data. +type Cursor struct { + bucket *Bucket + stack []elemRef +} + +// Bucket returns the bucket that this cursor was created from. +func (c *Cursor) Bucket() *Bucket { + return c.bucket +} + +// First moves the cursor to the first item in the bucket and returns its key and value. +// If the bucket is empty then a nil key and value are returned. +// The returned key and value are only valid for the life of the transaction. +func (c *Cursor) First() (key []byte, value []byte) { + _assert(c.bucket.tx.db != nil, "tx closed") + c.stack = c.stack[:0] + p, n := c.bucket.pageNode(c.bucket.root) + c.stack = append(c.stack, elemRef{page: p, node: n, index: 0}) + c.first() + + // If we land on an empty page then move to the next value. + // https://github.com/boltdb/bolt/issues/450 + if c.stack[len(c.stack)-1].count() == 0 { + c.next() + } + + k, v, flags := c.keyValue() + if (flags & uint32(bucketLeafFlag)) != 0 { + return k, nil + } + return k, v + +} + +// Last moves the cursor to the last item in the bucket and returns its key and value. +// If the bucket is empty then a nil key and value are returned. +// The returned key and value are only valid for the life of the transaction. +func (c *Cursor) Last() (key []byte, value []byte) { + _assert(c.bucket.tx.db != nil, "tx closed") + c.stack = c.stack[:0] + p, n := c.bucket.pageNode(c.bucket.root) + ref := elemRef{page: p, node: n} + ref.index = ref.count() - 1 + c.stack = append(c.stack, ref) + c.last() + k, v, flags := c.keyValue() + if (flags & uint32(bucketLeafFlag)) != 0 { + return k, nil + } + return k, v +} + +// Next moves the cursor to the next item in the bucket and returns its key and value. +// If the cursor is at the end of the bucket then a nil key and value are returned. +// The returned key and value are only valid for the life of the transaction. +func (c *Cursor) Next() (key []byte, value []byte) { + _assert(c.bucket.tx.db != nil, "tx closed") + k, v, flags := c.next() + if (flags & uint32(bucketLeafFlag)) != 0 { + return k, nil + } + return k, v +} + +// Prev moves the cursor to the previous item in the bucket and returns its key and value. +// If the cursor is at the beginning of the bucket then a nil key and value are returned. +// The returned key and value are only valid for the life of the transaction. +func (c *Cursor) Prev() (key []byte, value []byte) { + _assert(c.bucket.tx.db != nil, "tx closed") + + // Attempt to move back one element until we're successful. + // Move up the stack as we hit the beginning of each page in our stack. + for i := len(c.stack) - 1; i >= 0; i-- { + elem := &c.stack[i] + if elem.index > 0 { + elem.index-- + break + } + c.stack = c.stack[:i] + } + + // If we've hit the end then return nil. + if len(c.stack) == 0 { + return nil, nil + } + + // Move down the stack to find the last element of the last leaf under this branch. + c.last() + k, v, flags := c.keyValue() + if (flags & uint32(bucketLeafFlag)) != 0 { + return k, nil + } + return k, v +} + +// Seek moves the cursor to a given key and returns it. +// If the key does not exist then the next key is used. If no keys +// follow, a nil key is returned. +// The returned key and value are only valid for the life of the transaction. +func (c *Cursor) Seek(seek []byte) (key []byte, value []byte) { + k, v, flags := c.seek(seek) + + // If we ended up after the last element of a page then move to the next one. + if ref := &c.stack[len(c.stack)-1]; ref.index >= ref.count() { + k, v, flags = c.next() + } + + if k == nil { + return nil, nil + } else if (flags & uint32(bucketLeafFlag)) != 0 { + return k, nil + } + return k, v +} + +// Delete removes the current key/value under the cursor from the bucket. +// Delete fails if current key/value is a bucket or if the transaction is not writable. +func (c *Cursor) Delete() error { + if c.bucket.tx.db == nil { + return ErrTxClosed + } else if !c.bucket.Writable() { + return ErrTxNotWritable + } + + key, _, flags := c.keyValue() + // Return an error if current value is a bucket. + if (flags & bucketLeafFlag) != 0 { + return ErrIncompatibleValue + } + c.node().del(key) + + return nil +} + +// seek moves the cursor to a given key and returns it. +// If the key does not exist then the next key is used. +func (c *Cursor) seek(seek []byte) (key []byte, value []byte, flags uint32) { + _assert(c.bucket.tx.db != nil, "tx closed") + + // Start from root page/node and traverse to correct page. + c.stack = c.stack[:0] + c.search(seek, c.bucket.root) + ref := &c.stack[len(c.stack)-1] + + // If the cursor is pointing to the end of page/node then return nil. + if ref.index >= ref.count() { + return nil, nil, 0 + } + + // If this is a bucket then return a nil value. + return c.keyValue() +} + +// first moves the cursor to the first leaf element under the last page in the stack. +func (c *Cursor) first() { + for { + // Exit when we hit a leaf page. + var ref = &c.stack[len(c.stack)-1] + if ref.isLeaf() { + break + } + + // Keep adding pages pointing to the first element to the stack. + var pgid pgid + if ref.node != nil { + pgid = ref.node.inodes[ref.index].pgid + } else { + pgid = ref.page.branchPageElement(uint16(ref.index)).pgid + } + p, n := c.bucket.pageNode(pgid) + c.stack = append(c.stack, elemRef{page: p, node: n, index: 0}) + } +} + +// last moves the cursor to the last leaf element under the last page in the stack. +func (c *Cursor) last() { + for { + // Exit when we hit a leaf page. + ref := &c.stack[len(c.stack)-1] + if ref.isLeaf() { + break + } + + // Keep adding pages pointing to the last element in the stack. + var pgid pgid + if ref.node != nil { + pgid = ref.node.inodes[ref.index].pgid + } else { + pgid = ref.page.branchPageElement(uint16(ref.index)).pgid + } + p, n := c.bucket.pageNode(pgid) + + var nextRef = elemRef{page: p, node: n} + nextRef.index = nextRef.count() - 1 + c.stack = append(c.stack, nextRef) + } +} + +// next moves to the next leaf element and returns the key and value. +// If the cursor is at the last leaf element then it stays there and returns nil. +func (c *Cursor) next() (key []byte, value []byte, flags uint32) { + for { + // Attempt to move over one element until we're successful. + // Move up the stack as we hit the end of each page in our stack. + var i int + for i = len(c.stack) - 1; i >= 0; i-- { + elem := &c.stack[i] + if elem.index < elem.count()-1 { + elem.index++ + break + } + } + + // If we've hit the root page then stop and return. This will leave the + // cursor on the last element of the last page. + if i == -1 { + return nil, nil, 0 + } + + // Otherwise start from where we left off in the stack and find the + // first element of the first leaf page. + c.stack = c.stack[:i+1] + c.first() + + // If this is an empty page then restart and move back up the stack. + // https://github.com/boltdb/bolt/issues/450 + if c.stack[len(c.stack)-1].count() == 0 { + continue + } + + return c.keyValue() + } +} + +// search recursively performs a binary search against a given page/node until it finds a given key. +func (c *Cursor) search(key []byte, pgid pgid) { + p, n := c.bucket.pageNode(pgid) + if p != nil && (p.flags&(branchPageFlag|leafPageFlag)) == 0 { + panic(fmt.Sprintf("invalid page type: %d: %x", p.id, p.flags)) + } + e := elemRef{page: p, node: n} + c.stack = append(c.stack, e) + + // If we're on a leaf page/node then find the specific node. + if e.isLeaf() { + c.nsearch(key) + return + } + + if n != nil { + c.searchNode(key, n) + return + } + c.searchPage(key, p) +} + +func (c *Cursor) searchNode(key []byte, n *node) { + var exact bool + index := sort.Search(len(n.inodes), func(i int) bool { + // TODO(benbjohnson): Optimize this range search. It's a bit hacky right now. + // sort.Search() finds the lowest index where f() != -1 but we need the highest index. + ret := bytes.Compare(n.inodes[i].key, key) + if ret == 0 { + exact = true + } + return ret != -1 + }) + if !exact && index > 0 { + index-- + } + c.stack[len(c.stack)-1].index = index + + // Recursively search to the next page. + c.search(key, n.inodes[index].pgid) +} + +func (c *Cursor) searchPage(key []byte, p *page) { + // Binary search for the correct range. + inodes := p.branchPageElements() + + var exact bool + index := sort.Search(int(p.count), func(i int) bool { + // TODO(benbjohnson): Optimize this range search. It's a bit hacky right now. + // sort.Search() finds the lowest index where f() != -1 but we need the highest index. + ret := bytes.Compare(inodes[i].key(), key) + if ret == 0 { + exact = true + } + return ret != -1 + }) + if !exact && index > 0 { + index-- + } + c.stack[len(c.stack)-1].index = index + + // Recursively search to the next page. + c.search(key, inodes[index].pgid) +} + +// nsearch searches the leaf node on the top of the stack for a key. +func (c *Cursor) nsearch(key []byte) { + e := &c.stack[len(c.stack)-1] + p, n := e.page, e.node + + // If we have a node then search its inodes. + if n != nil { + index := sort.Search(len(n.inodes), func(i int) bool { + return bytes.Compare(n.inodes[i].key, key) != -1 + }) + e.index = index + return + } + + // If we have a page then search its leaf elements. + inodes := p.leafPageElements() + index := sort.Search(int(p.count), func(i int) bool { + return bytes.Compare(inodes[i].key(), key) != -1 + }) + e.index = index +} + +// keyValue returns the key and value of the current leaf element. +func (c *Cursor) keyValue() ([]byte, []byte, uint32) { + ref := &c.stack[len(c.stack)-1] + if ref.count() == 0 || ref.index >= ref.count() { + return nil, nil, 0 + } + + // Retrieve value from node. + if ref.node != nil { + inode := &ref.node.inodes[ref.index] + return inode.key, inode.value, inode.flags + } + + // Or retrieve value from page. + elem := ref.page.leafPageElement(uint16(ref.index)) + return elem.key(), elem.value(), elem.flags +} + +// node returns the node that the cursor is currently positioned on. +func (c *Cursor) node() *node { + _assert(len(c.stack) > 0, "accessing a node with a zero-length cursor stack") + + // If the top of the stack is a leaf node then just return it. + if ref := &c.stack[len(c.stack)-1]; ref.node != nil && ref.isLeaf() { + return ref.node + } + + // Start from root and traverse down the hierarchy. + var n = c.stack[0].node + if n == nil { + n = c.bucket.node(c.stack[0].page.id, nil) + } + for _, ref := range c.stack[:len(c.stack)-1] { + _assert(!n.isLeaf, "expected branch node") + n = n.childAt(int(ref.index)) + } + _assert(n.isLeaf, "expected leaf node") + return n +} + +// elemRef represents a reference to an element on a given page/node. +type elemRef struct { + page *page + node *node + index int +} + +// isLeaf returns whether the ref is pointing at a leaf page/node. +func (r *elemRef) isLeaf() bool { + if r.node != nil { + return r.node.isLeaf + } + return (r.page.flags & leafPageFlag) != 0 +} + +// count returns the number of inodes or page elements. +func (r *elemRef) count() int { + if r.node != nil { + return len(r.node.inodes) + } + return int(r.page.count) +} diff --git a/vendor/github.com/boltdb/bolt/cursor_test.go b/vendor/github.com/boltdb/bolt/cursor_test.go new file mode 100644 index 00000000..562d60f9 --- /dev/null +++ b/vendor/github.com/boltdb/bolt/cursor_test.go @@ -0,0 +1,817 @@ +package bolt_test + +import ( + "bytes" + "encoding/binary" + "fmt" + "log" + "os" + "reflect" + "sort" + "testing" + "testing/quick" + + "github.com/boltdb/bolt" +) + +// Ensure that a cursor can return a reference to the bucket that created it. +func TestCursor_Bucket(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + if cb := b.Cursor().Bucket(); !reflect.DeepEqual(cb, b) { + t.Fatal("cursor bucket mismatch") + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that a Tx cursor can seek to the appropriate keys. +func TestCursor_Seek(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("foo"), []byte("0001")); err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("bar"), []byte("0002")); err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("baz"), []byte("0003")); err != nil { + t.Fatal(err) + } + + if _, err := b.CreateBucket([]byte("bkt")); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + + if err := db.View(func(tx *bolt.Tx) error { + c := tx.Bucket([]byte("widgets")).Cursor() + + // Exact match should go to the key. + if k, v := c.Seek([]byte("bar")); !bytes.Equal(k, []byte("bar")) { + t.Fatalf("unexpected key: %v", k) + } else if !bytes.Equal(v, []byte("0002")) { + t.Fatalf("unexpected value: %v", v) + } + + // Inexact match should go to the next key. + if k, v := c.Seek([]byte("bas")); !bytes.Equal(k, []byte("baz")) { + t.Fatalf("unexpected key: %v", k) + } else if !bytes.Equal(v, []byte("0003")) { + t.Fatalf("unexpected value: %v", v) + } + + // Low key should go to the first key. + if k, v := c.Seek([]byte("")); !bytes.Equal(k, []byte("bar")) { + t.Fatalf("unexpected key: %v", k) + } else if !bytes.Equal(v, []byte("0002")) { + t.Fatalf("unexpected value: %v", v) + } + + // High key should return no key. + if k, v := c.Seek([]byte("zzz")); k != nil { + t.Fatalf("expected nil key: %v", k) + } else if v != nil { + t.Fatalf("expected nil value: %v", v) + } + + // Buckets should return their key but no value. + if k, v := c.Seek([]byte("bkt")); !bytes.Equal(k, []byte("bkt")) { + t.Fatalf("unexpected key: %v", k) + } else if v != nil { + t.Fatalf("expected nil value: %v", v) + } + + return nil + }); err != nil { + t.Fatal(err) + } +} + +func TestCursor_Delete(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + const count = 1000 + + // Insert every other key between 0 and $count. + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + for i := 0; i < count; i += 1 { + k := make([]byte, 8) + binary.BigEndian.PutUint64(k, uint64(i)) + if err := b.Put(k, make([]byte, 100)); err != nil { + t.Fatal(err) + } + } + if _, err := b.CreateBucket([]byte("sub")); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + + if err := db.Update(func(tx *bolt.Tx) error { + c := tx.Bucket([]byte("widgets")).Cursor() + bound := make([]byte, 8) + binary.BigEndian.PutUint64(bound, uint64(count/2)) + for key, _ := c.First(); bytes.Compare(key, bound) < 0; key, _ = c.Next() { + if err := c.Delete(); err != nil { + t.Fatal(err) + } + } + + c.Seek([]byte("sub")) + if err := c.Delete(); err != bolt.ErrIncompatibleValue { + t.Fatalf("unexpected error: %s", err) + } + + return nil + }); err != nil { + t.Fatal(err) + } + + if err := db.View(func(tx *bolt.Tx) error { + stats := tx.Bucket([]byte("widgets")).Stats() + if stats.KeyN != count/2+1 { + t.Fatalf("unexpected KeyN: %d", stats.KeyN) + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that a Tx cursor can seek to the appropriate keys when there are a +// large number of keys. This test also checks that seek will always move +// forward to the next key. +// +// Related: https://github.com/boltdb/bolt/pull/187 +func TestCursor_Seek_Large(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + var count = 10000 + + // Insert every other key between 0 and $count. + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + + for i := 0; i < count; i += 100 { + for j := i; j < i+100; j += 2 { + k := make([]byte, 8) + binary.BigEndian.PutUint64(k, uint64(j)) + if err := b.Put(k, make([]byte, 100)); err != nil { + t.Fatal(err) + } + } + } + return nil + }); err != nil { + t.Fatal(err) + } + + if err := db.View(func(tx *bolt.Tx) error { + c := tx.Bucket([]byte("widgets")).Cursor() + for i := 0; i < count; i++ { + seek := make([]byte, 8) + binary.BigEndian.PutUint64(seek, uint64(i)) + + k, _ := c.Seek(seek) + + // The last seek is beyond the end of the the range so + // it should return nil. + if i == count-1 { + if k != nil { + t.Fatal("expected nil key") + } + continue + } + + // Otherwise we should seek to the exact key or the next key. + num := binary.BigEndian.Uint64(k) + if i%2 == 0 { + if num != uint64(i) { + t.Fatalf("unexpected num: %d", num) + } + } else { + if num != uint64(i+1) { + t.Fatalf("unexpected num: %d", num) + } + } + } + + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that a cursor can iterate over an empty bucket without error. +func TestCursor_EmptyBucket(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + if err := db.Update(func(tx *bolt.Tx) error { + _, err := tx.CreateBucket([]byte("widgets")) + return err + }); err != nil { + t.Fatal(err) + } + + if err := db.View(func(tx *bolt.Tx) error { + c := tx.Bucket([]byte("widgets")).Cursor() + k, v := c.First() + if k != nil { + t.Fatalf("unexpected key: %v", k) + } else if v != nil { + t.Fatalf("unexpected value: %v", v) + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that a Tx cursor can reverse iterate over an empty bucket without error. +func TestCursor_EmptyBucketReverse(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + if err := db.Update(func(tx *bolt.Tx) error { + _, err := tx.CreateBucket([]byte("widgets")) + return err + }); err != nil { + t.Fatal(err) + } + if err := db.View(func(tx *bolt.Tx) error { + c := tx.Bucket([]byte("widgets")).Cursor() + k, v := c.Last() + if k != nil { + t.Fatalf("unexpected key: %v", k) + } else if v != nil { + t.Fatalf("unexpected value: %v", v) + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that a Tx cursor can iterate over a single root with a couple elements. +func TestCursor_Iterate_Leaf(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("baz"), []byte{}); err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("foo"), []byte{0}); err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("bar"), []byte{1}); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + tx, err := db.Begin(false) + if err != nil { + t.Fatal(err) + } + defer func() { _ = tx.Rollback() }() + + c := tx.Bucket([]byte("widgets")).Cursor() + + k, v := c.First() + if !bytes.Equal(k, []byte("bar")) { + t.Fatalf("unexpected key: %v", k) + } else if !bytes.Equal(v, []byte{1}) { + t.Fatalf("unexpected value: %v", v) + } + + k, v = c.Next() + if !bytes.Equal(k, []byte("baz")) { + t.Fatalf("unexpected key: %v", k) + } else if !bytes.Equal(v, []byte{}) { + t.Fatalf("unexpected value: %v", v) + } + + k, v = c.Next() + if !bytes.Equal(k, []byte("foo")) { + t.Fatalf("unexpected key: %v", k) + } else if !bytes.Equal(v, []byte{0}) { + t.Fatalf("unexpected value: %v", v) + } + + k, v = c.Next() + if k != nil { + t.Fatalf("expected nil key: %v", k) + } else if v != nil { + t.Fatalf("expected nil value: %v", v) + } + + k, v = c.Next() + if k != nil { + t.Fatalf("expected nil key: %v", k) + } else if v != nil { + t.Fatalf("expected nil value: %v", v) + } + + if err := tx.Rollback(); err != nil { + t.Fatal(err) + } +} + +// Ensure that a Tx cursor can iterate in reverse over a single root with a couple elements. +func TestCursor_LeafRootReverse(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("baz"), []byte{}); err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("foo"), []byte{0}); err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("bar"), []byte{1}); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + tx, err := db.Begin(false) + if err != nil { + t.Fatal(err) + } + c := tx.Bucket([]byte("widgets")).Cursor() + + if k, v := c.Last(); !bytes.Equal(k, []byte("foo")) { + t.Fatalf("unexpected key: %v", k) + } else if !bytes.Equal(v, []byte{0}) { + t.Fatalf("unexpected value: %v", v) + } + + if k, v := c.Prev(); !bytes.Equal(k, []byte("baz")) { + t.Fatalf("unexpected key: %v", k) + } else if !bytes.Equal(v, []byte{}) { + t.Fatalf("unexpected value: %v", v) + } + + if k, v := c.Prev(); !bytes.Equal(k, []byte("bar")) { + t.Fatalf("unexpected key: %v", k) + } else if !bytes.Equal(v, []byte{1}) { + t.Fatalf("unexpected value: %v", v) + } + + if k, v := c.Prev(); k != nil { + t.Fatalf("expected nil key: %v", k) + } else if v != nil { + t.Fatalf("expected nil value: %v", v) + } + + if k, v := c.Prev(); k != nil { + t.Fatalf("expected nil key: %v", k) + } else if v != nil { + t.Fatalf("expected nil value: %v", v) + } + + if err := tx.Rollback(); err != nil { + t.Fatal(err) + } +} + +// Ensure that a Tx cursor can restart from the beginning. +func TestCursor_Restart(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("bar"), []byte{}); err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("foo"), []byte{}); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + + tx, err := db.Begin(false) + if err != nil { + t.Fatal(err) + } + c := tx.Bucket([]byte("widgets")).Cursor() + + if k, _ := c.First(); !bytes.Equal(k, []byte("bar")) { + t.Fatalf("unexpected key: %v", k) + } + if k, _ := c.Next(); !bytes.Equal(k, []byte("foo")) { + t.Fatalf("unexpected key: %v", k) + } + + if k, _ := c.First(); !bytes.Equal(k, []byte("bar")) { + t.Fatalf("unexpected key: %v", k) + } + if k, _ := c.Next(); !bytes.Equal(k, []byte("foo")) { + t.Fatalf("unexpected key: %v", k) + } + + if err := tx.Rollback(); err != nil { + t.Fatal(err) + } +} + +// Ensure that a cursor can skip over empty pages that have been deleted. +func TestCursor_First_EmptyPages(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + // Create 1000 keys in the "widgets" bucket. + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + + for i := 0; i < 1000; i++ { + if err := b.Put(u64tob(uint64(i)), []byte{}); err != nil { + t.Fatal(err) + } + } + + return nil + }); err != nil { + t.Fatal(err) + } + + // Delete half the keys and then try to iterate. + if err := db.Update(func(tx *bolt.Tx) error { + b := tx.Bucket([]byte("widgets")) + for i := 0; i < 600; i++ { + if err := b.Delete(u64tob(uint64(i))); err != nil { + t.Fatal(err) + } + } + + c := b.Cursor() + var n int + for k, _ := c.First(); k != nil; k, _ = c.Next() { + n++ + } + if n != 400 { + t.Fatalf("unexpected key count: %d", n) + } + + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that a Tx can iterate over all elements in a bucket. +func TestCursor_QuickCheck(t *testing.T) { + f := func(items testdata) bool { + db := MustOpenDB() + defer db.MustClose() + + // Bulk insert all values. + tx, err := db.Begin(true) + if err != nil { + t.Fatal(err) + } + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + for _, item := range items { + if err := b.Put(item.Key, item.Value); err != nil { + t.Fatal(err) + } + } + if err := tx.Commit(); err != nil { + t.Fatal(err) + } + + // Sort test data. + sort.Sort(items) + + // Iterate over all items and check consistency. + var index = 0 + tx, err = db.Begin(false) + if err != nil { + t.Fatal(err) + } + + c := tx.Bucket([]byte("widgets")).Cursor() + for k, v := c.First(); k != nil && index < len(items); k, v = c.Next() { + if !bytes.Equal(k, items[index].Key) { + t.Fatalf("unexpected key: %v", k) + } else if !bytes.Equal(v, items[index].Value) { + t.Fatalf("unexpected value: %v", v) + } + index++ + } + if len(items) != index { + t.Fatalf("unexpected item count: %v, expected %v", len(items), index) + } + + if err := tx.Rollback(); err != nil { + t.Fatal(err) + } + + return true + } + if err := quick.Check(f, qconfig()); err != nil { + t.Error(err) + } +} + +// Ensure that a transaction can iterate over all elements in a bucket in reverse. +func TestCursor_QuickCheck_Reverse(t *testing.T) { + f := func(items testdata) bool { + db := MustOpenDB() + defer db.MustClose() + + // Bulk insert all values. + tx, err := db.Begin(true) + if err != nil { + t.Fatal(err) + } + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + for _, item := range items { + if err := b.Put(item.Key, item.Value); err != nil { + t.Fatal(err) + } + } + if err := tx.Commit(); err != nil { + t.Fatal(err) + } + + // Sort test data. + sort.Sort(revtestdata(items)) + + // Iterate over all items and check consistency. + var index = 0 + tx, err = db.Begin(false) + if err != nil { + t.Fatal(err) + } + c := tx.Bucket([]byte("widgets")).Cursor() + for k, v := c.Last(); k != nil && index < len(items); k, v = c.Prev() { + if !bytes.Equal(k, items[index].Key) { + t.Fatalf("unexpected key: %v", k) + } else if !bytes.Equal(v, items[index].Value) { + t.Fatalf("unexpected value: %v", v) + } + index++ + } + if len(items) != index { + t.Fatalf("unexpected item count: %v, expected %v", len(items), index) + } + + if err := tx.Rollback(); err != nil { + t.Fatal(err) + } + + return true + } + if err := quick.Check(f, qconfig()); err != nil { + t.Error(err) + } +} + +// Ensure that a Tx cursor can iterate over subbuckets. +func TestCursor_QuickCheck_BucketsOnly(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + if _, err := b.CreateBucket([]byte("foo")); err != nil { + t.Fatal(err) + } + if _, err := b.CreateBucket([]byte("bar")); err != nil { + t.Fatal(err) + } + if _, err := b.CreateBucket([]byte("baz")); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + + if err := db.View(func(tx *bolt.Tx) error { + var names []string + c := tx.Bucket([]byte("widgets")).Cursor() + for k, v := c.First(); k != nil; k, v = c.Next() { + names = append(names, string(k)) + if v != nil { + t.Fatalf("unexpected value: %v", v) + } + } + if !reflect.DeepEqual(names, []string{"bar", "baz", "foo"}) { + t.Fatalf("unexpected names: %+v", names) + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that a Tx cursor can reverse iterate over subbuckets. +func TestCursor_QuickCheck_BucketsOnly_Reverse(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + if _, err := b.CreateBucket([]byte("foo")); err != nil { + t.Fatal(err) + } + if _, err := b.CreateBucket([]byte("bar")); err != nil { + t.Fatal(err) + } + if _, err := b.CreateBucket([]byte("baz")); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + + if err := db.View(func(tx *bolt.Tx) error { + var names []string + c := tx.Bucket([]byte("widgets")).Cursor() + for k, v := c.Last(); k != nil; k, v = c.Prev() { + names = append(names, string(k)) + if v != nil { + t.Fatalf("unexpected value: %v", v) + } + } + if !reflect.DeepEqual(names, []string{"foo", "baz", "bar"}) { + t.Fatalf("unexpected names: %+v", names) + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +func ExampleCursor() { + // Open the database. + db, err := bolt.Open(tempfile(), 0666, nil) + if err != nil { + log.Fatal(err) + } + defer os.Remove(db.Path()) + + // Start a read-write transaction. + if err := db.Update(func(tx *bolt.Tx) error { + // Create a new bucket. + b, err := tx.CreateBucket([]byte("animals")) + if err != nil { + return err + } + + // Insert data into a bucket. + if err := b.Put([]byte("dog"), []byte("fun")); err != nil { + log.Fatal(err) + } + if err := b.Put([]byte("cat"), []byte("lame")); err != nil { + log.Fatal(err) + } + if err := b.Put([]byte("liger"), []byte("awesome")); err != nil { + log.Fatal(err) + } + + // Create a cursor for iteration. + c := b.Cursor() + + // Iterate over items in sorted key order. This starts from the + // first key/value pair and updates the k/v variables to the + // next key/value on each iteration. + // + // The loop finishes at the end of the cursor when a nil key is returned. + for k, v := c.First(); k != nil; k, v = c.Next() { + fmt.Printf("A %s is %s.\n", k, v) + } + + return nil + }); err != nil { + log.Fatal(err) + } + + if err := db.Close(); err != nil { + log.Fatal(err) + } + + // Output: + // A cat is lame. + // A dog is fun. + // A liger is awesome. +} + +func ExampleCursor_reverse() { + // Open the database. + db, err := bolt.Open(tempfile(), 0666, nil) + if err != nil { + log.Fatal(err) + } + defer os.Remove(db.Path()) + + // Start a read-write transaction. + if err := db.Update(func(tx *bolt.Tx) error { + // Create a new bucket. + b, err := tx.CreateBucket([]byte("animals")) + if err != nil { + return err + } + + // Insert data into a bucket. + if err := b.Put([]byte("dog"), []byte("fun")); err != nil { + log.Fatal(err) + } + if err := b.Put([]byte("cat"), []byte("lame")); err != nil { + log.Fatal(err) + } + if err := b.Put([]byte("liger"), []byte("awesome")); err != nil { + log.Fatal(err) + } + + // Create a cursor for iteration. + c := b.Cursor() + + // Iterate over items in reverse sorted key order. This starts + // from the last key/value pair and updates the k/v variables to + // the previous key/value on each iteration. + // + // The loop finishes at the beginning of the cursor when a nil key + // is returned. + for k, v := c.Last(); k != nil; k, v = c.Prev() { + fmt.Printf("A %s is %s.\n", k, v) + } + + return nil + }); err != nil { + log.Fatal(err) + } + + // Close the database to release the file lock. + if err := db.Close(); err != nil { + log.Fatal(err) + } + + // Output: + // A liger is awesome. + // A dog is fun. + // A cat is lame. +} diff --git a/vendor/github.com/boltdb/bolt/db.go b/vendor/github.com/boltdb/bolt/db.go new file mode 100644 index 00000000..f352ff14 --- /dev/null +++ b/vendor/github.com/boltdb/bolt/db.go @@ -0,0 +1,1039 @@ +package bolt + +import ( + "errors" + "fmt" + "hash/fnv" + "log" + "os" + "runtime" + "runtime/debug" + "strings" + "sync" + "time" + "unsafe" +) + +// The largest step that can be taken when remapping the mmap. +const maxMmapStep = 1 << 30 // 1GB + +// The data file format version. +const version = 2 + +// Represents a marker value to indicate that a file is a Bolt DB. +const magic uint32 = 0xED0CDAED + +// IgnoreNoSync specifies whether the NoSync field of a DB is ignored when +// syncing changes to a file. This is required as some operating systems, +// such as OpenBSD, do not have a unified buffer cache (UBC) and writes +// must be synchronized using the msync(2) syscall. +const IgnoreNoSync = runtime.GOOS == "openbsd" + +// Default values if not set in a DB instance. +const ( + DefaultMaxBatchSize int = 1000 + DefaultMaxBatchDelay = 10 * time.Millisecond + DefaultAllocSize = 16 * 1024 * 1024 +) + +// default page size for db is set to the OS page size. +var defaultPageSize = os.Getpagesize() + +// DB represents a collection of buckets persisted to a file on disk. +// All data access is performed through transactions which can be obtained through the DB. +// All the functions on DB will return a ErrDatabaseNotOpen if accessed before Open() is called. +type DB struct { + // When enabled, the database will perform a Check() after every commit. + // A panic is issued if the database is in an inconsistent state. This + // flag has a large performance impact so it should only be used for + // debugging purposes. + StrictMode bool + + // Setting the NoSync flag will cause the database to skip fsync() + // calls after each commit. This can be useful when bulk loading data + // into a database and you can restart the bulk load in the event of + // a system failure or database corruption. Do not set this flag for + // normal use. + // + // If the package global IgnoreNoSync constant is true, this value is + // ignored. See the comment on that constant for more details. + // + // THIS IS UNSAFE. PLEASE USE WITH CAUTION. + NoSync bool + + // When true, skips the truncate call when growing the database. + // Setting this to true is only safe on non-ext3/ext4 systems. + // Skipping truncation avoids preallocation of hard drive space and + // bypasses a truncate() and fsync() syscall on remapping. + // + // https://github.com/boltdb/bolt/issues/284 + NoGrowSync bool + + // If you want to read the entire database fast, you can set MmapFlag to + // syscall.MAP_POPULATE on Linux 2.6.23+ for sequential read-ahead. + MmapFlags int + + // MaxBatchSize is the maximum size of a batch. Default value is + // copied from DefaultMaxBatchSize in Open. + // + // If <=0, disables batching. + // + // Do not change concurrently with calls to Batch. + MaxBatchSize int + + // MaxBatchDelay is the maximum delay before a batch starts. + // Default value is copied from DefaultMaxBatchDelay in Open. + // + // If <=0, effectively disables batching. + // + // Do not change concurrently with calls to Batch. + MaxBatchDelay time.Duration + + // AllocSize is the amount of space allocated when the database + // needs to create new pages. This is done to amortize the cost + // of truncate() and fsync() when growing the data file. + AllocSize int + + path string + file *os.File + lockfile *os.File // windows only + dataref []byte // mmap'ed readonly, write throws SEGV + data *[maxMapSize]byte + datasz int + filesz int // current on disk file size + meta0 *meta + meta1 *meta + pageSize int + opened bool + rwtx *Tx + txs []*Tx + freelist *freelist + stats Stats + + pagePool sync.Pool + + batchMu sync.Mutex + batch *batch + + rwlock sync.Mutex // Allows only one writer at a time. + metalock sync.Mutex // Protects meta page access. + mmaplock sync.RWMutex // Protects mmap access during remapping. + statlock sync.RWMutex // Protects stats access. + + ops struct { + writeAt func(b []byte, off int64) (n int, err error) + } + + // Read only mode. + // When true, Update() and Begin(true) return ErrDatabaseReadOnly immediately. + readOnly bool +} + +// Path returns the path to currently open database file. +func (db *DB) Path() string { + return db.path +} + +// GoString returns the Go string representation of the database. +func (db *DB) GoString() string { + return fmt.Sprintf("bolt.DB{path:%q}", db.path) +} + +// String returns the string representation of the database. +func (db *DB) String() string { + return fmt.Sprintf("DB<%q>", db.path) +} + +// Open creates and opens a database at the given path. +// If the file does not exist then it will be created automatically. +// Passing in nil options will cause Bolt to open the database with the default options. +func Open(path string, mode os.FileMode, options *Options) (*DB, error) { + var db = &DB{opened: true} + + // Set default options if no options are provided. + if options == nil { + options = DefaultOptions + } + db.NoGrowSync = options.NoGrowSync + db.MmapFlags = options.MmapFlags + + // Set default values for later DB operations. + db.MaxBatchSize = DefaultMaxBatchSize + db.MaxBatchDelay = DefaultMaxBatchDelay + db.AllocSize = DefaultAllocSize + + flag := os.O_RDWR + if options.ReadOnly { + flag = os.O_RDONLY + db.readOnly = true + } + + // Open data file and separate sync handler for metadata writes. + db.path = path + var err error + if db.file, err = os.OpenFile(db.path, flag|os.O_CREATE, mode); err != nil { + _ = db.close() + return nil, err + } + + // Lock file so that other processes using Bolt in read-write mode cannot + // use the database at the same time. This would cause corruption since + // the two processes would write meta pages and free pages separately. + // The database file is locked exclusively (only one process can grab the lock) + // if !options.ReadOnly. + // The database file is locked using the shared lock (more than one process may + // hold a lock at the same time) otherwise (options.ReadOnly is set). + if err := flock(db, mode, !db.readOnly, options.Timeout); err != nil { + _ = db.close() + return nil, err + } + + // Default values for test hooks + db.ops.writeAt = db.file.WriteAt + + // Initialize the database if it doesn't exist. + if info, err := db.file.Stat(); err != nil { + return nil, err + } else if info.Size() == 0 { + // Initialize new files with meta pages. + if err := db.init(); err != nil { + return nil, err + } + } else { + // Read the first meta page to determine the page size. + var buf [0x1000]byte + if _, err := db.file.ReadAt(buf[:], 0); err == nil { + m := db.pageInBuffer(buf[:], 0).meta() + if err := m.validate(); err != nil { + // If we can't read the page size, we can assume it's the same + // as the OS -- since that's how the page size was chosen in the + // first place. + // + // If the first page is invalid and this OS uses a different + // page size than what the database was created with then we + // are out of luck and cannot access the database. + db.pageSize = os.Getpagesize() + } else { + db.pageSize = int(m.pageSize) + } + } + } + + // Initialize page pool. + db.pagePool = sync.Pool{ + New: func() interface{} { + return make([]byte, db.pageSize) + }, + } + + // Memory map the data file. + if err := db.mmap(options.InitialMmapSize); err != nil { + _ = db.close() + return nil, err + } + + // Read in the freelist. + db.freelist = newFreelist() + db.freelist.read(db.page(db.meta().freelist)) + + // Mark the database as opened and return. + return db, nil +} + +// mmap opens the underlying memory-mapped file and initializes the meta references. +// minsz is the minimum size that the new mmap can be. +func (db *DB) mmap(minsz int) error { + db.mmaplock.Lock() + defer db.mmaplock.Unlock() + + info, err := db.file.Stat() + if err != nil { + return fmt.Errorf("mmap stat error: %s", err) + } else if int(info.Size()) < db.pageSize*2 { + return fmt.Errorf("file size too small") + } + + // Ensure the size is at least the minimum size. + var size = int(info.Size()) + if size < minsz { + size = minsz + } + size, err = db.mmapSize(size) + if err != nil { + return err + } + + // Dereference all mmap references before unmapping. + if db.rwtx != nil { + db.rwtx.root.dereference() + } + + // Unmap existing data before continuing. + if err := db.munmap(); err != nil { + return err + } + + // Memory-map the data file as a byte slice. + if err := mmap(db, size); err != nil { + return err + } + + // Save references to the meta pages. + db.meta0 = db.page(0).meta() + db.meta1 = db.page(1).meta() + + // Validate the meta pages. We only return an error if both meta pages fail + // validation, since meta0 failing validation means that it wasn't saved + // properly -- but we can recover using meta1. And vice-versa. + err0 := db.meta0.validate() + err1 := db.meta1.validate() + if err0 != nil && err1 != nil { + return err0 + } + + return nil +} + +// munmap unmaps the data file from memory. +func (db *DB) munmap() error { + if err := munmap(db); err != nil { + return fmt.Errorf("unmap error: " + err.Error()) + } + return nil +} + +// mmapSize determines the appropriate size for the mmap given the current size +// of the database. The minimum size is 32KB and doubles until it reaches 1GB. +// Returns an error if the new mmap size is greater than the max allowed. +func (db *DB) mmapSize(size int) (int, error) { + // Double the size from 32KB until 1GB. + for i := uint(15); i <= 30; i++ { + if size <= 1< maxMapSize { + return 0, fmt.Errorf("mmap too large") + } + + // If larger than 1GB then grow by 1GB at a time. + sz := int64(size) + if remainder := sz % int64(maxMmapStep); remainder > 0 { + sz += int64(maxMmapStep) - remainder + } + + // Ensure that the mmap size is a multiple of the page size. + // This should always be true since we're incrementing in MBs. + pageSize := int64(db.pageSize) + if (sz % pageSize) != 0 { + sz = ((sz / pageSize) + 1) * pageSize + } + + // If we've exceeded the max size then only grow up to the max size. + if sz > maxMapSize { + sz = maxMapSize + } + + return int(sz), nil +} + +// init creates a new database file and initializes its meta pages. +func (db *DB) init() error { + // Set the page size to the OS page size. + db.pageSize = os.Getpagesize() + + // Create two meta pages on a buffer. + buf := make([]byte, db.pageSize*4) + for i := 0; i < 2; i++ { + p := db.pageInBuffer(buf[:], pgid(i)) + p.id = pgid(i) + p.flags = metaPageFlag + + // Initialize the meta page. + m := p.meta() + m.magic = magic + m.version = version + m.pageSize = uint32(db.pageSize) + m.freelist = 2 + m.root = bucket{root: 3} + m.pgid = 4 + m.txid = txid(i) + m.checksum = m.sum64() + } + + // Write an empty freelist at page 3. + p := db.pageInBuffer(buf[:], pgid(2)) + p.id = pgid(2) + p.flags = freelistPageFlag + p.count = 0 + + // Write an empty leaf page at page 4. + p = db.pageInBuffer(buf[:], pgid(3)) + p.id = pgid(3) + p.flags = leafPageFlag + p.count = 0 + + // Write the buffer to our data file. + if _, err := db.ops.writeAt(buf, 0); err != nil { + return err + } + if err := fdatasync(db); err != nil { + return err + } + + return nil +} + +// Close releases all database resources. +// All transactions must be closed before closing the database. +func (db *DB) Close() error { + db.rwlock.Lock() + defer db.rwlock.Unlock() + + db.metalock.Lock() + defer db.metalock.Unlock() + + db.mmaplock.RLock() + defer db.mmaplock.RUnlock() + + return db.close() +} + +func (db *DB) close() error { + if !db.opened { + return nil + } + + db.opened = false + + db.freelist = nil + + // Clear ops. + db.ops.writeAt = nil + + // Close the mmap. + if err := db.munmap(); err != nil { + return err + } + + // Close file handles. + if db.file != nil { + // No need to unlock read-only file. + if !db.readOnly { + // Unlock the file. + if err := funlock(db); err != nil { + log.Printf("bolt.Close(): funlock error: %s", err) + } + } + + // Close the file descriptor. + if err := db.file.Close(); err != nil { + return fmt.Errorf("db file close: %s", err) + } + db.file = nil + } + + db.path = "" + return nil +} + +// Begin starts a new transaction. +// Multiple read-only transactions can be used concurrently but only one +// write transaction can be used at a time. Starting multiple write transactions +// will cause the calls to block and be serialized until the current write +// transaction finishes. +// +// Transactions should not be dependent on one another. Opening a read +// transaction and a write transaction in the same goroutine can cause the +// writer to deadlock because the database periodically needs to re-mmap itself +// as it grows and it cannot do that while a read transaction is open. +// +// If a long running read transaction (for example, a snapshot transaction) is +// needed, you might want to set DB.InitialMmapSize to a large enough value +// to avoid potential blocking of write transaction. +// +// IMPORTANT: You must close read-only transactions after you are finished or +// else the database will not reclaim old pages. +func (db *DB) Begin(writable bool) (*Tx, error) { + if writable { + return db.beginRWTx() + } + return db.beginTx() +} + +func (db *DB) beginTx() (*Tx, error) { + // Lock the meta pages while we initialize the transaction. We obtain + // the meta lock before the mmap lock because that's the order that the + // write transaction will obtain them. + db.metalock.Lock() + + // Obtain a read-only lock on the mmap. When the mmap is remapped it will + // obtain a write lock so all transactions must finish before it can be + // remapped. + db.mmaplock.RLock() + + // Exit if the database is not open yet. + if !db.opened { + db.mmaplock.RUnlock() + db.metalock.Unlock() + return nil, ErrDatabaseNotOpen + } + + // Create a transaction associated with the database. + t := &Tx{} + t.init(db) + + // Keep track of transaction until it closes. + db.txs = append(db.txs, t) + n := len(db.txs) + + // Unlock the meta pages. + db.metalock.Unlock() + + // Update the transaction stats. + db.statlock.Lock() + db.stats.TxN++ + db.stats.OpenTxN = n + db.statlock.Unlock() + + return t, nil +} + +func (db *DB) beginRWTx() (*Tx, error) { + // If the database was opened with Options.ReadOnly, return an error. + if db.readOnly { + return nil, ErrDatabaseReadOnly + } + + // Obtain writer lock. This is released by the transaction when it closes. + // This enforces only one writer transaction at a time. + db.rwlock.Lock() + + // Once we have the writer lock then we can lock the meta pages so that + // we can set up the transaction. + db.metalock.Lock() + defer db.metalock.Unlock() + + // Exit if the database is not open yet. + if !db.opened { + db.rwlock.Unlock() + return nil, ErrDatabaseNotOpen + } + + // Create a transaction associated with the database. + t := &Tx{writable: true} + t.init(db) + db.rwtx = t + + // Free any pages associated with closed read-only transactions. + var minid txid = 0xFFFFFFFFFFFFFFFF + for _, t := range db.txs { + if t.meta.txid < minid { + minid = t.meta.txid + } + } + if minid > 0 { + db.freelist.release(minid - 1) + } + + return t, nil +} + +// removeTx removes a transaction from the database. +func (db *DB) removeTx(tx *Tx) { + // Release the read lock on the mmap. + db.mmaplock.RUnlock() + + // Use the meta lock to restrict access to the DB object. + db.metalock.Lock() + + // Remove the transaction. + for i, t := range db.txs { + if t == tx { + last := len(db.txs) - 1 + db.txs[i] = db.txs[last] + db.txs[last] = nil + db.txs = db.txs[:last] + break + } + } + n := len(db.txs) + + // Unlock the meta pages. + db.metalock.Unlock() + + // Merge statistics. + db.statlock.Lock() + db.stats.OpenTxN = n + db.stats.TxStats.add(&tx.stats) + db.statlock.Unlock() +} + +// Update executes a function within the context of a read-write managed transaction. +// If no error is returned from the function then the transaction is committed. +// If an error is returned then the entire transaction is rolled back. +// Any error that is returned from the function or returned from the commit is +// returned from the Update() method. +// +// Attempting to manually commit or rollback within the function will cause a panic. +func (db *DB) Update(fn func(*Tx) error) error { + t, err := db.Begin(true) + if err != nil { + return err + } + + // Make sure the transaction rolls back in the event of a panic. + defer func() { + if t.db != nil { + t.rollback() + } + }() + + // Mark as a managed tx so that the inner function cannot manually commit. + t.managed = true + + // If an error is returned from the function then rollback and return error. + err = fn(t) + t.managed = false + if err != nil { + _ = t.Rollback() + return err + } + + return t.Commit() +} + +// View executes a function within the context of a managed read-only transaction. +// Any error that is returned from the function is returned from the View() method. +// +// Attempting to manually rollback within the function will cause a panic. +func (db *DB) View(fn func(*Tx) error) error { + t, err := db.Begin(false) + if err != nil { + return err + } + + // Make sure the transaction rolls back in the event of a panic. + defer func() { + if t.db != nil { + t.rollback() + } + }() + + // Mark as a managed tx so that the inner function cannot manually rollback. + t.managed = true + + // If an error is returned from the function then pass it through. + err = fn(t) + t.managed = false + if err != nil { + _ = t.Rollback() + return err + } + + if err := t.Rollback(); err != nil { + return err + } + + return nil +} + +// Batch calls fn as part of a batch. It behaves similar to Update, +// except: +// +// 1. concurrent Batch calls can be combined into a single Bolt +// transaction. +// +// 2. the function passed to Batch may be called multiple times, +// regardless of whether it returns error or not. +// +// This means that Batch function side effects must be idempotent and +// take permanent effect only after a successful return is seen in +// caller. +// +// The maximum batch size and delay can be adjusted with DB.MaxBatchSize +// and DB.MaxBatchDelay, respectively. +// +// Batch is only useful when there are multiple goroutines calling it. +func (db *DB) Batch(fn func(*Tx) error) error { + errCh := make(chan error, 1) + + db.batchMu.Lock() + if (db.batch == nil) || (db.batch != nil && len(db.batch.calls) >= db.MaxBatchSize) { + // There is no existing batch, or the existing batch is full; start a new one. + db.batch = &batch{ + db: db, + } + db.batch.timer = time.AfterFunc(db.MaxBatchDelay, db.batch.trigger) + } + db.batch.calls = append(db.batch.calls, call{fn: fn, err: errCh}) + if len(db.batch.calls) >= db.MaxBatchSize { + // wake up batch, it's ready to run + go db.batch.trigger() + } + db.batchMu.Unlock() + + err := <-errCh + if err == trySolo { + err = db.Update(fn) + } + return err +} + +type call struct { + fn func(*Tx) error + err chan<- error +} + +type batch struct { + db *DB + timer *time.Timer + start sync.Once + calls []call +} + +// trigger runs the batch if it hasn't already been run. +func (b *batch) trigger() { + b.start.Do(b.run) +} + +// run performs the transactions in the batch and communicates results +// back to DB.Batch. +func (b *batch) run() { + b.db.batchMu.Lock() + b.timer.Stop() + // Make sure no new work is added to this batch, but don't break + // other batches. + if b.db.batch == b { + b.db.batch = nil + } + b.db.batchMu.Unlock() + +retry: + for len(b.calls) > 0 { + var failIdx = -1 + err := b.db.Update(func(tx *Tx) error { + for i, c := range b.calls { + if err := safelyCall(c.fn, tx); err != nil { + failIdx = i + return err + } + } + return nil + }) + + if failIdx >= 0 { + // take the failing transaction out of the batch. it's + // safe to shorten b.calls here because db.batch no longer + // points to us, and we hold the mutex anyway. + c := b.calls[failIdx] + b.calls[failIdx], b.calls = b.calls[len(b.calls)-1], b.calls[:len(b.calls)-1] + // tell the submitter re-run it solo, continue with the rest of the batch + c.err <- trySolo + continue retry + } + + // pass success, or bolt internal errors, to all callers + for _, c := range b.calls { + if c.err != nil { + c.err <- err + } + } + break retry + } +} + +// trySolo is a special sentinel error value used for signaling that a +// transaction function should be re-run. It should never be seen by +// callers. +var trySolo = errors.New("batch function returned an error and should be re-run solo") + +type panicked struct { + reason interface{} +} + +func (p panicked) Error() string { + if err, ok := p.reason.(error); ok { + return err.Error() + } + return fmt.Sprintf("panic: %v", p.reason) +} + +func safelyCall(fn func(*Tx) error, tx *Tx) (err error) { + defer func() { + if p := recover(); p != nil { + err = panicked{p} + } + }() + return fn(tx) +} + +// Sync executes fdatasync() against the database file handle. +// +// This is not necessary under normal operation, however, if you use NoSync +// then it allows you to force the database file to sync against the disk. +func (db *DB) Sync() error { return fdatasync(db) } + +// Stats retrieves ongoing performance stats for the database. +// This is only updated when a transaction closes. +func (db *DB) Stats() Stats { + db.statlock.RLock() + defer db.statlock.RUnlock() + return db.stats +} + +// This is for internal access to the raw data bytes from the C cursor, use +// carefully, or not at all. +func (db *DB) Info() *Info { + return &Info{uintptr(unsafe.Pointer(&db.data[0])), db.pageSize} +} + +// page retrieves a page reference from the mmap based on the current page size. +func (db *DB) page(id pgid) *page { + pos := id * pgid(db.pageSize) + return (*page)(unsafe.Pointer(&db.data[pos])) +} + +// pageInBuffer retrieves a page reference from a given byte array based on the current page size. +func (db *DB) pageInBuffer(b []byte, id pgid) *page { + return (*page)(unsafe.Pointer(&b[id*pgid(db.pageSize)])) +} + +// meta retrieves the current meta page reference. +func (db *DB) meta() *meta { + // We have to return the meta with the highest txid which doesn't fail + // validation. Otherwise, we can cause errors when in fact the database is + // in a consistent state. metaA is the one with the higher txid. + metaA := db.meta0 + metaB := db.meta1 + if db.meta1.txid > db.meta0.txid { + metaA = db.meta1 + metaB = db.meta0 + } + + // Use higher meta page if valid. Otherwise fallback to previous, if valid. + if err := metaA.validate(); err == nil { + return metaA + } else if err := metaB.validate(); err == nil { + return metaB + } + + // This should never be reached, because both meta1 and meta0 were validated + // on mmap() and we do fsync() on every write. + panic("bolt.DB.meta(): invalid meta pages") +} + +// allocate returns a contiguous block of memory starting at a given page. +func (db *DB) allocate(count int) (*page, error) { + // Allocate a temporary buffer for the page. + var buf []byte + if count == 1 { + buf = db.pagePool.Get().([]byte) + } else { + buf = make([]byte, count*db.pageSize) + } + p := (*page)(unsafe.Pointer(&buf[0])) + p.overflow = uint32(count - 1) + + // Use pages from the freelist if they are available. + if p.id = db.freelist.allocate(count); p.id != 0 { + return p, nil + } + + // Resize mmap() if we're at the end. + p.id = db.rwtx.meta.pgid + var minsz = int((p.id+pgid(count))+1) * db.pageSize + if minsz >= db.datasz { + if err := db.mmap(minsz); err != nil { + return nil, fmt.Errorf("mmap allocate error: %s", err) + } + } + + // Move the page id high water mark. + db.rwtx.meta.pgid += pgid(count) + + return p, nil +} + +// grow grows the size of the database to the given sz. +func (db *DB) grow(sz int) error { + // Ignore if the new size is less than available file size. + if sz <= db.filesz { + return nil + } + + // If the data is smaller than the alloc size then only allocate what's needed. + // Once it goes over the allocation size then allocate in chunks. + if db.datasz < db.AllocSize { + sz = db.datasz + } else { + sz += db.AllocSize + } + + // Truncate and fsync to ensure file size metadata is flushed. + // https://github.com/boltdb/bolt/issues/284 + if !db.NoGrowSync && !db.readOnly { + if runtime.GOOS != "windows" { + if err := db.file.Truncate(int64(sz)); err != nil { + return fmt.Errorf("file resize error: %s", err) + } + } + if err := db.file.Sync(); err != nil { + return fmt.Errorf("file sync error: %s", err) + } + } + + db.filesz = sz + return nil +} + +func (db *DB) IsReadOnly() bool { + return db.readOnly +} + +// Options represents the options that can be set when opening a database. +type Options struct { + // Timeout is the amount of time to wait to obtain a file lock. + // When set to zero it will wait indefinitely. This option is only + // available on Darwin and Linux. + Timeout time.Duration + + // Sets the DB.NoGrowSync flag before memory mapping the file. + NoGrowSync bool + + // Open database in read-only mode. Uses flock(..., LOCK_SH |LOCK_NB) to + // grab a shared lock (UNIX). + ReadOnly bool + + // Sets the DB.MmapFlags flag before memory mapping the file. + MmapFlags int + + // InitialMmapSize is the initial mmap size of the database + // in bytes. Read transactions won't block write transaction + // if the InitialMmapSize is large enough to hold database mmap + // size. (See DB.Begin for more information) + // + // If <=0, the initial map size is 0. + // If initialMmapSize is smaller than the previous database size, + // it takes no effect. + InitialMmapSize int +} + +// DefaultOptions represent the options used if nil options are passed into Open(). +// No timeout is used which will cause Bolt to wait indefinitely for a lock. +var DefaultOptions = &Options{ + Timeout: 0, + NoGrowSync: false, +} + +// Stats represents statistics about the database. +type Stats struct { + // Freelist stats + FreePageN int // total number of free pages on the freelist + PendingPageN int // total number of pending pages on the freelist + FreeAlloc int // total bytes allocated in free pages + FreelistInuse int // total bytes used by the freelist + + // Transaction stats + TxN int // total number of started read transactions + OpenTxN int // number of currently open read transactions + + TxStats TxStats // global, ongoing stats. +} + +// Sub calculates and returns the difference between two sets of database stats. +// This is useful when obtaining stats at two different points and time and +// you need the performance counters that occurred within that time span. +func (s *Stats) Sub(other *Stats) Stats { + if other == nil { + return *s + } + var diff Stats + diff.FreePageN = s.FreePageN + diff.PendingPageN = s.PendingPageN + diff.FreeAlloc = s.FreeAlloc + diff.FreelistInuse = s.FreelistInuse + diff.TxN = s.TxN - other.TxN + diff.TxStats = s.TxStats.Sub(&other.TxStats) + return diff +} + +func (s *Stats) add(other *Stats) { + s.TxStats.add(&other.TxStats) +} + +type Info struct { + Data uintptr + PageSize int +} + +type meta struct { + magic uint32 + version uint32 + pageSize uint32 + flags uint32 + root bucket + freelist pgid + pgid pgid + txid txid + checksum uint64 +} + +// validate checks the marker bytes and version of the meta page to ensure it matches this binary. +func (m *meta) validate() error { + if m.magic != magic { + return ErrInvalid + } else if m.version != version { + return ErrVersionMismatch + } else if m.checksum != 0 && m.checksum != m.sum64() { + return ErrChecksum + } + return nil +} + +// copy copies one meta object to another. +func (m *meta) copy(dest *meta) { + *dest = *m +} + +// write writes the meta onto a page. +func (m *meta) write(p *page) { + if m.root.root >= m.pgid { + panic(fmt.Sprintf("root bucket pgid (%d) above high water mark (%d)", m.root.root, m.pgid)) + } else if m.freelist >= m.pgid { + panic(fmt.Sprintf("freelist pgid (%d) above high water mark (%d)", m.freelist, m.pgid)) + } + + // Page id is either going to be 0 or 1 which we can determine by the transaction ID. + p.id = pgid(m.txid % 2) + p.flags |= metaPageFlag + + // Calculate the checksum. + m.checksum = m.sum64() + + m.copy(p.meta()) +} + +// generates the checksum for the meta. +func (m *meta) sum64() uint64 { + var h = fnv.New64a() + _, _ = h.Write((*[unsafe.Offsetof(meta{}.checksum)]byte)(unsafe.Pointer(m))[:]) + return h.Sum64() +} + +// _assert will panic with a given formatted message if the given condition is false. +func _assert(condition bool, msg string, v ...interface{}) { + if !condition { + panic(fmt.Sprintf("assertion failed: "+msg, v...)) + } +} + +func warn(v ...interface{}) { fmt.Fprintln(os.Stderr, v...) } +func warnf(msg string, v ...interface{}) { fmt.Fprintf(os.Stderr, msg+"\n", v...) } + +func printstack() { + stack := strings.Join(strings.Split(string(debug.Stack()), "\n")[2:], "\n") + fmt.Fprintln(os.Stderr, stack) +} diff --git a/vendor/github.com/boltdb/bolt/db_test.go b/vendor/github.com/boltdb/bolt/db_test.go new file mode 100644 index 00000000..3034d4f4 --- /dev/null +++ b/vendor/github.com/boltdb/bolt/db_test.go @@ -0,0 +1,1545 @@ +package bolt_test + +import ( + "bytes" + "encoding/binary" + "errors" + "flag" + "fmt" + "hash/fnv" + "io/ioutil" + "log" + "os" + "path/filepath" + "regexp" + "sort" + "strings" + "sync" + "testing" + "time" + "unsafe" + + "github.com/boltdb/bolt" +) + +var statsFlag = flag.Bool("stats", false, "show performance stats") + +// version is the data file format version. +const version = 2 + +// magic is the marker value to indicate that a file is a Bolt DB. +const magic uint32 = 0xED0CDAED + +// pageSize is the size of one page in the data file. +const pageSize = 4096 + +// pageHeaderSize is the size of a page header. +const pageHeaderSize = 16 + +// meta represents a simplified version of a database meta page for testing. +type meta struct { + magic uint32 + version uint32 + _ uint32 + _ uint32 + _ [16]byte + _ uint64 + pgid uint64 + _ uint64 + checksum uint64 +} + +// Ensure that a database can be opened without error. +func TestOpen(t *testing.T) { + path := tempfile() + db, err := bolt.Open(path, 0666, nil) + if err != nil { + t.Fatal(err) + } else if db == nil { + t.Fatal("expected db") + } + + if s := db.Path(); s != path { + t.Fatalf("unexpected path: %s", s) + } + + if err := db.Close(); err != nil { + t.Fatal(err) + } +} + +// Ensure that opening a database with a blank path returns an error. +func TestOpen_ErrPathRequired(t *testing.T) { + _, err := bolt.Open("", 0666, nil) + if err == nil { + t.Fatalf("expected error") + } +} + +// Ensure that opening a database with a bad path returns an error. +func TestOpen_ErrNotExists(t *testing.T) { + _, err := bolt.Open(filepath.Join(tempfile(), "bad-path"), 0666, nil) + if err == nil { + t.Fatal("expected error") + } +} + +// Ensure that opening a file that is not a Bolt database returns ErrInvalid. +func TestOpen_ErrInvalid(t *testing.T) { + path := tempfile() + + f, err := os.Create(path) + if err != nil { + t.Fatal(err) + } + if _, err := fmt.Fprintln(f, "this is not a bolt database"); err != nil { + t.Fatal(err) + } + if err := f.Close(); err != nil { + t.Fatal(err) + } + defer os.Remove(path) + + if _, err := bolt.Open(path, 0666, nil); err != bolt.ErrInvalid { + t.Fatalf("unexpected error: %s", err) + } +} + +// Ensure that opening a file with two invalid versions returns ErrVersionMismatch. +func TestOpen_ErrVersionMismatch(t *testing.T) { + if pageSize != os.Getpagesize() { + t.Skip("page size mismatch") + } + + // Create empty database. + db := MustOpenDB() + path := db.Path() + defer db.MustClose() + + // Close database. + if err := db.DB.Close(); err != nil { + t.Fatal(err) + } + + // Read data file. + buf, err := ioutil.ReadFile(path) + if err != nil { + t.Fatal(err) + } + + // Rewrite meta pages. + meta0 := (*meta)(unsafe.Pointer(&buf[pageHeaderSize])) + meta0.version++ + meta1 := (*meta)(unsafe.Pointer(&buf[pageSize+pageHeaderSize])) + meta1.version++ + if err := ioutil.WriteFile(path, buf, 0666); err != nil { + t.Fatal(err) + } + + // Reopen data file. + if _, err := bolt.Open(path, 0666, nil); err != bolt.ErrVersionMismatch { + t.Fatalf("unexpected error: %s", err) + } +} + +// Ensure that opening a file with two invalid checksums returns ErrChecksum. +func TestOpen_ErrChecksum(t *testing.T) { + if pageSize != os.Getpagesize() { + t.Skip("page size mismatch") + } + + // Create empty database. + db := MustOpenDB() + path := db.Path() + defer db.MustClose() + + // Close database. + if err := db.DB.Close(); err != nil { + t.Fatal(err) + } + + // Read data file. + buf, err := ioutil.ReadFile(path) + if err != nil { + t.Fatal(err) + } + + // Rewrite meta pages. + meta0 := (*meta)(unsafe.Pointer(&buf[pageHeaderSize])) + meta0.pgid++ + meta1 := (*meta)(unsafe.Pointer(&buf[pageSize+pageHeaderSize])) + meta1.pgid++ + if err := ioutil.WriteFile(path, buf, 0666); err != nil { + t.Fatal(err) + } + + // Reopen data file. + if _, err := bolt.Open(path, 0666, nil); err != bolt.ErrChecksum { + t.Fatalf("unexpected error: %s", err) + } +} + +// Ensure that opening a database does not increase its size. +// https://github.com/boltdb/bolt/issues/291 +func TestOpen_Size(t *testing.T) { + // Open a data file. + db := MustOpenDB() + path := db.Path() + defer db.MustClose() + + pagesize := db.Info().PageSize + + // Insert until we get above the minimum 4MB size. + if err := db.Update(func(tx *bolt.Tx) error { + b, _ := tx.CreateBucketIfNotExists([]byte("data")) + for i := 0; i < 10000; i++ { + if err := b.Put([]byte(fmt.Sprintf("%04d", i)), make([]byte, 1000)); err != nil { + t.Fatal(err) + } + } + return nil + }); err != nil { + t.Fatal(err) + } + + // Close database and grab the size. + if err := db.DB.Close(); err != nil { + t.Fatal(err) + } + sz := fileSize(path) + if sz == 0 { + t.Fatalf("unexpected new file size: %d", sz) + } + + // Reopen database, update, and check size again. + db0, err := bolt.Open(path, 0666, nil) + if err != nil { + t.Fatal(err) + } + if err := db0.Update(func(tx *bolt.Tx) error { + if err := tx.Bucket([]byte("data")).Put([]byte{0}, []byte{0}); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + if err := db0.Close(); err != nil { + t.Fatal(err) + } + newSz := fileSize(path) + if newSz == 0 { + t.Fatalf("unexpected new file size: %d", newSz) + } + + // Compare the original size with the new size. + // db size might increase by a few page sizes due to the new small update. + if sz < newSz-5*int64(pagesize) { + t.Fatalf("unexpected file growth: %d => %d", sz, newSz) + } +} + +// Ensure that opening a database beyond the max step size does not increase its size. +// https://github.com/boltdb/bolt/issues/303 +func TestOpen_Size_Large(t *testing.T) { + if testing.Short() { + t.Skip("short mode") + } + + // Open a data file. + db := MustOpenDB() + path := db.Path() + defer db.MustClose() + + pagesize := db.Info().PageSize + + // Insert until we get above the minimum 4MB size. + var index uint64 + for i := 0; i < 10000; i++ { + if err := db.Update(func(tx *bolt.Tx) error { + b, _ := tx.CreateBucketIfNotExists([]byte("data")) + for j := 0; j < 1000; j++ { + if err := b.Put(u64tob(index), make([]byte, 50)); err != nil { + t.Fatal(err) + } + index++ + } + return nil + }); err != nil { + t.Fatal(err) + } + } + + // Close database and grab the size. + if err := db.DB.Close(); err != nil { + t.Fatal(err) + } + sz := fileSize(path) + if sz == 0 { + t.Fatalf("unexpected new file size: %d", sz) + } else if sz < (1 << 30) { + t.Fatalf("expected larger initial size: %d", sz) + } + + // Reopen database, update, and check size again. + db0, err := bolt.Open(path, 0666, nil) + if err != nil { + t.Fatal(err) + } + if err := db0.Update(func(tx *bolt.Tx) error { + return tx.Bucket([]byte("data")).Put([]byte{0}, []byte{0}) + }); err != nil { + t.Fatal(err) + } + if err := db0.Close(); err != nil { + t.Fatal(err) + } + + newSz := fileSize(path) + if newSz == 0 { + t.Fatalf("unexpected new file size: %d", newSz) + } + + // Compare the original size with the new size. + // db size might increase by a few page sizes due to the new small update. + if sz < newSz-5*int64(pagesize) { + t.Fatalf("unexpected file growth: %d => %d", sz, newSz) + } +} + +// Ensure that a re-opened database is consistent. +func TestOpen_Check(t *testing.T) { + path := tempfile() + + db, err := bolt.Open(path, 0666, nil) + if err != nil { + t.Fatal(err) + } + if err := db.View(func(tx *bolt.Tx) error { return <-tx.Check() }); err != nil { + t.Fatal(err) + } + if err := db.Close(); err != nil { + t.Fatal(err) + } + + db, err = bolt.Open(path, 0666, nil) + if err != nil { + t.Fatal(err) + } + if err := db.View(func(tx *bolt.Tx) error { return <-tx.Check() }); err != nil { + t.Fatal(err) + } + if err := db.Close(); err != nil { + t.Fatal(err) + } +} + +// Ensure that write errors to the meta file handler during initialization are returned. +func TestOpen_MetaInitWriteError(t *testing.T) { + t.Skip("pending") +} + +// Ensure that a database that is too small returns an error. +func TestOpen_FileTooSmall(t *testing.T) { + path := tempfile() + + db, err := bolt.Open(path, 0666, nil) + if err != nil { + t.Fatal(err) + } + if err := db.Close(); err != nil { + t.Fatal(err) + } + + // corrupt the database + if err := os.Truncate(path, int64(os.Getpagesize())); err != nil { + t.Fatal(err) + } + + db, err = bolt.Open(path, 0666, nil) + if err == nil || err.Error() != "file size too small" { + t.Fatalf("unexpected error: %s", err) + } +} + +// TestDB_Open_InitialMmapSize tests if having InitialMmapSize large enough +// to hold data from concurrent write transaction resolves the issue that +// read transaction blocks the write transaction and causes deadlock. +// This is a very hacky test since the mmap size is not exposed. +func TestDB_Open_InitialMmapSize(t *testing.T) { + path := tempfile() + defer os.Remove(path) + + initMmapSize := 1 << 31 // 2GB + testWriteSize := 1 << 27 // 134MB + + db, err := bolt.Open(path, 0666, &bolt.Options{InitialMmapSize: initMmapSize}) + if err != nil { + t.Fatal(err) + } + + // create a long-running read transaction + // that never gets closed while writing + rtx, err := db.Begin(false) + if err != nil { + t.Fatal(err) + } + + // create a write transaction + wtx, err := db.Begin(true) + if err != nil { + t.Fatal(err) + } + + b, err := wtx.CreateBucket([]byte("test")) + if err != nil { + t.Fatal(err) + } + + // and commit a large write + err = b.Put([]byte("foo"), make([]byte, testWriteSize)) + if err != nil { + t.Fatal(err) + } + + done := make(chan struct{}) + + go func() { + if err := wtx.Commit(); err != nil { + t.Fatal(err) + } + done <- struct{}{} + }() + + select { + case <-time.After(5 * time.Second): + t.Errorf("unexpected that the reader blocks writer") + case <-done: + } + + if err := rtx.Rollback(); err != nil { + t.Fatal(err) + } +} + +// Ensure that a database cannot open a transaction when it's not open. +func TestDB_Begin_ErrDatabaseNotOpen(t *testing.T) { + var db bolt.DB + if _, err := db.Begin(false); err != bolt.ErrDatabaseNotOpen { + t.Fatalf("unexpected error: %s", err) + } +} + +// Ensure that a read-write transaction can be retrieved. +func TestDB_BeginRW(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + tx, err := db.Begin(true) + if err != nil { + t.Fatal(err) + } else if tx == nil { + t.Fatal("expected tx") + } + + if tx.DB() != db.DB { + t.Fatal("unexpected tx database") + } else if !tx.Writable() { + t.Fatal("expected writable tx") + } + + if err := tx.Commit(); err != nil { + t.Fatal(err) + } +} + +// Ensure that opening a transaction while the DB is closed returns an error. +func TestDB_BeginRW_Closed(t *testing.T) { + var db bolt.DB + if _, err := db.Begin(true); err != bolt.ErrDatabaseNotOpen { + t.Fatalf("unexpected error: %s", err) + } +} + +func TestDB_Close_PendingTx_RW(t *testing.T) { testDB_Close_PendingTx(t, true) } +func TestDB_Close_PendingTx_RO(t *testing.T) { testDB_Close_PendingTx(t, false) } + +// Ensure that a database cannot close while transactions are open. +func testDB_Close_PendingTx(t *testing.T, writable bool) { + db := MustOpenDB() + defer db.MustClose() + + // Start transaction. + tx, err := db.Begin(true) + if err != nil { + t.Fatal(err) + } + + // Open update in separate goroutine. + done := make(chan struct{}) + go func() { + if err := db.Close(); err != nil { + t.Fatal(err) + } + close(done) + }() + + // Ensure database hasn't closed. + time.Sleep(100 * time.Millisecond) + select { + case <-done: + t.Fatal("database closed too early") + default: + } + + // Commit transaction. + if err := tx.Commit(); err != nil { + t.Fatal(err) + } + + // Ensure database closed now. + time.Sleep(100 * time.Millisecond) + select { + case <-done: + default: + t.Fatal("database did not close") + } +} + +// Ensure a database can provide a transactional block. +func TestDB_Update(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("foo"), []byte("bar")); err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("baz"), []byte("bat")); err != nil { + t.Fatal(err) + } + if err := b.Delete([]byte("foo")); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + if err := db.View(func(tx *bolt.Tx) error { + b := tx.Bucket([]byte("widgets")) + if v := b.Get([]byte("foo")); v != nil { + t.Fatalf("expected nil value, got: %v", v) + } + if v := b.Get([]byte("baz")); !bytes.Equal(v, []byte("bat")) { + t.Fatalf("unexpected value: %v", v) + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure a closed database returns an error while running a transaction block +func TestDB_Update_Closed(t *testing.T) { + var db bolt.DB + if err := db.Update(func(tx *bolt.Tx) error { + if _, err := tx.CreateBucket([]byte("widgets")); err != nil { + t.Fatal(err) + } + return nil + }); err != bolt.ErrDatabaseNotOpen { + t.Fatalf("unexpected error: %s", err) + } +} + +// Ensure a panic occurs while trying to commit a managed transaction. +func TestDB_Update_ManualCommit(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + var panicked bool + if err := db.Update(func(tx *bolt.Tx) error { + func() { + defer func() { + if r := recover(); r != nil { + panicked = true + } + }() + + if err := tx.Commit(); err != nil { + t.Fatal(err) + } + }() + return nil + }); err != nil { + t.Fatal(err) + } else if !panicked { + t.Fatal("expected panic") + } +} + +// Ensure a panic occurs while trying to rollback a managed transaction. +func TestDB_Update_ManualRollback(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + var panicked bool + if err := db.Update(func(tx *bolt.Tx) error { + func() { + defer func() { + if r := recover(); r != nil { + panicked = true + } + }() + + if err := tx.Rollback(); err != nil { + t.Fatal(err) + } + }() + return nil + }); err != nil { + t.Fatal(err) + } else if !panicked { + t.Fatal("expected panic") + } +} + +// Ensure a panic occurs while trying to commit a managed transaction. +func TestDB_View_ManualCommit(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + var panicked bool + if err := db.View(func(tx *bolt.Tx) error { + func() { + defer func() { + if r := recover(); r != nil { + panicked = true + } + }() + + if err := tx.Commit(); err != nil { + t.Fatal(err) + } + }() + return nil + }); err != nil { + t.Fatal(err) + } else if !panicked { + t.Fatal("expected panic") + } +} + +// Ensure a panic occurs while trying to rollback a managed transaction. +func TestDB_View_ManualRollback(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + var panicked bool + if err := db.View(func(tx *bolt.Tx) error { + func() { + defer func() { + if r := recover(); r != nil { + panicked = true + } + }() + + if err := tx.Rollback(); err != nil { + t.Fatal(err) + } + }() + return nil + }); err != nil { + t.Fatal(err) + } else if !panicked { + t.Fatal("expected panic") + } +} + +// Ensure a write transaction that panics does not hold open locks. +func TestDB_Update_Panic(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + // Panic during update but recover. + func() { + defer func() { + if r := recover(); r != nil { + t.Log("recover: update", r) + } + }() + + if err := db.Update(func(tx *bolt.Tx) error { + if _, err := tx.CreateBucket([]byte("widgets")); err != nil { + t.Fatal(err) + } + panic("omg") + }); err != nil { + t.Fatal(err) + } + }() + + // Verify we can update again. + if err := db.Update(func(tx *bolt.Tx) error { + if _, err := tx.CreateBucket([]byte("widgets")); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + + // Verify that our change persisted. + if err := db.Update(func(tx *bolt.Tx) error { + if tx.Bucket([]byte("widgets")) == nil { + t.Fatal("expected bucket") + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure a database can return an error through a read-only transactional block. +func TestDB_View_Error(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + if err := db.View(func(tx *bolt.Tx) error { + return errors.New("xxx") + }); err == nil || err.Error() != "xxx" { + t.Fatalf("unexpected error: %s", err) + } +} + +// Ensure a read transaction that panics does not hold open locks. +func TestDB_View_Panic(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + if err := db.Update(func(tx *bolt.Tx) error { + if _, err := tx.CreateBucket([]byte("widgets")); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + + // Panic during view transaction but recover. + func() { + defer func() { + if r := recover(); r != nil { + t.Log("recover: view", r) + } + }() + + if err := db.View(func(tx *bolt.Tx) error { + if tx.Bucket([]byte("widgets")) == nil { + t.Fatal("expected bucket") + } + panic("omg") + }); err != nil { + t.Fatal(err) + } + }() + + // Verify that we can still use read transactions. + if err := db.View(func(tx *bolt.Tx) error { + if tx.Bucket([]byte("widgets")) == nil { + t.Fatal("expected bucket") + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that DB stats can be returned. +func TestDB_Stats(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + if err := db.Update(func(tx *bolt.Tx) error { + _, err := tx.CreateBucket([]byte("widgets")) + return err + }); err != nil { + t.Fatal(err) + } + + stats := db.Stats() + if stats.TxStats.PageCount != 2 { + t.Fatalf("unexpected TxStats.PageCount: %d", stats.TxStats.PageCount) + } else if stats.FreePageN != 0 { + t.Fatalf("unexpected FreePageN != 0: %d", stats.FreePageN) + } else if stats.PendingPageN != 2 { + t.Fatalf("unexpected PendingPageN != 2: %d", stats.PendingPageN) + } +} + +// Ensure that database pages are in expected order and type. +func TestDB_Consistency(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + if err := db.Update(func(tx *bolt.Tx) error { + _, err := tx.CreateBucket([]byte("widgets")) + return err + }); err != nil { + t.Fatal(err) + } + + for i := 0; i < 10; i++ { + if err := db.Update(func(tx *bolt.Tx) error { + if err := tx.Bucket([]byte("widgets")).Put([]byte("foo"), []byte("bar")); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + } + + if err := db.Update(func(tx *bolt.Tx) error { + if p, _ := tx.Page(0); p == nil { + t.Fatal("expected page") + } else if p.Type != "meta" { + t.Fatalf("unexpected page type: %s", p.Type) + } + + if p, _ := tx.Page(1); p == nil { + t.Fatal("expected page") + } else if p.Type != "meta" { + t.Fatalf("unexpected page type: %s", p.Type) + } + + if p, _ := tx.Page(2); p == nil { + t.Fatal("expected page") + } else if p.Type != "free" { + t.Fatalf("unexpected page type: %s", p.Type) + } + + if p, _ := tx.Page(3); p == nil { + t.Fatal("expected page") + } else if p.Type != "free" { + t.Fatalf("unexpected page type: %s", p.Type) + } + + if p, _ := tx.Page(4); p == nil { + t.Fatal("expected page") + } else if p.Type != "leaf" { + t.Fatalf("unexpected page type: %s", p.Type) + } + + if p, _ := tx.Page(5); p == nil { + t.Fatal("expected page") + } else if p.Type != "freelist" { + t.Fatalf("unexpected page type: %s", p.Type) + } + + if p, _ := tx.Page(6); p != nil { + t.Fatal("unexpected page") + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that DB stats can be subtracted from one another. +func TestDBStats_Sub(t *testing.T) { + var a, b bolt.Stats + a.TxStats.PageCount = 3 + a.FreePageN = 4 + b.TxStats.PageCount = 10 + b.FreePageN = 14 + diff := b.Sub(&a) + if diff.TxStats.PageCount != 7 { + t.Fatalf("unexpected TxStats.PageCount: %d", diff.TxStats.PageCount) + } + + // free page stats are copied from the receiver and not subtracted + if diff.FreePageN != 14 { + t.Fatalf("unexpected FreePageN: %d", diff.FreePageN) + } +} + +// Ensure two functions can perform updates in a single batch. +func TestDB_Batch(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + if err := db.Update(func(tx *bolt.Tx) error { + if _, err := tx.CreateBucket([]byte("widgets")); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + + // Iterate over multiple updates in separate goroutines. + n := 2 + ch := make(chan error) + for i := 0; i < n; i++ { + go func(i int) { + ch <- db.Batch(func(tx *bolt.Tx) error { + return tx.Bucket([]byte("widgets")).Put(u64tob(uint64(i)), []byte{}) + }) + }(i) + } + + // Check all responses to make sure there's no error. + for i := 0; i < n; i++ { + if err := <-ch; err != nil { + t.Fatal(err) + } + } + + // Ensure data is correct. + if err := db.View(func(tx *bolt.Tx) error { + b := tx.Bucket([]byte("widgets")) + for i := 0; i < n; i++ { + if v := b.Get(u64tob(uint64(i))); v == nil { + t.Errorf("key not found: %d", i) + } + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +func TestDB_Batch_Panic(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + var sentinel int + var bork = &sentinel + var problem interface{} + var err error + + // Execute a function inside a batch that panics. + func() { + defer func() { + if p := recover(); p != nil { + problem = p + } + }() + err = db.Batch(func(tx *bolt.Tx) error { + panic(bork) + }) + }() + + // Verify there is no error. + if g, e := err, error(nil); g != e { + t.Fatalf("wrong error: %v != %v", g, e) + } + // Verify the panic was captured. + if g, e := problem, bork; g != e { + t.Fatalf("wrong error: %v != %v", g, e) + } +} + +func TestDB_BatchFull(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + if err := db.Update(func(tx *bolt.Tx) error { + _, err := tx.CreateBucket([]byte("widgets")) + return err + }); err != nil { + t.Fatal(err) + } + + const size = 3 + // buffered so we never leak goroutines + ch := make(chan error, size) + put := func(i int) { + ch <- db.Batch(func(tx *bolt.Tx) error { + return tx.Bucket([]byte("widgets")).Put(u64tob(uint64(i)), []byte{}) + }) + } + + db.MaxBatchSize = size + // high enough to never trigger here + db.MaxBatchDelay = 1 * time.Hour + + go put(1) + go put(2) + + // Give the batch a chance to exhibit bugs. + time.Sleep(10 * time.Millisecond) + + // not triggered yet + select { + case <-ch: + t.Fatalf("batch triggered too early") + default: + } + + go put(3) + + // Check all responses to make sure there's no error. + for i := 0; i < size; i++ { + if err := <-ch; err != nil { + t.Fatal(err) + } + } + + // Ensure data is correct. + if err := db.View(func(tx *bolt.Tx) error { + b := tx.Bucket([]byte("widgets")) + for i := 1; i <= size; i++ { + if v := b.Get(u64tob(uint64(i))); v == nil { + t.Errorf("key not found: %d", i) + } + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +func TestDB_BatchTime(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + if err := db.Update(func(tx *bolt.Tx) error { + _, err := tx.CreateBucket([]byte("widgets")) + return err + }); err != nil { + t.Fatal(err) + } + + const size = 1 + // buffered so we never leak goroutines + ch := make(chan error, size) + put := func(i int) { + ch <- db.Batch(func(tx *bolt.Tx) error { + return tx.Bucket([]byte("widgets")).Put(u64tob(uint64(i)), []byte{}) + }) + } + + db.MaxBatchSize = 1000 + db.MaxBatchDelay = 0 + + go put(1) + + // Batch must trigger by time alone. + + // Check all responses to make sure there's no error. + for i := 0; i < size; i++ { + if err := <-ch; err != nil { + t.Fatal(err) + } + } + + // Ensure data is correct. + if err := db.View(func(tx *bolt.Tx) error { + b := tx.Bucket([]byte("widgets")) + for i := 1; i <= size; i++ { + if v := b.Get(u64tob(uint64(i))); v == nil { + t.Errorf("key not found: %d", i) + } + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +func ExampleDB_Update() { + // Open the database. + db, err := bolt.Open(tempfile(), 0666, nil) + if err != nil { + log.Fatal(err) + } + defer os.Remove(db.Path()) + + // Execute several commands within a read-write transaction. + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + return err + } + if err := b.Put([]byte("foo"), []byte("bar")); err != nil { + return err + } + return nil + }); err != nil { + log.Fatal(err) + } + + // Read the value back from a separate read-only transaction. + if err := db.View(func(tx *bolt.Tx) error { + value := tx.Bucket([]byte("widgets")).Get([]byte("foo")) + fmt.Printf("The value of 'foo' is: %s\n", value) + return nil + }); err != nil { + log.Fatal(err) + } + + // Close database to release the file lock. + if err := db.Close(); err != nil { + log.Fatal(err) + } + + // Output: + // The value of 'foo' is: bar +} + +func ExampleDB_View() { + // Open the database. + db, err := bolt.Open(tempfile(), 0666, nil) + if err != nil { + log.Fatal(err) + } + defer os.Remove(db.Path()) + + // Insert data into a bucket. + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("people")) + if err != nil { + return err + } + if err := b.Put([]byte("john"), []byte("doe")); err != nil { + return err + } + if err := b.Put([]byte("susy"), []byte("que")); err != nil { + return err + } + return nil + }); err != nil { + log.Fatal(err) + } + + // Access data from within a read-only transactional block. + if err := db.View(func(tx *bolt.Tx) error { + v := tx.Bucket([]byte("people")).Get([]byte("john")) + fmt.Printf("John's last name is %s.\n", v) + return nil + }); err != nil { + log.Fatal(err) + } + + // Close database to release the file lock. + if err := db.Close(); err != nil { + log.Fatal(err) + } + + // Output: + // John's last name is doe. +} + +func ExampleDB_Begin_ReadOnly() { + // Open the database. + db, err := bolt.Open(tempfile(), 0666, nil) + if err != nil { + log.Fatal(err) + } + defer os.Remove(db.Path()) + + // Create a bucket using a read-write transaction. + if err := db.Update(func(tx *bolt.Tx) error { + _, err := tx.CreateBucket([]byte("widgets")) + return err + }); err != nil { + log.Fatal(err) + } + + // Create several keys in a transaction. + tx, err := db.Begin(true) + if err != nil { + log.Fatal(err) + } + b := tx.Bucket([]byte("widgets")) + if err := b.Put([]byte("john"), []byte("blue")); err != nil { + log.Fatal(err) + } + if err := b.Put([]byte("abby"), []byte("red")); err != nil { + log.Fatal(err) + } + if err := b.Put([]byte("zephyr"), []byte("purple")); err != nil { + log.Fatal(err) + } + if err := tx.Commit(); err != nil { + log.Fatal(err) + } + + // Iterate over the values in sorted key order. + tx, err = db.Begin(false) + if err != nil { + log.Fatal(err) + } + c := tx.Bucket([]byte("widgets")).Cursor() + for k, v := c.First(); k != nil; k, v = c.Next() { + fmt.Printf("%s likes %s\n", k, v) + } + + if err := tx.Rollback(); err != nil { + log.Fatal(err) + } + + if err := db.Close(); err != nil { + log.Fatal(err) + } + + // Output: + // abby likes red + // john likes blue + // zephyr likes purple +} + +func BenchmarkDBBatchAutomatic(b *testing.B) { + db := MustOpenDB() + defer db.MustClose() + if err := db.Update(func(tx *bolt.Tx) error { + _, err := tx.CreateBucket([]byte("bench")) + return err + }); err != nil { + b.Fatal(err) + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + start := make(chan struct{}) + var wg sync.WaitGroup + + for round := 0; round < 1000; round++ { + wg.Add(1) + + go func(id uint32) { + defer wg.Done() + <-start + + h := fnv.New32a() + buf := make([]byte, 4) + binary.LittleEndian.PutUint32(buf, id) + _, _ = h.Write(buf[:]) + k := h.Sum(nil) + insert := func(tx *bolt.Tx) error { + b := tx.Bucket([]byte("bench")) + return b.Put(k, []byte("filler")) + } + if err := db.Batch(insert); err != nil { + b.Error(err) + return + } + }(uint32(round)) + } + close(start) + wg.Wait() + } + + b.StopTimer() + validateBatchBench(b, db) +} + +func BenchmarkDBBatchSingle(b *testing.B) { + db := MustOpenDB() + defer db.MustClose() + if err := db.Update(func(tx *bolt.Tx) error { + _, err := tx.CreateBucket([]byte("bench")) + return err + }); err != nil { + b.Fatal(err) + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + start := make(chan struct{}) + var wg sync.WaitGroup + + for round := 0; round < 1000; round++ { + wg.Add(1) + go func(id uint32) { + defer wg.Done() + <-start + + h := fnv.New32a() + buf := make([]byte, 4) + binary.LittleEndian.PutUint32(buf, id) + _, _ = h.Write(buf[:]) + k := h.Sum(nil) + insert := func(tx *bolt.Tx) error { + b := tx.Bucket([]byte("bench")) + return b.Put(k, []byte("filler")) + } + if err := db.Update(insert); err != nil { + b.Error(err) + return + } + }(uint32(round)) + } + close(start) + wg.Wait() + } + + b.StopTimer() + validateBatchBench(b, db) +} + +func BenchmarkDBBatchManual10x100(b *testing.B) { + db := MustOpenDB() + defer db.MustClose() + if err := db.Update(func(tx *bolt.Tx) error { + _, err := tx.CreateBucket([]byte("bench")) + return err + }); err != nil { + b.Fatal(err) + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + start := make(chan struct{}) + var wg sync.WaitGroup + + for major := 0; major < 10; major++ { + wg.Add(1) + go func(id uint32) { + defer wg.Done() + <-start + + insert100 := func(tx *bolt.Tx) error { + h := fnv.New32a() + buf := make([]byte, 4) + for minor := uint32(0); minor < 100; minor++ { + binary.LittleEndian.PutUint32(buf, uint32(id*100+minor)) + h.Reset() + _, _ = h.Write(buf[:]) + k := h.Sum(nil) + b := tx.Bucket([]byte("bench")) + if err := b.Put(k, []byte("filler")); err != nil { + return err + } + } + return nil + } + if err := db.Update(insert100); err != nil { + b.Fatal(err) + } + }(uint32(major)) + } + close(start) + wg.Wait() + } + + b.StopTimer() + validateBatchBench(b, db) +} + +func validateBatchBench(b *testing.B, db *DB) { + var rollback = errors.New("sentinel error to cause rollback") + validate := func(tx *bolt.Tx) error { + bucket := tx.Bucket([]byte("bench")) + h := fnv.New32a() + buf := make([]byte, 4) + for id := uint32(0); id < 1000; id++ { + binary.LittleEndian.PutUint32(buf, id) + h.Reset() + _, _ = h.Write(buf[:]) + k := h.Sum(nil) + v := bucket.Get(k) + if v == nil { + b.Errorf("not found id=%d key=%x", id, k) + continue + } + if g, e := v, []byte("filler"); !bytes.Equal(g, e) { + b.Errorf("bad value for id=%d key=%x: %s != %q", id, k, g, e) + } + if err := bucket.Delete(k); err != nil { + return err + } + } + // should be empty now + c := bucket.Cursor() + for k, v := c.First(); k != nil; k, v = c.Next() { + b.Errorf("unexpected key: %x = %q", k, v) + } + return rollback + } + if err := db.Update(validate); err != nil && err != rollback { + b.Error(err) + } +} + +// DB is a test wrapper for bolt.DB. +type DB struct { + *bolt.DB +} + +// MustOpenDB returns a new, open DB at a temporary location. +func MustOpenDB() *DB { + db, err := bolt.Open(tempfile(), 0666, nil) + if err != nil { + panic(err) + } + return &DB{db} +} + +// Close closes the database and deletes the underlying file. +func (db *DB) Close() error { + // Log statistics. + if *statsFlag { + db.PrintStats() + } + + // Check database consistency after every test. + db.MustCheck() + + // Close database and remove file. + defer os.Remove(db.Path()) + return db.DB.Close() +} + +// MustClose closes the database and deletes the underlying file. Panic on error. +func (db *DB) MustClose() { + if err := db.Close(); err != nil { + panic(err) + } +} + +// PrintStats prints the database stats +func (db *DB) PrintStats() { + var stats = db.Stats() + fmt.Printf("[db] %-20s %-20s %-20s\n", + fmt.Sprintf("pg(%d/%d)", stats.TxStats.PageCount, stats.TxStats.PageAlloc), + fmt.Sprintf("cur(%d)", stats.TxStats.CursorCount), + fmt.Sprintf("node(%d/%d)", stats.TxStats.NodeCount, stats.TxStats.NodeDeref), + ) + fmt.Printf(" %-20s %-20s %-20s\n", + fmt.Sprintf("rebal(%d/%v)", stats.TxStats.Rebalance, truncDuration(stats.TxStats.RebalanceTime)), + fmt.Sprintf("spill(%d/%v)", stats.TxStats.Spill, truncDuration(stats.TxStats.SpillTime)), + fmt.Sprintf("w(%d/%v)", stats.TxStats.Write, truncDuration(stats.TxStats.WriteTime)), + ) +} + +// MustCheck runs a consistency check on the database and panics if any errors are found. +func (db *DB) MustCheck() { + if err := db.Update(func(tx *bolt.Tx) error { + // Collect all the errors. + var errors []error + for err := range tx.Check() { + errors = append(errors, err) + if len(errors) > 10 { + break + } + } + + // If errors occurred, copy the DB and print the errors. + if len(errors) > 0 { + var path = tempfile() + if err := tx.CopyFile(path, 0600); err != nil { + panic(err) + } + + // Print errors. + fmt.Print("\n\n") + fmt.Printf("consistency check failed (%d errors)\n", len(errors)) + for _, err := range errors { + fmt.Println(err) + } + fmt.Println("") + fmt.Println("db saved to:") + fmt.Println(path) + fmt.Print("\n\n") + os.Exit(-1) + } + + return nil + }); err != nil && err != bolt.ErrDatabaseNotOpen { + panic(err) + } +} + +// CopyTempFile copies a database to a temporary file. +func (db *DB) CopyTempFile() { + path := tempfile() + if err := db.View(func(tx *bolt.Tx) error { + return tx.CopyFile(path, 0600) + }); err != nil { + panic(err) + } + fmt.Println("db copied to: ", path) +} + +// tempfile returns a temporary file path. +func tempfile() string { + f, err := ioutil.TempFile("", "bolt-") + if err != nil { + panic(err) + } + if err := f.Close(); err != nil { + panic(err) + } + if err := os.Remove(f.Name()); err != nil { + panic(err) + } + return f.Name() +} + +// mustContainKeys checks that a bucket contains a given set of keys. +func mustContainKeys(b *bolt.Bucket, m map[string]string) { + found := make(map[string]string) + if err := b.ForEach(func(k, _ []byte) error { + found[string(k)] = "" + return nil + }); err != nil { + panic(err) + } + + // Check for keys found in bucket that shouldn't be there. + var keys []string + for k, _ := range found { + if _, ok := m[string(k)]; !ok { + keys = append(keys, k) + } + } + if len(keys) > 0 { + sort.Strings(keys) + panic(fmt.Sprintf("keys found(%d): %s", len(keys), strings.Join(keys, ","))) + } + + // Check for keys not found in bucket that should be there. + for k, _ := range m { + if _, ok := found[string(k)]; !ok { + keys = append(keys, k) + } + } + if len(keys) > 0 { + sort.Strings(keys) + panic(fmt.Sprintf("keys not found(%d): %s", len(keys), strings.Join(keys, ","))) + } +} + +func trunc(b []byte, length int) []byte { + if length < len(b) { + return b[:length] + } + return b +} + +func truncDuration(d time.Duration) string { + return regexp.MustCompile(`^(\d+)(\.\d+)`).ReplaceAllString(d.String(), "$1") +} + +func fileSize(path string) int64 { + fi, err := os.Stat(path) + if err != nil { + return 0 + } + return fi.Size() +} + +func warn(v ...interface{}) { fmt.Fprintln(os.Stderr, v...) } +func warnf(msg string, v ...interface{}) { fmt.Fprintf(os.Stderr, msg+"\n", v...) } + +// u64tob converts a uint64 into an 8-byte slice. +func u64tob(v uint64) []byte { + b := make([]byte, 8) + binary.BigEndian.PutUint64(b, v) + return b +} + +// btou64 converts an 8-byte slice into an uint64. +func btou64(b []byte) uint64 { return binary.BigEndian.Uint64(b) } diff --git a/vendor/github.com/boltdb/bolt/doc.go b/vendor/github.com/boltdb/bolt/doc.go new file mode 100644 index 00000000..cc937845 --- /dev/null +++ b/vendor/github.com/boltdb/bolt/doc.go @@ -0,0 +1,44 @@ +/* +Package bolt implements a low-level key/value store in pure Go. It supports +fully serializable transactions, ACID semantics, and lock-free MVCC with +multiple readers and a single writer. Bolt can be used for projects that +want a simple data store without the need to add large dependencies such as +Postgres or MySQL. + +Bolt is a single-level, zero-copy, B+tree data store. This means that Bolt is +optimized for fast read access and does not require recovery in the event of a +system crash. Transactions which have not finished committing will simply be +rolled back in the event of a crash. + +The design of Bolt is based on Howard Chu's LMDB database project. + +Bolt currently works on Windows, Mac OS X, and Linux. + + +Basics + +There are only a few types in Bolt: DB, Bucket, Tx, and Cursor. The DB is +a collection of buckets and is represented by a single file on disk. A bucket is +a collection of unique keys that are associated with values. + +Transactions provide either read-only or read-write access to the database. +Read-only transactions can retrieve key/value pairs and can use Cursors to +iterate over the dataset sequentially. Read-write transactions can create and +delete buckets and can insert and remove keys. Only one read-write transaction +is allowed at a time. + + +Caveats + +The database uses a read-only, memory-mapped data file to ensure that +applications cannot corrupt the database, however, this means that keys and +values returned from Bolt cannot be changed. Writing to a read-only byte slice +will cause Go to panic. + +Keys and values retrieved from the database are only valid for the life of +the transaction. When used outside the transaction, these byte slices can +point to different data or can point to invalid memory which will cause a panic. + + +*/ +package bolt diff --git a/vendor/github.com/boltdb/bolt/errors.go b/vendor/github.com/boltdb/bolt/errors.go new file mode 100644 index 00000000..a3620a3e --- /dev/null +++ b/vendor/github.com/boltdb/bolt/errors.go @@ -0,0 +1,71 @@ +package bolt + +import "errors" + +// These errors can be returned when opening or calling methods on a DB. +var ( + // ErrDatabaseNotOpen is returned when a DB instance is accessed before it + // is opened or after it is closed. + ErrDatabaseNotOpen = errors.New("database not open") + + // ErrDatabaseOpen is returned when opening a database that is + // already open. + ErrDatabaseOpen = errors.New("database already open") + + // ErrInvalid is returned when both meta pages on a database are invalid. + // This typically occurs when a file is not a bolt database. + ErrInvalid = errors.New("invalid database") + + // ErrVersionMismatch is returned when the data file was created with a + // different version of Bolt. + ErrVersionMismatch = errors.New("version mismatch") + + // ErrChecksum is returned when either meta page checksum does not match. + ErrChecksum = errors.New("checksum error") + + // ErrTimeout is returned when a database cannot obtain an exclusive lock + // on the data file after the timeout passed to Open(). + ErrTimeout = errors.New("timeout") +) + +// These errors can occur when beginning or committing a Tx. +var ( + // ErrTxNotWritable is returned when performing a write operation on a + // read-only transaction. + ErrTxNotWritable = errors.New("tx not writable") + + // ErrTxClosed is returned when committing or rolling back a transaction + // that has already been committed or rolled back. + ErrTxClosed = errors.New("tx closed") + + // ErrDatabaseReadOnly is returned when a mutating transaction is started on a + // read-only database. + ErrDatabaseReadOnly = errors.New("database is in read-only mode") +) + +// These errors can occur when putting or deleting a value or a bucket. +var ( + // ErrBucketNotFound is returned when trying to access a bucket that has + // not been created yet. + ErrBucketNotFound = errors.New("bucket not found") + + // ErrBucketExists is returned when creating a bucket that already exists. + ErrBucketExists = errors.New("bucket already exists") + + // ErrBucketNameRequired is returned when creating a bucket with a blank name. + ErrBucketNameRequired = errors.New("bucket name required") + + // ErrKeyRequired is returned when inserting a zero-length key. + ErrKeyRequired = errors.New("key required") + + // ErrKeyTooLarge is returned when inserting a key that is larger than MaxKeySize. + ErrKeyTooLarge = errors.New("key too large") + + // ErrValueTooLarge is returned when inserting a value that is larger than MaxValueSize. + ErrValueTooLarge = errors.New("value too large") + + // ErrIncompatibleValue is returned when trying create or delete a bucket + // on an existing non-bucket key or when trying to create or delete a + // non-bucket key on an existing bucket key. + ErrIncompatibleValue = errors.New("incompatible value") +) diff --git a/vendor/github.com/boltdb/bolt/freelist.go b/vendor/github.com/boltdb/bolt/freelist.go new file mode 100644 index 00000000..aba48f58 --- /dev/null +++ b/vendor/github.com/boltdb/bolt/freelist.go @@ -0,0 +1,252 @@ +package bolt + +import ( + "fmt" + "sort" + "unsafe" +) + +// freelist represents a list of all pages that are available for allocation. +// It also tracks pages that have been freed but are still in use by open transactions. +type freelist struct { + ids []pgid // all free and available free page ids. + pending map[txid][]pgid // mapping of soon-to-be free page ids by tx. + cache map[pgid]bool // fast lookup of all free and pending page ids. +} + +// newFreelist returns an empty, initialized freelist. +func newFreelist() *freelist { + return &freelist{ + pending: make(map[txid][]pgid), + cache: make(map[pgid]bool), + } +} + +// size returns the size of the page after serialization. +func (f *freelist) size() int { + n := f.count() + if n >= 0xFFFF { + // The first element will be used to store the count. See freelist.write. + n++ + } + return pageHeaderSize + (int(unsafe.Sizeof(pgid(0))) * n) +} + +// count returns count of pages on the freelist +func (f *freelist) count() int { + return f.free_count() + f.pending_count() +} + +// free_count returns count of free pages +func (f *freelist) free_count() int { + return len(f.ids) +} + +// pending_count returns count of pending pages +func (f *freelist) pending_count() int { + var count int + for _, list := range f.pending { + count += len(list) + } + return count +} + +// copyall copies into dst a list of all free ids and all pending ids in one sorted list. +// f.count returns the minimum length required for dst. +func (f *freelist) copyall(dst []pgid) { + m := make(pgids, 0, f.pending_count()) + for _, list := range f.pending { + m = append(m, list...) + } + sort.Sort(m) + mergepgids(dst, f.ids, m) +} + +// allocate returns the starting page id of a contiguous list of pages of a given size. +// If a contiguous block cannot be found then 0 is returned. +func (f *freelist) allocate(n int) pgid { + if len(f.ids) == 0 { + return 0 + } + + var initial, previd pgid + for i, id := range f.ids { + if id <= 1 { + panic(fmt.Sprintf("invalid page allocation: %d", id)) + } + + // Reset initial page if this is not contiguous. + if previd == 0 || id-previd != 1 { + initial = id + } + + // If we found a contiguous block then remove it and return it. + if (id-initial)+1 == pgid(n) { + // If we're allocating off the beginning then take the fast path + // and just adjust the existing slice. This will use extra memory + // temporarily but the append() in free() will realloc the slice + // as is necessary. + if (i + 1) == n { + f.ids = f.ids[i+1:] + } else { + copy(f.ids[i-n+1:], f.ids[i+1:]) + f.ids = f.ids[:len(f.ids)-n] + } + + // Remove from the free cache. + for i := pgid(0); i < pgid(n); i++ { + delete(f.cache, initial+i) + } + + return initial + } + + previd = id + } + return 0 +} + +// free releases a page and its overflow for a given transaction id. +// If the page is already free then a panic will occur. +func (f *freelist) free(txid txid, p *page) { + if p.id <= 1 { + panic(fmt.Sprintf("cannot free page 0 or 1: %d", p.id)) + } + + // Free page and all its overflow pages. + var ids = f.pending[txid] + for id := p.id; id <= p.id+pgid(p.overflow); id++ { + // Verify that page is not already free. + if f.cache[id] { + panic(fmt.Sprintf("page %d already freed", id)) + } + + // Add to the freelist and cache. + ids = append(ids, id) + f.cache[id] = true + } + f.pending[txid] = ids +} + +// release moves all page ids for a transaction id (or older) to the freelist. +func (f *freelist) release(txid txid) { + m := make(pgids, 0) + for tid, ids := range f.pending { + if tid <= txid { + // Move transaction's pending pages to the available freelist. + // Don't remove from the cache since the page is still free. + m = append(m, ids...) + delete(f.pending, tid) + } + } + sort.Sort(m) + f.ids = pgids(f.ids).merge(m) +} + +// rollback removes the pages from a given pending tx. +func (f *freelist) rollback(txid txid) { + // Remove page ids from cache. + for _, id := range f.pending[txid] { + delete(f.cache, id) + } + + // Remove pages from pending list. + delete(f.pending, txid) +} + +// freed returns whether a given page is in the free list. +func (f *freelist) freed(pgid pgid) bool { + return f.cache[pgid] +} + +// read initializes the freelist from a freelist page. +func (f *freelist) read(p *page) { + // If the page.count is at the max uint16 value (64k) then it's considered + // an overflow and the size of the freelist is stored as the first element. + idx, count := 0, int(p.count) + if count == 0xFFFF { + idx = 1 + count = int(((*[maxAllocSize]pgid)(unsafe.Pointer(&p.ptr)))[0]) + } + + // Copy the list of page ids from the freelist. + if count == 0 { + f.ids = nil + } else { + ids := ((*[maxAllocSize]pgid)(unsafe.Pointer(&p.ptr)))[idx:count] + f.ids = make([]pgid, len(ids)) + copy(f.ids, ids) + + // Make sure they're sorted. + sort.Sort(pgids(f.ids)) + } + + // Rebuild the page cache. + f.reindex() +} + +// write writes the page ids onto a freelist page. All free and pending ids are +// saved to disk since in the event of a program crash, all pending ids will +// become free. +func (f *freelist) write(p *page) error { + // Combine the old free pgids and pgids waiting on an open transaction. + + // Update the header flag. + p.flags |= freelistPageFlag + + // The page.count can only hold up to 64k elements so if we overflow that + // number then we handle it by putting the size in the first element. + lenids := f.count() + if lenids == 0 { + p.count = uint16(lenids) + } else if lenids < 0xFFFF { + p.count = uint16(lenids) + f.copyall(((*[maxAllocSize]pgid)(unsafe.Pointer(&p.ptr)))[:]) + } else { + p.count = 0xFFFF + ((*[maxAllocSize]pgid)(unsafe.Pointer(&p.ptr)))[0] = pgid(lenids) + f.copyall(((*[maxAllocSize]pgid)(unsafe.Pointer(&p.ptr)))[1:]) + } + + return nil +} + +// reload reads the freelist from a page and filters out pending items. +func (f *freelist) reload(p *page) { + f.read(p) + + // Build a cache of only pending pages. + pcache := make(map[pgid]bool) + for _, pendingIDs := range f.pending { + for _, pendingID := range pendingIDs { + pcache[pendingID] = true + } + } + + // Check each page in the freelist and build a new available freelist + // with any pages not in the pending lists. + var a []pgid + for _, id := range f.ids { + if !pcache[id] { + a = append(a, id) + } + } + f.ids = a + + // Once the available list is rebuilt then rebuild the free cache so that + // it includes the available and pending free pages. + f.reindex() +} + +// reindex rebuilds the free cache based on available and pending free lists. +func (f *freelist) reindex() { + f.cache = make(map[pgid]bool, len(f.ids)) + for _, id := range f.ids { + f.cache[id] = true + } + for _, pendingIDs := range f.pending { + for _, pendingID := range pendingIDs { + f.cache[pendingID] = true + } + } +} diff --git a/vendor/github.com/boltdb/bolt/freelist_test.go b/vendor/github.com/boltdb/bolt/freelist_test.go new file mode 100644 index 00000000..4e9b3a8d --- /dev/null +++ b/vendor/github.com/boltdb/bolt/freelist_test.go @@ -0,0 +1,158 @@ +package bolt + +import ( + "math/rand" + "reflect" + "sort" + "testing" + "unsafe" +) + +// Ensure that a page is added to a transaction's freelist. +func TestFreelist_free(t *testing.T) { + f := newFreelist() + f.free(100, &page{id: 12}) + if !reflect.DeepEqual([]pgid{12}, f.pending[100]) { + t.Fatalf("exp=%v; got=%v", []pgid{12}, f.pending[100]) + } +} + +// Ensure that a page and its overflow is added to a transaction's freelist. +func TestFreelist_free_overflow(t *testing.T) { + f := newFreelist() + f.free(100, &page{id: 12, overflow: 3}) + if exp := []pgid{12, 13, 14, 15}; !reflect.DeepEqual(exp, f.pending[100]) { + t.Fatalf("exp=%v; got=%v", exp, f.pending[100]) + } +} + +// Ensure that a transaction's free pages can be released. +func TestFreelist_release(t *testing.T) { + f := newFreelist() + f.free(100, &page{id: 12, overflow: 1}) + f.free(100, &page{id: 9}) + f.free(102, &page{id: 39}) + f.release(100) + f.release(101) + if exp := []pgid{9, 12, 13}; !reflect.DeepEqual(exp, f.ids) { + t.Fatalf("exp=%v; got=%v", exp, f.ids) + } + + f.release(102) + if exp := []pgid{9, 12, 13, 39}; !reflect.DeepEqual(exp, f.ids) { + t.Fatalf("exp=%v; got=%v", exp, f.ids) + } +} + +// Ensure that a freelist can find contiguous blocks of pages. +func TestFreelist_allocate(t *testing.T) { + f := &freelist{ids: []pgid{3, 4, 5, 6, 7, 9, 12, 13, 18}} + if id := int(f.allocate(3)); id != 3 { + t.Fatalf("exp=3; got=%v", id) + } + if id := int(f.allocate(1)); id != 6 { + t.Fatalf("exp=6; got=%v", id) + } + if id := int(f.allocate(3)); id != 0 { + t.Fatalf("exp=0; got=%v", id) + } + if id := int(f.allocate(2)); id != 12 { + t.Fatalf("exp=12; got=%v", id) + } + if id := int(f.allocate(1)); id != 7 { + t.Fatalf("exp=7; got=%v", id) + } + if id := int(f.allocate(0)); id != 0 { + t.Fatalf("exp=0; got=%v", id) + } + if id := int(f.allocate(0)); id != 0 { + t.Fatalf("exp=0; got=%v", id) + } + if exp := []pgid{9, 18}; !reflect.DeepEqual(exp, f.ids) { + t.Fatalf("exp=%v; got=%v", exp, f.ids) + } + + if id := int(f.allocate(1)); id != 9 { + t.Fatalf("exp=9; got=%v", id) + } + if id := int(f.allocate(1)); id != 18 { + t.Fatalf("exp=18; got=%v", id) + } + if id := int(f.allocate(1)); id != 0 { + t.Fatalf("exp=0; got=%v", id) + } + if exp := []pgid{}; !reflect.DeepEqual(exp, f.ids) { + t.Fatalf("exp=%v; got=%v", exp, f.ids) + } +} + +// Ensure that a freelist can deserialize from a freelist page. +func TestFreelist_read(t *testing.T) { + // Create a page. + var buf [4096]byte + page := (*page)(unsafe.Pointer(&buf[0])) + page.flags = freelistPageFlag + page.count = 2 + + // Insert 2 page ids. + ids := (*[3]pgid)(unsafe.Pointer(&page.ptr)) + ids[0] = 23 + ids[1] = 50 + + // Deserialize page into a freelist. + f := newFreelist() + f.read(page) + + // Ensure that there are two page ids in the freelist. + if exp := []pgid{23, 50}; !reflect.DeepEqual(exp, f.ids) { + t.Fatalf("exp=%v; got=%v", exp, f.ids) + } +} + +// Ensure that a freelist can serialize into a freelist page. +func TestFreelist_write(t *testing.T) { + // Create a freelist and write it to a page. + var buf [4096]byte + f := &freelist{ids: []pgid{12, 39}, pending: make(map[txid][]pgid)} + f.pending[100] = []pgid{28, 11} + f.pending[101] = []pgid{3} + p := (*page)(unsafe.Pointer(&buf[0])) + if err := f.write(p); err != nil { + t.Fatal(err) + } + + // Read the page back out. + f2 := newFreelist() + f2.read(p) + + // Ensure that the freelist is correct. + // All pages should be present and in reverse order. + if exp := []pgid{3, 11, 12, 28, 39}; !reflect.DeepEqual(exp, f2.ids) { + t.Fatalf("exp=%v; got=%v", exp, f2.ids) + } +} + +func Benchmark_FreelistRelease10K(b *testing.B) { benchmark_FreelistRelease(b, 10000) } +func Benchmark_FreelistRelease100K(b *testing.B) { benchmark_FreelistRelease(b, 100000) } +func Benchmark_FreelistRelease1000K(b *testing.B) { benchmark_FreelistRelease(b, 1000000) } +func Benchmark_FreelistRelease10000K(b *testing.B) { benchmark_FreelistRelease(b, 10000000) } + +func benchmark_FreelistRelease(b *testing.B, size int) { + ids := randomPgids(size) + pending := randomPgids(len(ids) / 400) + b.ResetTimer() + for i := 0; i < b.N; i++ { + f := &freelist{ids: ids, pending: map[txid][]pgid{1: pending}} + f.release(1) + } +} + +func randomPgids(n int) []pgid { + rand.Seed(42) + pgids := make(pgids, n) + for i := range pgids { + pgids[i] = pgid(rand.Int63()) + } + sort.Sort(pgids) + return pgids +} diff --git a/vendor/github.com/boltdb/bolt/node.go b/vendor/github.com/boltdb/bolt/node.go new file mode 100644 index 00000000..159318b2 --- /dev/null +++ b/vendor/github.com/boltdb/bolt/node.go @@ -0,0 +1,604 @@ +package bolt + +import ( + "bytes" + "fmt" + "sort" + "unsafe" +) + +// node represents an in-memory, deserialized page. +type node struct { + bucket *Bucket + isLeaf bool + unbalanced bool + spilled bool + key []byte + pgid pgid + parent *node + children nodes + inodes inodes +} + +// root returns the top-level node this node is attached to. +func (n *node) root() *node { + if n.parent == nil { + return n + } + return n.parent.root() +} + +// minKeys returns the minimum number of inodes this node should have. +func (n *node) minKeys() int { + if n.isLeaf { + return 1 + } + return 2 +} + +// size returns the size of the node after serialization. +func (n *node) size() int { + sz, elsz := pageHeaderSize, n.pageElementSize() + for i := 0; i < len(n.inodes); i++ { + item := &n.inodes[i] + sz += elsz + len(item.key) + len(item.value) + } + return sz +} + +// sizeLessThan returns true if the node is less than a given size. +// This is an optimization to avoid calculating a large node when we only need +// to know if it fits inside a certain page size. +func (n *node) sizeLessThan(v int) bool { + sz, elsz := pageHeaderSize, n.pageElementSize() + for i := 0; i < len(n.inodes); i++ { + item := &n.inodes[i] + sz += elsz + len(item.key) + len(item.value) + if sz >= v { + return false + } + } + return true +} + +// pageElementSize returns the size of each page element based on the type of node. +func (n *node) pageElementSize() int { + if n.isLeaf { + return leafPageElementSize + } + return branchPageElementSize +} + +// childAt returns the child node at a given index. +func (n *node) childAt(index int) *node { + if n.isLeaf { + panic(fmt.Sprintf("invalid childAt(%d) on a leaf node", index)) + } + return n.bucket.node(n.inodes[index].pgid, n) +} + +// childIndex returns the index of a given child node. +func (n *node) childIndex(child *node) int { + index := sort.Search(len(n.inodes), func(i int) bool { return bytes.Compare(n.inodes[i].key, child.key) != -1 }) + return index +} + +// numChildren returns the number of children. +func (n *node) numChildren() int { + return len(n.inodes) +} + +// nextSibling returns the next node with the same parent. +func (n *node) nextSibling() *node { + if n.parent == nil { + return nil + } + index := n.parent.childIndex(n) + if index >= n.parent.numChildren()-1 { + return nil + } + return n.parent.childAt(index + 1) +} + +// prevSibling returns the previous node with the same parent. +func (n *node) prevSibling() *node { + if n.parent == nil { + return nil + } + index := n.parent.childIndex(n) + if index == 0 { + return nil + } + return n.parent.childAt(index - 1) +} + +// put inserts a key/value. +func (n *node) put(oldKey, newKey, value []byte, pgid pgid, flags uint32) { + if pgid >= n.bucket.tx.meta.pgid { + panic(fmt.Sprintf("pgid (%d) above high water mark (%d)", pgid, n.bucket.tx.meta.pgid)) + } else if len(oldKey) <= 0 { + panic("put: zero-length old key") + } else if len(newKey) <= 0 { + panic("put: zero-length new key") + } + + // Find insertion index. + index := sort.Search(len(n.inodes), func(i int) bool { return bytes.Compare(n.inodes[i].key, oldKey) != -1 }) + + // Add capacity and shift nodes if we don't have an exact match and need to insert. + exact := (len(n.inodes) > 0 && index < len(n.inodes) && bytes.Equal(n.inodes[index].key, oldKey)) + if !exact { + n.inodes = append(n.inodes, inode{}) + copy(n.inodes[index+1:], n.inodes[index:]) + } + + inode := &n.inodes[index] + inode.flags = flags + inode.key = newKey + inode.value = value + inode.pgid = pgid + _assert(len(inode.key) > 0, "put: zero-length inode key") +} + +// del removes a key from the node. +func (n *node) del(key []byte) { + // Find index of key. + index := sort.Search(len(n.inodes), func(i int) bool { return bytes.Compare(n.inodes[i].key, key) != -1 }) + + // Exit if the key isn't found. + if index >= len(n.inodes) || !bytes.Equal(n.inodes[index].key, key) { + return + } + + // Delete inode from the node. + n.inodes = append(n.inodes[:index], n.inodes[index+1:]...) + + // Mark the node as needing rebalancing. + n.unbalanced = true +} + +// read initializes the node from a page. +func (n *node) read(p *page) { + n.pgid = p.id + n.isLeaf = ((p.flags & leafPageFlag) != 0) + n.inodes = make(inodes, int(p.count)) + + for i := 0; i < int(p.count); i++ { + inode := &n.inodes[i] + if n.isLeaf { + elem := p.leafPageElement(uint16(i)) + inode.flags = elem.flags + inode.key = elem.key() + inode.value = elem.value() + } else { + elem := p.branchPageElement(uint16(i)) + inode.pgid = elem.pgid + inode.key = elem.key() + } + _assert(len(inode.key) > 0, "read: zero-length inode key") + } + + // Save first key so we can find the node in the parent when we spill. + if len(n.inodes) > 0 { + n.key = n.inodes[0].key + _assert(len(n.key) > 0, "read: zero-length node key") + } else { + n.key = nil + } +} + +// write writes the items onto one or more pages. +func (n *node) write(p *page) { + // Initialize page. + if n.isLeaf { + p.flags |= leafPageFlag + } else { + p.flags |= branchPageFlag + } + + if len(n.inodes) >= 0xFFFF { + panic(fmt.Sprintf("inode overflow: %d (pgid=%d)", len(n.inodes), p.id)) + } + p.count = uint16(len(n.inodes)) + + // Stop here if there are no items to write. + if p.count == 0 { + return + } + + // Loop over each item and write it to the page. + b := (*[maxAllocSize]byte)(unsafe.Pointer(&p.ptr))[n.pageElementSize()*len(n.inodes):] + for i, item := range n.inodes { + _assert(len(item.key) > 0, "write: zero-length inode key") + + // Write the page element. + if n.isLeaf { + elem := p.leafPageElement(uint16(i)) + elem.pos = uint32(uintptr(unsafe.Pointer(&b[0])) - uintptr(unsafe.Pointer(elem))) + elem.flags = item.flags + elem.ksize = uint32(len(item.key)) + elem.vsize = uint32(len(item.value)) + } else { + elem := p.branchPageElement(uint16(i)) + elem.pos = uint32(uintptr(unsafe.Pointer(&b[0])) - uintptr(unsafe.Pointer(elem))) + elem.ksize = uint32(len(item.key)) + elem.pgid = item.pgid + _assert(elem.pgid != p.id, "write: circular dependency occurred") + } + + // If the length of key+value is larger than the max allocation size + // then we need to reallocate the byte array pointer. + // + // See: https://github.com/boltdb/bolt/pull/335 + klen, vlen := len(item.key), len(item.value) + if len(b) < klen+vlen { + b = (*[maxAllocSize]byte)(unsafe.Pointer(&b[0]))[:] + } + + // Write data for the element to the end of the page. + copy(b[0:], item.key) + b = b[klen:] + copy(b[0:], item.value) + b = b[vlen:] + } + + // DEBUG ONLY: n.dump() +} + +// split breaks up a node into multiple smaller nodes, if appropriate. +// This should only be called from the spill() function. +func (n *node) split(pageSize int) []*node { + var nodes []*node + + node := n + for { + // Split node into two. + a, b := node.splitTwo(pageSize) + nodes = append(nodes, a) + + // If we can't split then exit the loop. + if b == nil { + break + } + + // Set node to b so it gets split on the next iteration. + node = b + } + + return nodes +} + +// splitTwo breaks up a node into two smaller nodes, if appropriate. +// This should only be called from the split() function. +func (n *node) splitTwo(pageSize int) (*node, *node) { + // Ignore the split if the page doesn't have at least enough nodes for + // two pages or if the nodes can fit in a single page. + if len(n.inodes) <= (minKeysPerPage*2) || n.sizeLessThan(pageSize) { + return n, nil + } + + // Determine the threshold before starting a new node. + var fillPercent = n.bucket.FillPercent + if fillPercent < minFillPercent { + fillPercent = minFillPercent + } else if fillPercent > maxFillPercent { + fillPercent = maxFillPercent + } + threshold := int(float64(pageSize) * fillPercent) + + // Determine split position and sizes of the two pages. + splitIndex, _ := n.splitIndex(threshold) + + // Split node into two separate nodes. + // If there's no parent then we'll need to create one. + if n.parent == nil { + n.parent = &node{bucket: n.bucket, children: []*node{n}} + } + + // Create a new node and add it to the parent. + next := &node{bucket: n.bucket, isLeaf: n.isLeaf, parent: n.parent} + n.parent.children = append(n.parent.children, next) + + // Split inodes across two nodes. + next.inodes = n.inodes[splitIndex:] + n.inodes = n.inodes[:splitIndex] + + // Update the statistics. + n.bucket.tx.stats.Split++ + + return n, next +} + +// splitIndex finds the position where a page will fill a given threshold. +// It returns the index as well as the size of the first page. +// This is only be called from split(). +func (n *node) splitIndex(threshold int) (index, sz int) { + sz = pageHeaderSize + + // Loop until we only have the minimum number of keys required for the second page. + for i := 0; i < len(n.inodes)-minKeysPerPage; i++ { + index = i + inode := n.inodes[i] + elsize := n.pageElementSize() + len(inode.key) + len(inode.value) + + // If we have at least the minimum number of keys and adding another + // node would put us over the threshold then exit and return. + if i >= minKeysPerPage && sz+elsize > threshold { + break + } + + // Add the element size to the total size. + sz += elsize + } + + return +} + +// spill writes the nodes to dirty pages and splits nodes as it goes. +// Returns an error if dirty pages cannot be allocated. +func (n *node) spill() error { + var tx = n.bucket.tx + if n.spilled { + return nil + } + + // Spill child nodes first. Child nodes can materialize sibling nodes in + // the case of split-merge so we cannot use a range loop. We have to check + // the children size on every loop iteration. + sort.Sort(n.children) + for i := 0; i < len(n.children); i++ { + if err := n.children[i].spill(); err != nil { + return err + } + } + + // We no longer need the child list because it's only used for spill tracking. + n.children = nil + + // Split nodes into appropriate sizes. The first node will always be n. + var nodes = n.split(tx.db.pageSize) + for _, node := range nodes { + // Add node's page to the freelist if it's not new. + if node.pgid > 0 { + tx.db.freelist.free(tx.meta.txid, tx.page(node.pgid)) + node.pgid = 0 + } + + // Allocate contiguous space for the node. + p, err := tx.allocate((node.size() / tx.db.pageSize) + 1) + if err != nil { + return err + } + + // Write the node. + if p.id >= tx.meta.pgid { + panic(fmt.Sprintf("pgid (%d) above high water mark (%d)", p.id, tx.meta.pgid)) + } + node.pgid = p.id + node.write(p) + node.spilled = true + + // Insert into parent inodes. + if node.parent != nil { + var key = node.key + if key == nil { + key = node.inodes[0].key + } + + node.parent.put(key, node.inodes[0].key, nil, node.pgid, 0) + node.key = node.inodes[0].key + _assert(len(node.key) > 0, "spill: zero-length node key") + } + + // Update the statistics. + tx.stats.Spill++ + } + + // If the root node split and created a new root then we need to spill that + // as well. We'll clear out the children to make sure it doesn't try to respill. + if n.parent != nil && n.parent.pgid == 0 { + n.children = nil + return n.parent.spill() + } + + return nil +} + +// rebalance attempts to combine the node with sibling nodes if the node fill +// size is below a threshold or if there are not enough keys. +func (n *node) rebalance() { + if !n.unbalanced { + return + } + n.unbalanced = false + + // Update statistics. + n.bucket.tx.stats.Rebalance++ + + // Ignore if node is above threshold (25%) and has enough keys. + var threshold = n.bucket.tx.db.pageSize / 4 + if n.size() > threshold && len(n.inodes) > n.minKeys() { + return + } + + // Root node has special handling. + if n.parent == nil { + // If root node is a branch and only has one node then collapse it. + if !n.isLeaf && len(n.inodes) == 1 { + // Move root's child up. + child := n.bucket.node(n.inodes[0].pgid, n) + n.isLeaf = child.isLeaf + n.inodes = child.inodes[:] + n.children = child.children + + // Reparent all child nodes being moved. + for _, inode := range n.inodes { + if child, ok := n.bucket.nodes[inode.pgid]; ok { + child.parent = n + } + } + + // Remove old child. + child.parent = nil + delete(n.bucket.nodes, child.pgid) + child.free() + } + + return + } + + // If node has no keys then just remove it. + if n.numChildren() == 0 { + n.parent.del(n.key) + n.parent.removeChild(n) + delete(n.bucket.nodes, n.pgid) + n.free() + n.parent.rebalance() + return + } + + _assert(n.parent.numChildren() > 1, "parent must have at least 2 children") + + // Destination node is right sibling if idx == 0, otherwise left sibling. + var target *node + var useNextSibling = (n.parent.childIndex(n) == 0) + if useNextSibling { + target = n.nextSibling() + } else { + target = n.prevSibling() + } + + // If both this node and the target node are too small then merge them. + if useNextSibling { + // Reparent all child nodes being moved. + for _, inode := range target.inodes { + if child, ok := n.bucket.nodes[inode.pgid]; ok { + child.parent.removeChild(child) + child.parent = n + child.parent.children = append(child.parent.children, child) + } + } + + // Copy over inodes from target and remove target. + n.inodes = append(n.inodes, target.inodes...) + n.parent.del(target.key) + n.parent.removeChild(target) + delete(n.bucket.nodes, target.pgid) + target.free() + } else { + // Reparent all child nodes being moved. + for _, inode := range n.inodes { + if child, ok := n.bucket.nodes[inode.pgid]; ok { + child.parent.removeChild(child) + child.parent = target + child.parent.children = append(child.parent.children, child) + } + } + + // Copy over inodes to target and remove node. + target.inodes = append(target.inodes, n.inodes...) + n.parent.del(n.key) + n.parent.removeChild(n) + delete(n.bucket.nodes, n.pgid) + n.free() + } + + // Either this node or the target node was deleted from the parent so rebalance it. + n.parent.rebalance() +} + +// removes a node from the list of in-memory children. +// This does not affect the inodes. +func (n *node) removeChild(target *node) { + for i, child := range n.children { + if child == target { + n.children = append(n.children[:i], n.children[i+1:]...) + return + } + } +} + +// dereference causes the node to copy all its inode key/value references to heap memory. +// This is required when the mmap is reallocated so inodes are not pointing to stale data. +func (n *node) dereference() { + if n.key != nil { + key := make([]byte, len(n.key)) + copy(key, n.key) + n.key = key + _assert(n.pgid == 0 || len(n.key) > 0, "dereference: zero-length node key on existing node") + } + + for i := range n.inodes { + inode := &n.inodes[i] + + key := make([]byte, len(inode.key)) + copy(key, inode.key) + inode.key = key + _assert(len(inode.key) > 0, "dereference: zero-length inode key") + + value := make([]byte, len(inode.value)) + copy(value, inode.value) + inode.value = value + } + + // Recursively dereference children. + for _, child := range n.children { + child.dereference() + } + + // Update statistics. + n.bucket.tx.stats.NodeDeref++ +} + +// free adds the node's underlying page to the freelist. +func (n *node) free() { + if n.pgid != 0 { + n.bucket.tx.db.freelist.free(n.bucket.tx.meta.txid, n.bucket.tx.page(n.pgid)) + n.pgid = 0 + } +} + +// dump writes the contents of the node to STDERR for debugging purposes. +/* +func (n *node) dump() { + // Write node header. + var typ = "branch" + if n.isLeaf { + typ = "leaf" + } + warnf("[NODE %d {type=%s count=%d}]", n.pgid, typ, len(n.inodes)) + + // Write out abbreviated version of each item. + for _, item := range n.inodes { + if n.isLeaf { + if item.flags&bucketLeafFlag != 0 { + bucket := (*bucket)(unsafe.Pointer(&item.value[0])) + warnf("+L %08x -> (bucket root=%d)", trunc(item.key, 4), bucket.root) + } else { + warnf("+L %08x -> %08x", trunc(item.key, 4), trunc(item.value, 4)) + } + } else { + warnf("+B %08x -> pgid=%d", trunc(item.key, 4), item.pgid) + } + } + warn("") +} +*/ + +type nodes []*node + +func (s nodes) Len() int { return len(s) } +func (s nodes) Swap(i, j int) { s[i], s[j] = s[j], s[i] } +func (s nodes) Less(i, j int) bool { return bytes.Compare(s[i].inodes[0].key, s[j].inodes[0].key) == -1 } + +// inode represents an internal node inside of a node. +// It can be used to point to elements in a page or point +// to an element which hasn't been added to a page yet. +type inode struct { + flags uint32 + pgid pgid + key []byte + value []byte +} + +type inodes []inode diff --git a/vendor/github.com/boltdb/bolt/node_test.go b/vendor/github.com/boltdb/bolt/node_test.go new file mode 100644 index 00000000..fa5d10f9 --- /dev/null +++ b/vendor/github.com/boltdb/bolt/node_test.go @@ -0,0 +1,156 @@ +package bolt + +import ( + "testing" + "unsafe" +) + +// Ensure that a node can insert a key/value. +func TestNode_put(t *testing.T) { + n := &node{inodes: make(inodes, 0), bucket: &Bucket{tx: &Tx{meta: &meta{pgid: 1}}}} + n.put([]byte("baz"), []byte("baz"), []byte("2"), 0, 0) + n.put([]byte("foo"), []byte("foo"), []byte("0"), 0, 0) + n.put([]byte("bar"), []byte("bar"), []byte("1"), 0, 0) + n.put([]byte("foo"), []byte("foo"), []byte("3"), 0, leafPageFlag) + + if len(n.inodes) != 3 { + t.Fatalf("exp=3; got=%d", len(n.inodes)) + } + if k, v := n.inodes[0].key, n.inodes[0].value; string(k) != "bar" || string(v) != "1" { + t.Fatalf("exp=; got=<%s,%s>", k, v) + } + if k, v := n.inodes[1].key, n.inodes[1].value; string(k) != "baz" || string(v) != "2" { + t.Fatalf("exp=; got=<%s,%s>", k, v) + } + if k, v := n.inodes[2].key, n.inodes[2].value; string(k) != "foo" || string(v) != "3" { + t.Fatalf("exp=; got=<%s,%s>", k, v) + } + if n.inodes[2].flags != uint32(leafPageFlag) { + t.Fatalf("not a leaf: %d", n.inodes[2].flags) + } +} + +// Ensure that a node can deserialize from a leaf page. +func TestNode_read_LeafPage(t *testing.T) { + // Create a page. + var buf [4096]byte + page := (*page)(unsafe.Pointer(&buf[0])) + page.flags = leafPageFlag + page.count = 2 + + // Insert 2 elements at the beginning. sizeof(leafPageElement) == 16 + nodes := (*[3]leafPageElement)(unsafe.Pointer(&page.ptr)) + nodes[0] = leafPageElement{flags: 0, pos: 32, ksize: 3, vsize: 4} // pos = sizeof(leafPageElement) * 2 + nodes[1] = leafPageElement{flags: 0, pos: 23, ksize: 10, vsize: 3} // pos = sizeof(leafPageElement) + 3 + 4 + + // Write data for the nodes at the end. + data := (*[4096]byte)(unsafe.Pointer(&nodes[2])) + copy(data[:], []byte("barfooz")) + copy(data[7:], []byte("helloworldbye")) + + // Deserialize page into a leaf. + n := &node{} + n.read(page) + + // Check that there are two inodes with correct data. + if !n.isLeaf { + t.Fatal("expected leaf") + } + if len(n.inodes) != 2 { + t.Fatalf("exp=2; got=%d", len(n.inodes)) + } + if k, v := n.inodes[0].key, n.inodes[0].value; string(k) != "bar" || string(v) != "fooz" { + t.Fatalf("exp=; got=<%s,%s>", k, v) + } + if k, v := n.inodes[1].key, n.inodes[1].value; string(k) != "helloworld" || string(v) != "bye" { + t.Fatalf("exp=; got=<%s,%s>", k, v) + } +} + +// Ensure that a node can serialize into a leaf page. +func TestNode_write_LeafPage(t *testing.T) { + // Create a node. + n := &node{isLeaf: true, inodes: make(inodes, 0), bucket: &Bucket{tx: &Tx{db: &DB{}, meta: &meta{pgid: 1}}}} + n.put([]byte("susy"), []byte("susy"), []byte("que"), 0, 0) + n.put([]byte("ricki"), []byte("ricki"), []byte("lake"), 0, 0) + n.put([]byte("john"), []byte("john"), []byte("johnson"), 0, 0) + + // Write it to a page. + var buf [4096]byte + p := (*page)(unsafe.Pointer(&buf[0])) + n.write(p) + + // Read the page back in. + n2 := &node{} + n2.read(p) + + // Check that the two pages are the same. + if len(n2.inodes) != 3 { + t.Fatalf("exp=3; got=%d", len(n2.inodes)) + } + if k, v := n2.inodes[0].key, n2.inodes[0].value; string(k) != "john" || string(v) != "johnson" { + t.Fatalf("exp=; got=<%s,%s>", k, v) + } + if k, v := n2.inodes[1].key, n2.inodes[1].value; string(k) != "ricki" || string(v) != "lake" { + t.Fatalf("exp=; got=<%s,%s>", k, v) + } + if k, v := n2.inodes[2].key, n2.inodes[2].value; string(k) != "susy" || string(v) != "que" { + t.Fatalf("exp=; got=<%s,%s>", k, v) + } +} + +// Ensure that a node can split into appropriate subgroups. +func TestNode_split(t *testing.T) { + // Create a node. + n := &node{inodes: make(inodes, 0), bucket: &Bucket{tx: &Tx{db: &DB{}, meta: &meta{pgid: 1}}}} + n.put([]byte("00000001"), []byte("00000001"), []byte("0123456701234567"), 0, 0) + n.put([]byte("00000002"), []byte("00000002"), []byte("0123456701234567"), 0, 0) + n.put([]byte("00000003"), []byte("00000003"), []byte("0123456701234567"), 0, 0) + n.put([]byte("00000004"), []byte("00000004"), []byte("0123456701234567"), 0, 0) + n.put([]byte("00000005"), []byte("00000005"), []byte("0123456701234567"), 0, 0) + + // Split between 2 & 3. + n.split(100) + + var parent = n.parent + if len(parent.children) != 2 { + t.Fatalf("exp=2; got=%d", len(parent.children)) + } + if len(parent.children[0].inodes) != 2 { + t.Fatalf("exp=2; got=%d", len(parent.children[0].inodes)) + } + if len(parent.children[1].inodes) != 3 { + t.Fatalf("exp=3; got=%d", len(parent.children[1].inodes)) + } +} + +// Ensure that a page with the minimum number of inodes just returns a single node. +func TestNode_split_MinKeys(t *testing.T) { + // Create a node. + n := &node{inodes: make(inodes, 0), bucket: &Bucket{tx: &Tx{db: &DB{}, meta: &meta{pgid: 1}}}} + n.put([]byte("00000001"), []byte("00000001"), []byte("0123456701234567"), 0, 0) + n.put([]byte("00000002"), []byte("00000002"), []byte("0123456701234567"), 0, 0) + + // Split. + n.split(20) + if n.parent != nil { + t.Fatalf("expected nil parent") + } +} + +// Ensure that a node that has keys that all fit on a page just returns one leaf. +func TestNode_split_SinglePage(t *testing.T) { + // Create a node. + n := &node{inodes: make(inodes, 0), bucket: &Bucket{tx: &Tx{db: &DB{}, meta: &meta{pgid: 1}}}} + n.put([]byte("00000001"), []byte("00000001"), []byte("0123456701234567"), 0, 0) + n.put([]byte("00000002"), []byte("00000002"), []byte("0123456701234567"), 0, 0) + n.put([]byte("00000003"), []byte("00000003"), []byte("0123456701234567"), 0, 0) + n.put([]byte("00000004"), []byte("00000004"), []byte("0123456701234567"), 0, 0) + n.put([]byte("00000005"), []byte("00000005"), []byte("0123456701234567"), 0, 0) + + // Split. + n.split(4096) + if n.parent != nil { + t.Fatalf("expected nil parent") + } +} diff --git a/vendor/github.com/boltdb/bolt/page.go b/vendor/github.com/boltdb/bolt/page.go new file mode 100644 index 00000000..cde403ae --- /dev/null +++ b/vendor/github.com/boltdb/bolt/page.go @@ -0,0 +1,197 @@ +package bolt + +import ( + "fmt" + "os" + "sort" + "unsafe" +) + +const pageHeaderSize = int(unsafe.Offsetof(((*page)(nil)).ptr)) + +const minKeysPerPage = 2 + +const branchPageElementSize = int(unsafe.Sizeof(branchPageElement{})) +const leafPageElementSize = int(unsafe.Sizeof(leafPageElement{})) + +const ( + branchPageFlag = 0x01 + leafPageFlag = 0x02 + metaPageFlag = 0x04 + freelistPageFlag = 0x10 +) + +const ( + bucketLeafFlag = 0x01 +) + +type pgid uint64 + +type page struct { + id pgid + flags uint16 + count uint16 + overflow uint32 + ptr uintptr +} + +// typ returns a human readable page type string used for debugging. +func (p *page) typ() string { + if (p.flags & branchPageFlag) != 0 { + return "branch" + } else if (p.flags & leafPageFlag) != 0 { + return "leaf" + } else if (p.flags & metaPageFlag) != 0 { + return "meta" + } else if (p.flags & freelistPageFlag) != 0 { + return "freelist" + } + return fmt.Sprintf("unknown<%02x>", p.flags) +} + +// meta returns a pointer to the metadata section of the page. +func (p *page) meta() *meta { + return (*meta)(unsafe.Pointer(&p.ptr)) +} + +// leafPageElement retrieves the leaf node by index +func (p *page) leafPageElement(index uint16) *leafPageElement { + n := &((*[0x7FFFFFF]leafPageElement)(unsafe.Pointer(&p.ptr)))[index] + return n +} + +// leafPageElements retrieves a list of leaf nodes. +func (p *page) leafPageElements() []leafPageElement { + if p.count == 0 { + return nil + } + return ((*[0x7FFFFFF]leafPageElement)(unsafe.Pointer(&p.ptr)))[:] +} + +// branchPageElement retrieves the branch node by index +func (p *page) branchPageElement(index uint16) *branchPageElement { + return &((*[0x7FFFFFF]branchPageElement)(unsafe.Pointer(&p.ptr)))[index] +} + +// branchPageElements retrieves a list of branch nodes. +func (p *page) branchPageElements() []branchPageElement { + if p.count == 0 { + return nil + } + return ((*[0x7FFFFFF]branchPageElement)(unsafe.Pointer(&p.ptr)))[:] +} + +// dump writes n bytes of the page to STDERR as hex output. +func (p *page) hexdump(n int) { + buf := (*[maxAllocSize]byte)(unsafe.Pointer(p))[:n] + fmt.Fprintf(os.Stderr, "%x\n", buf) +} + +type pages []*page + +func (s pages) Len() int { return len(s) } +func (s pages) Swap(i, j int) { s[i], s[j] = s[j], s[i] } +func (s pages) Less(i, j int) bool { return s[i].id < s[j].id } + +// branchPageElement represents a node on a branch page. +type branchPageElement struct { + pos uint32 + ksize uint32 + pgid pgid +} + +// key returns a byte slice of the node key. +func (n *branchPageElement) key() []byte { + buf := (*[maxAllocSize]byte)(unsafe.Pointer(n)) + return (*[maxAllocSize]byte)(unsafe.Pointer(&buf[n.pos]))[:n.ksize] +} + +// leafPageElement represents a node on a leaf page. +type leafPageElement struct { + flags uint32 + pos uint32 + ksize uint32 + vsize uint32 +} + +// key returns a byte slice of the node key. +func (n *leafPageElement) key() []byte { + buf := (*[maxAllocSize]byte)(unsafe.Pointer(n)) + return (*[maxAllocSize]byte)(unsafe.Pointer(&buf[n.pos]))[:n.ksize:n.ksize] +} + +// value returns a byte slice of the node value. +func (n *leafPageElement) value() []byte { + buf := (*[maxAllocSize]byte)(unsafe.Pointer(n)) + return (*[maxAllocSize]byte)(unsafe.Pointer(&buf[n.pos+n.ksize]))[:n.vsize:n.vsize] +} + +// PageInfo represents human readable information about a page. +type PageInfo struct { + ID int + Type string + Count int + OverflowCount int +} + +type pgids []pgid + +func (s pgids) Len() int { return len(s) } +func (s pgids) Swap(i, j int) { s[i], s[j] = s[j], s[i] } +func (s pgids) Less(i, j int) bool { return s[i] < s[j] } + +// merge returns the sorted union of a and b. +func (a pgids) merge(b pgids) pgids { + // Return the opposite slice if one is nil. + if len(a) == 0 { + return b + } + if len(b) == 0 { + return a + } + merged := make(pgids, len(a)+len(b)) + mergepgids(merged, a, b) + return merged +} + +// mergepgids copies the sorted union of a and b into dst. +// If dst is too small, it panics. +func mergepgids(dst, a, b pgids) { + if len(dst) < len(a)+len(b) { + panic(fmt.Errorf("mergepgids bad len %d < %d + %d", len(dst), len(a), len(b))) + } + // Copy in the opposite slice if one is nil. + if len(a) == 0 { + copy(dst, b) + return + } + if len(b) == 0 { + copy(dst, a) + return + } + + // Merged will hold all elements from both lists. + merged := dst[:0] + + // Assign lead to the slice with a lower starting value, follow to the higher value. + lead, follow := a, b + if b[0] < a[0] { + lead, follow = b, a + } + + // Continue while there are elements in the lead. + for len(lead) > 0 { + // Merge largest prefix of lead that is ahead of follow[0]. + n := sort.Search(len(lead), func(i int) bool { return lead[i] > follow[0] }) + merged = append(merged, lead[:n]...) + if n >= len(lead) { + break + } + + // Swap lead and follow. + lead, follow = follow, lead[n:] + } + + // Append what's left in follow. + _ = append(merged, follow...) +} diff --git a/vendor/github.com/boltdb/bolt/page_test.go b/vendor/github.com/boltdb/bolt/page_test.go new file mode 100644 index 00000000..59f4a30e --- /dev/null +++ b/vendor/github.com/boltdb/bolt/page_test.go @@ -0,0 +1,72 @@ +package bolt + +import ( + "reflect" + "sort" + "testing" + "testing/quick" +) + +// Ensure that the page type can be returned in human readable format. +func TestPage_typ(t *testing.T) { + if typ := (&page{flags: branchPageFlag}).typ(); typ != "branch" { + t.Fatalf("exp=branch; got=%v", typ) + } + if typ := (&page{flags: leafPageFlag}).typ(); typ != "leaf" { + t.Fatalf("exp=leaf; got=%v", typ) + } + if typ := (&page{flags: metaPageFlag}).typ(); typ != "meta" { + t.Fatalf("exp=meta; got=%v", typ) + } + if typ := (&page{flags: freelistPageFlag}).typ(); typ != "freelist" { + t.Fatalf("exp=freelist; got=%v", typ) + } + if typ := (&page{flags: 20000}).typ(); typ != "unknown<4e20>" { + t.Fatalf("exp=unknown<4e20>; got=%v", typ) + } +} + +// Ensure that the hexdump debugging function doesn't blow up. +func TestPage_dump(t *testing.T) { + (&page{id: 256}).hexdump(16) +} + +func TestPgids_merge(t *testing.T) { + a := pgids{4, 5, 6, 10, 11, 12, 13, 27} + b := pgids{1, 3, 8, 9, 25, 30} + c := a.merge(b) + if !reflect.DeepEqual(c, pgids{1, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 25, 27, 30}) { + t.Errorf("mismatch: %v", c) + } + + a = pgids{4, 5, 6, 10, 11, 12, 13, 27, 35, 36} + b = pgids{8, 9, 25, 30} + c = a.merge(b) + if !reflect.DeepEqual(c, pgids{4, 5, 6, 8, 9, 10, 11, 12, 13, 25, 27, 30, 35, 36}) { + t.Errorf("mismatch: %v", c) + } +} + +func TestPgids_merge_quick(t *testing.T) { + if err := quick.Check(func(a, b pgids) bool { + // Sort incoming lists. + sort.Sort(a) + sort.Sort(b) + + // Merge the two lists together. + got := a.merge(b) + + // The expected value should be the two lists combined and sorted. + exp := append(a, b...) + sort.Sort(exp) + + if !reflect.DeepEqual(exp, got) { + t.Errorf("\nexp=%+v\ngot=%+v\n", exp, got) + return false + } + + return true + }, nil); err != nil { + t.Fatal(err) + } +} diff --git a/vendor/github.com/boltdb/bolt/quick_test.go b/vendor/github.com/boltdb/bolt/quick_test.go new file mode 100644 index 00000000..9e27792e --- /dev/null +++ b/vendor/github.com/boltdb/bolt/quick_test.go @@ -0,0 +1,87 @@ +package bolt_test + +import ( + "bytes" + "flag" + "fmt" + "math/rand" + "os" + "reflect" + "testing/quick" + "time" +) + +// testing/quick defaults to 5 iterations and a random seed. +// You can override these settings from the command line: +// +// -quick.count The number of iterations to perform. +// -quick.seed The seed to use for randomizing. +// -quick.maxitems The maximum number of items to insert into a DB. +// -quick.maxksize The maximum size of a key. +// -quick.maxvsize The maximum size of a value. +// + +var qcount, qseed, qmaxitems, qmaxksize, qmaxvsize int + +func init() { + flag.IntVar(&qcount, "quick.count", 5, "") + flag.IntVar(&qseed, "quick.seed", int(time.Now().UnixNano())%100000, "") + flag.IntVar(&qmaxitems, "quick.maxitems", 1000, "") + flag.IntVar(&qmaxksize, "quick.maxksize", 1024, "") + flag.IntVar(&qmaxvsize, "quick.maxvsize", 1024, "") + flag.Parse() + fmt.Fprintln(os.Stderr, "seed:", qseed) + fmt.Fprintf(os.Stderr, "quick settings: count=%v, items=%v, ksize=%v, vsize=%v\n", qcount, qmaxitems, qmaxksize, qmaxvsize) +} + +func qconfig() *quick.Config { + return &quick.Config{ + MaxCount: qcount, + Rand: rand.New(rand.NewSource(int64(qseed))), + } +} + +type testdata []testdataitem + +func (t testdata) Len() int { return len(t) } +func (t testdata) Swap(i, j int) { t[i], t[j] = t[j], t[i] } +func (t testdata) Less(i, j int) bool { return bytes.Compare(t[i].Key, t[j].Key) == -1 } + +func (t testdata) Generate(rand *rand.Rand, size int) reflect.Value { + n := rand.Intn(qmaxitems-1) + 1 + items := make(testdata, n) + used := make(map[string]bool) + for i := 0; i < n; i++ { + item := &items[i] + // Ensure that keys are unique by looping until we find one that we have not already used. + for { + item.Key = randByteSlice(rand, 1, qmaxksize) + if !used[string(item.Key)] { + used[string(item.Key)] = true + break + } + } + item.Value = randByteSlice(rand, 0, qmaxvsize) + } + return reflect.ValueOf(items) +} + +type revtestdata []testdataitem + +func (t revtestdata) Len() int { return len(t) } +func (t revtestdata) Swap(i, j int) { t[i], t[j] = t[j], t[i] } +func (t revtestdata) Less(i, j int) bool { return bytes.Compare(t[i].Key, t[j].Key) == 1 } + +type testdataitem struct { + Key []byte + Value []byte +} + +func randByteSlice(rand *rand.Rand, minSize, maxSize int) []byte { + n := rand.Intn(maxSize-minSize) + minSize + b := make([]byte, n) + for i := 0; i < n; i++ { + b[i] = byte(rand.Intn(255)) + } + return b +} diff --git a/vendor/github.com/boltdb/bolt/simulation_test.go b/vendor/github.com/boltdb/bolt/simulation_test.go new file mode 100644 index 00000000..38310165 --- /dev/null +++ b/vendor/github.com/boltdb/bolt/simulation_test.go @@ -0,0 +1,329 @@ +package bolt_test + +import ( + "bytes" + "fmt" + "math/rand" + "sync" + "testing" + + "github.com/boltdb/bolt" +) + +func TestSimulate_1op_1p(t *testing.T) { testSimulate(t, 1, 1) } +func TestSimulate_10op_1p(t *testing.T) { testSimulate(t, 10, 1) } +func TestSimulate_100op_1p(t *testing.T) { testSimulate(t, 100, 1) } +func TestSimulate_1000op_1p(t *testing.T) { testSimulate(t, 1000, 1) } +func TestSimulate_10000op_1p(t *testing.T) { testSimulate(t, 10000, 1) } + +func TestSimulate_10op_10p(t *testing.T) { testSimulate(t, 10, 10) } +func TestSimulate_100op_10p(t *testing.T) { testSimulate(t, 100, 10) } +func TestSimulate_1000op_10p(t *testing.T) { testSimulate(t, 1000, 10) } +func TestSimulate_10000op_10p(t *testing.T) { testSimulate(t, 10000, 10) } + +func TestSimulate_100op_100p(t *testing.T) { testSimulate(t, 100, 100) } +func TestSimulate_1000op_100p(t *testing.T) { testSimulate(t, 1000, 100) } +func TestSimulate_10000op_100p(t *testing.T) { testSimulate(t, 10000, 100) } + +func TestSimulate_10000op_1000p(t *testing.T) { testSimulate(t, 10000, 1000) } + +// Randomly generate operations on a given database with multiple clients to ensure consistency and thread safety. +func testSimulate(t *testing.T, threadCount, parallelism int) { + if testing.Short() { + t.Skip("skipping test in short mode.") + } + + rand.Seed(int64(qseed)) + + // A list of operations that readers and writers can perform. + var readerHandlers = []simulateHandler{simulateGetHandler} + var writerHandlers = []simulateHandler{simulateGetHandler, simulatePutHandler} + + var versions = make(map[int]*QuickDB) + versions[1] = NewQuickDB() + + db := MustOpenDB() + defer db.MustClose() + + var mutex sync.Mutex + + // Run n threads in parallel, each with their own operation. + var wg sync.WaitGroup + var threads = make(chan bool, parallelism) + var i int + for { + threads <- true + wg.Add(1) + writable := ((rand.Int() % 100) < 20) // 20% writers + + // Choose an operation to execute. + var handler simulateHandler + if writable { + handler = writerHandlers[rand.Intn(len(writerHandlers))] + } else { + handler = readerHandlers[rand.Intn(len(readerHandlers))] + } + + // Execute a thread for the given operation. + go func(writable bool, handler simulateHandler) { + defer wg.Done() + + // Start transaction. + tx, err := db.Begin(writable) + if err != nil { + t.Fatal("tx begin: ", err) + } + + // Obtain current state of the dataset. + mutex.Lock() + var qdb = versions[tx.ID()] + if writable { + qdb = versions[tx.ID()-1].Copy() + } + mutex.Unlock() + + // Make sure we commit/rollback the tx at the end and update the state. + if writable { + defer func() { + mutex.Lock() + versions[tx.ID()] = qdb + mutex.Unlock() + + if err := tx.Commit(); err != nil { + t.Fatal(err) + } + }() + } else { + defer func() { _ = tx.Rollback() }() + } + + // Ignore operation if we don't have data yet. + if qdb == nil { + return + } + + // Execute handler. + handler(tx, qdb) + + // Release a thread back to the scheduling loop. + <-threads + }(writable, handler) + + i++ + if i > threadCount { + break + } + } + + // Wait until all threads are done. + wg.Wait() +} + +type simulateHandler func(tx *bolt.Tx, qdb *QuickDB) + +// Retrieves a key from the database and verifies that it is what is expected. +func simulateGetHandler(tx *bolt.Tx, qdb *QuickDB) { + // Randomly retrieve an existing exist. + keys := qdb.Rand() + if len(keys) == 0 { + return + } + + // Retrieve root bucket. + b := tx.Bucket(keys[0]) + if b == nil { + panic(fmt.Sprintf("bucket[0] expected: %08x\n", trunc(keys[0], 4))) + } + + // Drill into nested buckets. + for _, key := range keys[1 : len(keys)-1] { + b = b.Bucket(key) + if b == nil { + panic(fmt.Sprintf("bucket[n] expected: %v -> %v\n", keys, key)) + } + } + + // Verify key/value on the final bucket. + expected := qdb.Get(keys) + actual := b.Get(keys[len(keys)-1]) + if !bytes.Equal(actual, expected) { + fmt.Println("=== EXPECTED ===") + fmt.Println(expected) + fmt.Println("=== ACTUAL ===") + fmt.Println(actual) + fmt.Println("=== END ===") + panic("value mismatch") + } +} + +// Inserts a key into the database. +func simulatePutHandler(tx *bolt.Tx, qdb *QuickDB) { + var err error + keys, value := randKeys(), randValue() + + // Retrieve root bucket. + b := tx.Bucket(keys[0]) + if b == nil { + b, err = tx.CreateBucket(keys[0]) + if err != nil { + panic("create bucket: " + err.Error()) + } + } + + // Create nested buckets, if necessary. + for _, key := range keys[1 : len(keys)-1] { + child := b.Bucket(key) + if child != nil { + b = child + } else { + b, err = b.CreateBucket(key) + if err != nil { + panic("create bucket: " + err.Error()) + } + } + } + + // Insert into database. + if err := b.Put(keys[len(keys)-1], value); err != nil { + panic("put: " + err.Error()) + } + + // Insert into in-memory database. + qdb.Put(keys, value) +} + +// QuickDB is an in-memory database that replicates the functionality of the +// Bolt DB type except that it is entirely in-memory. It is meant for testing +// that the Bolt database is consistent. +type QuickDB struct { + sync.RWMutex + m map[string]interface{} +} + +// NewQuickDB returns an instance of QuickDB. +func NewQuickDB() *QuickDB { + return &QuickDB{m: make(map[string]interface{})} +} + +// Get retrieves the value at a key path. +func (db *QuickDB) Get(keys [][]byte) []byte { + db.RLock() + defer db.RUnlock() + + m := db.m + for _, key := range keys[:len(keys)-1] { + value := m[string(key)] + if value == nil { + return nil + } + switch value := value.(type) { + case map[string]interface{}: + m = value + case []byte: + return nil + } + } + + // Only return if it's a simple value. + if value, ok := m[string(keys[len(keys)-1])].([]byte); ok { + return value + } + return nil +} + +// Put inserts a value into a key path. +func (db *QuickDB) Put(keys [][]byte, value []byte) { + db.Lock() + defer db.Unlock() + + // Build buckets all the way down the key path. + m := db.m + for _, key := range keys[:len(keys)-1] { + if _, ok := m[string(key)].([]byte); ok { + return // Keypath intersects with a simple value. Do nothing. + } + + if m[string(key)] == nil { + m[string(key)] = make(map[string]interface{}) + } + m = m[string(key)].(map[string]interface{}) + } + + // Insert value into the last key. + m[string(keys[len(keys)-1])] = value +} + +// Rand returns a random key path that points to a simple value. +func (db *QuickDB) Rand() [][]byte { + db.RLock() + defer db.RUnlock() + if len(db.m) == 0 { + return nil + } + var keys [][]byte + db.rand(db.m, &keys) + return keys +} + +func (db *QuickDB) rand(m map[string]interface{}, keys *[][]byte) { + i, index := 0, rand.Intn(len(m)) + for k, v := range m { + if i == index { + *keys = append(*keys, []byte(k)) + if v, ok := v.(map[string]interface{}); ok { + db.rand(v, keys) + } + return + } + i++ + } + panic("quickdb rand: out-of-range") +} + +// Copy copies the entire database. +func (db *QuickDB) Copy() *QuickDB { + db.RLock() + defer db.RUnlock() + return &QuickDB{m: db.copy(db.m)} +} + +func (db *QuickDB) copy(m map[string]interface{}) map[string]interface{} { + clone := make(map[string]interface{}, len(m)) + for k, v := range m { + switch v := v.(type) { + case map[string]interface{}: + clone[k] = db.copy(v) + default: + clone[k] = v + } + } + return clone +} + +func randKey() []byte { + var min, max = 1, 1024 + n := rand.Intn(max-min) + min + b := make([]byte, n) + for i := 0; i < n; i++ { + b[i] = byte(rand.Intn(255)) + } + return b +} + +func randKeys() [][]byte { + var keys [][]byte + var count = rand.Intn(2) + 2 + for i := 0; i < count; i++ { + keys = append(keys, randKey()) + } + return keys +} + +func randValue() []byte { + n := rand.Intn(8192) + b := make([]byte, n) + for i := 0; i < n; i++ { + b[i] = byte(rand.Intn(255)) + } + return b +} diff --git a/vendor/github.com/boltdb/bolt/tx.go b/vendor/github.com/boltdb/bolt/tx.go new file mode 100644 index 00000000..6700308a --- /dev/null +++ b/vendor/github.com/boltdb/bolt/tx.go @@ -0,0 +1,684 @@ +package bolt + +import ( + "fmt" + "io" + "os" + "sort" + "strings" + "time" + "unsafe" +) + +// txid represents the internal transaction identifier. +type txid uint64 + +// Tx represents a read-only or read/write transaction on the database. +// Read-only transactions can be used for retrieving values for keys and creating cursors. +// Read/write transactions can create and remove buckets and create and remove keys. +// +// IMPORTANT: You must commit or rollback transactions when you are done with +// them. Pages can not be reclaimed by the writer until no more transactions +// are using them. A long running read transaction can cause the database to +// quickly grow. +type Tx struct { + writable bool + managed bool + db *DB + meta *meta + root Bucket + pages map[pgid]*page + stats TxStats + commitHandlers []func() + + // WriteFlag specifies the flag for write-related methods like WriteTo(). + // Tx opens the database file with the specified flag to copy the data. + // + // By default, the flag is unset, which works well for mostly in-memory + // workloads. For databases that are much larger than available RAM, + // set the flag to syscall.O_DIRECT to avoid trashing the page cache. + WriteFlag int +} + +// init initializes the transaction. +func (tx *Tx) init(db *DB) { + tx.db = db + tx.pages = nil + + // Copy the meta page since it can be changed by the writer. + tx.meta = &meta{} + db.meta().copy(tx.meta) + + // Copy over the root bucket. + tx.root = newBucket(tx) + tx.root.bucket = &bucket{} + *tx.root.bucket = tx.meta.root + + // Increment the transaction id and add a page cache for writable transactions. + if tx.writable { + tx.pages = make(map[pgid]*page) + tx.meta.txid += txid(1) + } +} + +// ID returns the transaction id. +func (tx *Tx) ID() int { + return int(tx.meta.txid) +} + +// DB returns a reference to the database that created the transaction. +func (tx *Tx) DB() *DB { + return tx.db +} + +// Size returns current database size in bytes as seen by this transaction. +func (tx *Tx) Size() int64 { + return int64(tx.meta.pgid) * int64(tx.db.pageSize) +} + +// Writable returns whether the transaction can perform write operations. +func (tx *Tx) Writable() bool { + return tx.writable +} + +// Cursor creates a cursor associated with the root bucket. +// All items in the cursor will return a nil value because all root bucket keys point to buckets. +// The cursor is only valid as long as the transaction is open. +// Do not use a cursor after the transaction is closed. +func (tx *Tx) Cursor() *Cursor { + return tx.root.Cursor() +} + +// Stats retrieves a copy of the current transaction statistics. +func (tx *Tx) Stats() TxStats { + return tx.stats +} + +// Bucket retrieves a bucket by name. +// Returns nil if the bucket does not exist. +// The bucket instance is only valid for the lifetime of the transaction. +func (tx *Tx) Bucket(name []byte) *Bucket { + return tx.root.Bucket(name) +} + +// CreateBucket creates a new bucket. +// Returns an error if the bucket already exists, if the bucket name is blank, or if the bucket name is too long. +// The bucket instance is only valid for the lifetime of the transaction. +func (tx *Tx) CreateBucket(name []byte) (*Bucket, error) { + return tx.root.CreateBucket(name) +} + +// CreateBucketIfNotExists creates a new bucket if it doesn't already exist. +// Returns an error if the bucket name is blank, or if the bucket name is too long. +// The bucket instance is only valid for the lifetime of the transaction. +func (tx *Tx) CreateBucketIfNotExists(name []byte) (*Bucket, error) { + return tx.root.CreateBucketIfNotExists(name) +} + +// DeleteBucket deletes a bucket. +// Returns an error if the bucket cannot be found or if the key represents a non-bucket value. +func (tx *Tx) DeleteBucket(name []byte) error { + return tx.root.DeleteBucket(name) +} + +// ForEach executes a function for each bucket in the root. +// If the provided function returns an error then the iteration is stopped and +// the error is returned to the caller. +func (tx *Tx) ForEach(fn func(name []byte, b *Bucket) error) error { + return tx.root.ForEach(func(k, v []byte) error { + if err := fn(k, tx.root.Bucket(k)); err != nil { + return err + } + return nil + }) +} + +// OnCommit adds a handler function to be executed after the transaction successfully commits. +func (tx *Tx) OnCommit(fn func()) { + tx.commitHandlers = append(tx.commitHandlers, fn) +} + +// Commit writes all changes to disk and updates the meta page. +// Returns an error if a disk write error occurs, or if Commit is +// called on a read-only transaction. +func (tx *Tx) Commit() error { + _assert(!tx.managed, "managed tx commit not allowed") + if tx.db == nil { + return ErrTxClosed + } else if !tx.writable { + return ErrTxNotWritable + } + + // TODO(benbjohnson): Use vectorized I/O to write out dirty pages. + + // Rebalance nodes which have had deletions. + var startTime = time.Now() + tx.root.rebalance() + if tx.stats.Rebalance > 0 { + tx.stats.RebalanceTime += time.Since(startTime) + } + + // spill data onto dirty pages. + startTime = time.Now() + if err := tx.root.spill(); err != nil { + tx.rollback() + return err + } + tx.stats.SpillTime += time.Since(startTime) + + // Free the old root bucket. + tx.meta.root.root = tx.root.root + + opgid := tx.meta.pgid + + // Free the freelist and allocate new pages for it. This will overestimate + // the size of the freelist but not underestimate the size (which would be bad). + tx.db.freelist.free(tx.meta.txid, tx.db.page(tx.meta.freelist)) + p, err := tx.allocate((tx.db.freelist.size() / tx.db.pageSize) + 1) + if err != nil { + tx.rollback() + return err + } + if err := tx.db.freelist.write(p); err != nil { + tx.rollback() + return err + } + tx.meta.freelist = p.id + + // If the high water mark has moved up then attempt to grow the database. + if tx.meta.pgid > opgid { + if err := tx.db.grow(int(tx.meta.pgid+1) * tx.db.pageSize); err != nil { + tx.rollback() + return err + } + } + + // Write dirty pages to disk. + startTime = time.Now() + if err := tx.write(); err != nil { + tx.rollback() + return err + } + + // If strict mode is enabled then perform a consistency check. + // Only the first consistency error is reported in the panic. + if tx.db.StrictMode { + ch := tx.Check() + var errs []string + for { + err, ok := <-ch + if !ok { + break + } + errs = append(errs, err.Error()) + } + if len(errs) > 0 { + panic("check fail: " + strings.Join(errs, "\n")) + } + } + + // Write meta to disk. + if err := tx.writeMeta(); err != nil { + tx.rollback() + return err + } + tx.stats.WriteTime += time.Since(startTime) + + // Finalize the transaction. + tx.close() + + // Execute commit handlers now that the locks have been removed. + for _, fn := range tx.commitHandlers { + fn() + } + + return nil +} + +// Rollback closes the transaction and ignores all previous updates. Read-only +// transactions must be rolled back and not committed. +func (tx *Tx) Rollback() error { + _assert(!tx.managed, "managed tx rollback not allowed") + if tx.db == nil { + return ErrTxClosed + } + tx.rollback() + return nil +} + +func (tx *Tx) rollback() { + if tx.db == nil { + return + } + if tx.writable { + tx.db.freelist.rollback(tx.meta.txid) + tx.db.freelist.reload(tx.db.page(tx.db.meta().freelist)) + } + tx.close() +} + +func (tx *Tx) close() { + if tx.db == nil { + return + } + if tx.writable { + // Grab freelist stats. + var freelistFreeN = tx.db.freelist.free_count() + var freelistPendingN = tx.db.freelist.pending_count() + var freelistAlloc = tx.db.freelist.size() + + // Remove transaction ref & writer lock. + tx.db.rwtx = nil + tx.db.rwlock.Unlock() + + // Merge statistics. + tx.db.statlock.Lock() + tx.db.stats.FreePageN = freelistFreeN + tx.db.stats.PendingPageN = freelistPendingN + tx.db.stats.FreeAlloc = (freelistFreeN + freelistPendingN) * tx.db.pageSize + tx.db.stats.FreelistInuse = freelistAlloc + tx.db.stats.TxStats.add(&tx.stats) + tx.db.statlock.Unlock() + } else { + tx.db.removeTx(tx) + } + + // Clear all references. + tx.db = nil + tx.meta = nil + tx.root = Bucket{tx: tx} + tx.pages = nil +} + +// Copy writes the entire database to a writer. +// This function exists for backwards compatibility. Use WriteTo() instead. +func (tx *Tx) Copy(w io.Writer) error { + _, err := tx.WriteTo(w) + return err +} + +// WriteTo writes the entire database to a writer. +// If err == nil then exactly tx.Size() bytes will be written into the writer. +func (tx *Tx) WriteTo(w io.Writer) (n int64, err error) { + // Attempt to open reader with WriteFlag + f, err := os.OpenFile(tx.db.path, os.O_RDONLY|tx.WriteFlag, 0) + if err != nil { + return 0, err + } + defer func() { _ = f.Close() }() + + // Generate a meta page. We use the same page data for both meta pages. + buf := make([]byte, tx.db.pageSize) + page := (*page)(unsafe.Pointer(&buf[0])) + page.flags = metaPageFlag + *page.meta() = *tx.meta + + // Write meta 0. + page.id = 0 + page.meta().checksum = page.meta().sum64() + nn, err := w.Write(buf) + n += int64(nn) + if err != nil { + return n, fmt.Errorf("meta 0 copy: %s", err) + } + + // Write meta 1 with a lower transaction id. + page.id = 1 + page.meta().txid -= 1 + page.meta().checksum = page.meta().sum64() + nn, err = w.Write(buf) + n += int64(nn) + if err != nil { + return n, fmt.Errorf("meta 1 copy: %s", err) + } + + // Move past the meta pages in the file. + if _, err := f.Seek(int64(tx.db.pageSize*2), os.SEEK_SET); err != nil { + return n, fmt.Errorf("seek: %s", err) + } + + // Copy data pages. + wn, err := io.CopyN(w, f, tx.Size()-int64(tx.db.pageSize*2)) + n += wn + if err != nil { + return n, err + } + + return n, f.Close() +} + +// CopyFile copies the entire database to file at the given path. +// A reader transaction is maintained during the copy so it is safe to continue +// using the database while a copy is in progress. +func (tx *Tx) CopyFile(path string, mode os.FileMode) error { + f, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_TRUNC, mode) + if err != nil { + return err + } + + err = tx.Copy(f) + if err != nil { + _ = f.Close() + return err + } + return f.Close() +} + +// Check performs several consistency checks on the database for this transaction. +// An error is returned if any inconsistency is found. +// +// It can be safely run concurrently on a writable transaction. However, this +// incurs a high cost for large databases and databases with a lot of subbuckets +// because of caching. This overhead can be removed if running on a read-only +// transaction, however, it is not safe to execute other writer transactions at +// the same time. +func (tx *Tx) Check() <-chan error { + ch := make(chan error) + go tx.check(ch) + return ch +} + +func (tx *Tx) check(ch chan error) { + // Check if any pages are double freed. + freed := make(map[pgid]bool) + all := make([]pgid, tx.db.freelist.count()) + tx.db.freelist.copyall(all) + for _, id := range all { + if freed[id] { + ch <- fmt.Errorf("page %d: already freed", id) + } + freed[id] = true + } + + // Track every reachable page. + reachable := make(map[pgid]*page) + reachable[0] = tx.page(0) // meta0 + reachable[1] = tx.page(1) // meta1 + for i := uint32(0); i <= tx.page(tx.meta.freelist).overflow; i++ { + reachable[tx.meta.freelist+pgid(i)] = tx.page(tx.meta.freelist) + } + + // Recursively check buckets. + tx.checkBucket(&tx.root, reachable, freed, ch) + + // Ensure all pages below high water mark are either reachable or freed. + for i := pgid(0); i < tx.meta.pgid; i++ { + _, isReachable := reachable[i] + if !isReachable && !freed[i] { + ch <- fmt.Errorf("page %d: unreachable unfreed", int(i)) + } + } + + // Close the channel to signal completion. + close(ch) +} + +func (tx *Tx) checkBucket(b *Bucket, reachable map[pgid]*page, freed map[pgid]bool, ch chan error) { + // Ignore inline buckets. + if b.root == 0 { + return + } + + // Check every page used by this bucket. + b.tx.forEachPage(b.root, 0, func(p *page, _ int) { + if p.id > tx.meta.pgid { + ch <- fmt.Errorf("page %d: out of bounds: %d", int(p.id), int(b.tx.meta.pgid)) + } + + // Ensure each page is only referenced once. + for i := pgid(0); i <= pgid(p.overflow); i++ { + var id = p.id + i + if _, ok := reachable[id]; ok { + ch <- fmt.Errorf("page %d: multiple references", int(id)) + } + reachable[id] = p + } + + // We should only encounter un-freed leaf and branch pages. + if freed[p.id] { + ch <- fmt.Errorf("page %d: reachable freed", int(p.id)) + } else if (p.flags&branchPageFlag) == 0 && (p.flags&leafPageFlag) == 0 { + ch <- fmt.Errorf("page %d: invalid type: %s", int(p.id), p.typ()) + } + }) + + // Check each bucket within this bucket. + _ = b.ForEach(func(k, v []byte) error { + if child := b.Bucket(k); child != nil { + tx.checkBucket(child, reachable, freed, ch) + } + return nil + }) +} + +// allocate returns a contiguous block of memory starting at a given page. +func (tx *Tx) allocate(count int) (*page, error) { + p, err := tx.db.allocate(count) + if err != nil { + return nil, err + } + + // Save to our page cache. + tx.pages[p.id] = p + + // Update statistics. + tx.stats.PageCount++ + tx.stats.PageAlloc += count * tx.db.pageSize + + return p, nil +} + +// write writes any dirty pages to disk. +func (tx *Tx) write() error { + // Sort pages by id. + pages := make(pages, 0, len(tx.pages)) + for _, p := range tx.pages { + pages = append(pages, p) + } + // Clear out page cache early. + tx.pages = make(map[pgid]*page) + sort.Sort(pages) + + // Write pages to disk in order. + for _, p := range pages { + size := (int(p.overflow) + 1) * tx.db.pageSize + offset := int64(p.id) * int64(tx.db.pageSize) + + // Write out page in "max allocation" sized chunks. + ptr := (*[maxAllocSize]byte)(unsafe.Pointer(p)) + for { + // Limit our write to our max allocation size. + sz := size + if sz > maxAllocSize-1 { + sz = maxAllocSize - 1 + } + + // Write chunk to disk. + buf := ptr[:sz] + if _, err := tx.db.ops.writeAt(buf, offset); err != nil { + return err + } + + // Update statistics. + tx.stats.Write++ + + // Exit inner for loop if we've written all the chunks. + size -= sz + if size == 0 { + break + } + + // Otherwise move offset forward and move pointer to next chunk. + offset += int64(sz) + ptr = (*[maxAllocSize]byte)(unsafe.Pointer(&ptr[sz])) + } + } + + // Ignore file sync if flag is set on DB. + if !tx.db.NoSync || IgnoreNoSync { + if err := fdatasync(tx.db); err != nil { + return err + } + } + + // Put small pages back to page pool. + for _, p := range pages { + // Ignore page sizes over 1 page. + // These are allocated using make() instead of the page pool. + if int(p.overflow) != 0 { + continue + } + + buf := (*[maxAllocSize]byte)(unsafe.Pointer(p))[:tx.db.pageSize] + + // See https://go.googlesource.com/go/+/f03c9202c43e0abb130669852082117ca50aa9b1 + for i := range buf { + buf[i] = 0 + } + tx.db.pagePool.Put(buf) + } + + return nil +} + +// writeMeta writes the meta to the disk. +func (tx *Tx) writeMeta() error { + // Create a temporary buffer for the meta page. + buf := make([]byte, tx.db.pageSize) + p := tx.db.pageInBuffer(buf, 0) + tx.meta.write(p) + + // Write the meta page to file. + if _, err := tx.db.ops.writeAt(buf, int64(p.id)*int64(tx.db.pageSize)); err != nil { + return err + } + if !tx.db.NoSync || IgnoreNoSync { + if err := fdatasync(tx.db); err != nil { + return err + } + } + + // Update statistics. + tx.stats.Write++ + + return nil +} + +// page returns a reference to the page with a given id. +// If page has been written to then a temporary buffered page is returned. +func (tx *Tx) page(id pgid) *page { + // Check the dirty pages first. + if tx.pages != nil { + if p, ok := tx.pages[id]; ok { + return p + } + } + + // Otherwise return directly from the mmap. + return tx.db.page(id) +} + +// forEachPage iterates over every page within a given page and executes a function. +func (tx *Tx) forEachPage(pgid pgid, depth int, fn func(*page, int)) { + p := tx.page(pgid) + + // Execute function. + fn(p, depth) + + // Recursively loop over children. + if (p.flags & branchPageFlag) != 0 { + for i := 0; i < int(p.count); i++ { + elem := p.branchPageElement(uint16(i)) + tx.forEachPage(elem.pgid, depth+1, fn) + } + } +} + +// Page returns page information for a given page number. +// This is only safe for concurrent use when used by a writable transaction. +func (tx *Tx) Page(id int) (*PageInfo, error) { + if tx.db == nil { + return nil, ErrTxClosed + } else if pgid(id) >= tx.meta.pgid { + return nil, nil + } + + // Build the page info. + p := tx.db.page(pgid(id)) + info := &PageInfo{ + ID: id, + Count: int(p.count), + OverflowCount: int(p.overflow), + } + + // Determine the type (or if it's free). + if tx.db.freelist.freed(pgid(id)) { + info.Type = "free" + } else { + info.Type = p.typ() + } + + return info, nil +} + +// TxStats represents statistics about the actions performed by the transaction. +type TxStats struct { + // Page statistics. + PageCount int // number of page allocations + PageAlloc int // total bytes allocated + + // Cursor statistics. + CursorCount int // number of cursors created + + // Node statistics + NodeCount int // number of node allocations + NodeDeref int // number of node dereferences + + // Rebalance statistics. + Rebalance int // number of node rebalances + RebalanceTime time.Duration // total time spent rebalancing + + // Split/Spill statistics. + Split int // number of nodes split + Spill int // number of nodes spilled + SpillTime time.Duration // total time spent spilling + + // Write statistics. + Write int // number of writes performed + WriteTime time.Duration // total time spent writing to disk +} + +func (s *TxStats) add(other *TxStats) { + s.PageCount += other.PageCount + s.PageAlloc += other.PageAlloc + s.CursorCount += other.CursorCount + s.NodeCount += other.NodeCount + s.NodeDeref += other.NodeDeref + s.Rebalance += other.Rebalance + s.RebalanceTime += other.RebalanceTime + s.Split += other.Split + s.Spill += other.Spill + s.SpillTime += other.SpillTime + s.Write += other.Write + s.WriteTime += other.WriteTime +} + +// Sub calculates and returns the difference between two sets of transaction stats. +// This is useful when obtaining stats at two different points and time and +// you need the performance counters that occurred within that time span. +func (s *TxStats) Sub(other *TxStats) TxStats { + var diff TxStats + diff.PageCount = s.PageCount - other.PageCount + diff.PageAlloc = s.PageAlloc - other.PageAlloc + diff.CursorCount = s.CursorCount - other.CursorCount + diff.NodeCount = s.NodeCount - other.NodeCount + diff.NodeDeref = s.NodeDeref - other.NodeDeref + diff.Rebalance = s.Rebalance - other.Rebalance + diff.RebalanceTime = s.RebalanceTime - other.RebalanceTime + diff.Split = s.Split - other.Split + diff.Spill = s.Spill - other.Spill + diff.SpillTime = s.SpillTime - other.SpillTime + diff.Write = s.Write - other.Write + diff.WriteTime = s.WriteTime - other.WriteTime + return diff +} diff --git a/vendor/github.com/boltdb/bolt/tx_test.go b/vendor/github.com/boltdb/bolt/tx_test.go new file mode 100644 index 00000000..2201e792 --- /dev/null +++ b/vendor/github.com/boltdb/bolt/tx_test.go @@ -0,0 +1,716 @@ +package bolt_test + +import ( + "bytes" + "errors" + "fmt" + "log" + "os" + "testing" + + "github.com/boltdb/bolt" +) + +// Ensure that committing a closed transaction returns an error. +func TestTx_Commit_ErrTxClosed(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + tx, err := db.Begin(true) + if err != nil { + t.Fatal(err) + } + + if _, err := tx.CreateBucket([]byte("foo")); err != nil { + t.Fatal(err) + } + + if err := tx.Commit(); err != nil { + t.Fatal(err) + } + + if err := tx.Commit(); err != bolt.ErrTxClosed { + t.Fatalf("unexpected error: %s", err) + } +} + +// Ensure that rolling back a closed transaction returns an error. +func TestTx_Rollback_ErrTxClosed(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + tx, err := db.Begin(true) + if err != nil { + t.Fatal(err) + } + + if err := tx.Rollback(); err != nil { + t.Fatal(err) + } + if err := tx.Rollback(); err != bolt.ErrTxClosed { + t.Fatalf("unexpected error: %s", err) + } +} + +// Ensure that committing a read-only transaction returns an error. +func TestTx_Commit_ErrTxNotWritable(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + tx, err := db.Begin(false) + if err != nil { + t.Fatal(err) + } + if err := tx.Commit(); err != bolt.ErrTxNotWritable { + t.Fatal(err) + } +} + +// Ensure that a transaction can retrieve a cursor on the root bucket. +func TestTx_Cursor(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + if err := db.Update(func(tx *bolt.Tx) error { + if _, err := tx.CreateBucket([]byte("widgets")); err != nil { + t.Fatal(err) + } + + if _, err := tx.CreateBucket([]byte("woojits")); err != nil { + t.Fatal(err) + } + + c := tx.Cursor() + if k, v := c.First(); !bytes.Equal(k, []byte("widgets")) { + t.Fatalf("unexpected key: %v", k) + } else if v != nil { + t.Fatalf("unexpected value: %v", v) + } + + if k, v := c.Next(); !bytes.Equal(k, []byte("woojits")) { + t.Fatalf("unexpected key: %v", k) + } else if v != nil { + t.Fatalf("unexpected value: %v", v) + } + + if k, v := c.Next(); k != nil { + t.Fatalf("unexpected key: %v", k) + } else if v != nil { + t.Fatalf("unexpected value: %v", k) + } + + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that creating a bucket with a read-only transaction returns an error. +func TestTx_CreateBucket_ErrTxNotWritable(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + if err := db.View(func(tx *bolt.Tx) error { + _, err := tx.CreateBucket([]byte("foo")) + if err != bolt.ErrTxNotWritable { + t.Fatalf("unexpected error: %s", err) + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that creating a bucket on a closed transaction returns an error. +func TestTx_CreateBucket_ErrTxClosed(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + tx, err := db.Begin(true) + if err != nil { + t.Fatal(err) + } + if err := tx.Commit(); err != nil { + t.Fatal(err) + } + + if _, err := tx.CreateBucket([]byte("foo")); err != bolt.ErrTxClosed { + t.Fatalf("unexpected error: %s", err) + } +} + +// Ensure that a Tx can retrieve a bucket. +func TestTx_Bucket(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + if err := db.Update(func(tx *bolt.Tx) error { + if _, err := tx.CreateBucket([]byte("widgets")); err != nil { + t.Fatal(err) + } + if tx.Bucket([]byte("widgets")) == nil { + t.Fatal("expected bucket") + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that a Tx retrieving a non-existent key returns nil. +func TestTx_Get_NotFound(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + + if err := b.Put([]byte("foo"), []byte("bar")); err != nil { + t.Fatal(err) + } + if b.Get([]byte("no_such_key")) != nil { + t.Fatal("expected nil value") + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that a bucket can be created and retrieved. +func TestTx_CreateBucket(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + // Create a bucket. + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } else if b == nil { + t.Fatal("expected bucket") + } + return nil + }); err != nil { + t.Fatal(err) + } + + // Read the bucket through a separate transaction. + if err := db.View(func(tx *bolt.Tx) error { + if tx.Bucket([]byte("widgets")) == nil { + t.Fatal("expected bucket") + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that a bucket can be created if it doesn't already exist. +func TestTx_CreateBucketIfNotExists(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + if err := db.Update(func(tx *bolt.Tx) error { + // Create bucket. + if b, err := tx.CreateBucketIfNotExists([]byte("widgets")); err != nil { + t.Fatal(err) + } else if b == nil { + t.Fatal("expected bucket") + } + + // Create bucket again. + if b, err := tx.CreateBucketIfNotExists([]byte("widgets")); err != nil { + t.Fatal(err) + } else if b == nil { + t.Fatal("expected bucket") + } + + return nil + }); err != nil { + t.Fatal(err) + } + + // Read the bucket through a separate transaction. + if err := db.View(func(tx *bolt.Tx) error { + if tx.Bucket([]byte("widgets")) == nil { + t.Fatal("expected bucket") + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure transaction returns an error if creating an unnamed bucket. +func TestTx_CreateBucketIfNotExists_ErrBucketNameRequired(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + if err := db.Update(func(tx *bolt.Tx) error { + if _, err := tx.CreateBucketIfNotExists([]byte{}); err != bolt.ErrBucketNameRequired { + t.Fatalf("unexpected error: %s", err) + } + + if _, err := tx.CreateBucketIfNotExists(nil); err != bolt.ErrBucketNameRequired { + t.Fatalf("unexpected error: %s", err) + } + + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that a bucket cannot be created twice. +func TestTx_CreateBucket_ErrBucketExists(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + // Create a bucket. + if err := db.Update(func(tx *bolt.Tx) error { + if _, err := tx.CreateBucket([]byte("widgets")); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + + // Create the same bucket again. + if err := db.Update(func(tx *bolt.Tx) error { + if _, err := tx.CreateBucket([]byte("widgets")); err != bolt.ErrBucketExists { + t.Fatalf("unexpected error: %s", err) + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that a bucket is created with a non-blank name. +func TestTx_CreateBucket_ErrBucketNameRequired(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + if err := db.Update(func(tx *bolt.Tx) error { + if _, err := tx.CreateBucket(nil); err != bolt.ErrBucketNameRequired { + t.Fatalf("unexpected error: %s", err) + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that a bucket can be deleted. +func TestTx_DeleteBucket(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + // Create a bucket and add a value. + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("foo"), []byte("bar")); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + + // Delete the bucket and make sure we can't get the value. + if err := db.Update(func(tx *bolt.Tx) error { + if err := tx.DeleteBucket([]byte("widgets")); err != nil { + t.Fatal(err) + } + if tx.Bucket([]byte("widgets")) != nil { + t.Fatal("unexpected bucket") + } + return nil + }); err != nil { + t.Fatal(err) + } + + if err := db.Update(func(tx *bolt.Tx) error { + // Create the bucket again and make sure there's not a phantom value. + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + if v := b.Get([]byte("foo")); v != nil { + t.Fatalf("unexpected phantom value: %v", v) + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that deleting a bucket on a closed transaction returns an error. +func TestTx_DeleteBucket_ErrTxClosed(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + tx, err := db.Begin(true) + if err != nil { + t.Fatal(err) + } + if err := tx.Commit(); err != nil { + t.Fatal(err) + } + if err := tx.DeleteBucket([]byte("foo")); err != bolt.ErrTxClosed { + t.Fatalf("unexpected error: %s", err) + } +} + +// Ensure that deleting a bucket with a read-only transaction returns an error. +func TestTx_DeleteBucket_ReadOnly(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + if err := db.View(func(tx *bolt.Tx) error { + if err := tx.DeleteBucket([]byte("foo")); err != bolt.ErrTxNotWritable { + t.Fatalf("unexpected error: %s", err) + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that nothing happens when deleting a bucket that doesn't exist. +func TestTx_DeleteBucket_NotFound(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + if err := db.Update(func(tx *bolt.Tx) error { + if err := tx.DeleteBucket([]byte("widgets")); err != bolt.ErrBucketNotFound { + t.Fatalf("unexpected error: %s", err) + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that no error is returned when a tx.ForEach function does not return +// an error. +func TestTx_ForEach_NoError(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("foo"), []byte("bar")); err != nil { + t.Fatal(err) + } + + if err := tx.ForEach(func(name []byte, b *bolt.Bucket) error { + return nil + }); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that an error is returned when a tx.ForEach function returns an error. +func TestTx_ForEach_WithError(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("foo"), []byte("bar")); err != nil { + t.Fatal(err) + } + + marker := errors.New("marker") + if err := tx.ForEach(func(name []byte, b *bolt.Bucket) error { + return marker + }); err != marker { + t.Fatalf("unexpected error: %s", err) + } + return nil + }); err != nil { + t.Fatal(err) + } +} + +// Ensure that Tx commit handlers are called after a transaction successfully commits. +func TestTx_OnCommit(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + var x int + if err := db.Update(func(tx *bolt.Tx) error { + tx.OnCommit(func() { x += 1 }) + tx.OnCommit(func() { x += 2 }) + if _, err := tx.CreateBucket([]byte("widgets")); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } else if x != 3 { + t.Fatalf("unexpected x: %d", x) + } +} + +// Ensure that Tx commit handlers are NOT called after a transaction rolls back. +func TestTx_OnCommit_Rollback(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + var x int + if err := db.Update(func(tx *bolt.Tx) error { + tx.OnCommit(func() { x += 1 }) + tx.OnCommit(func() { x += 2 }) + if _, err := tx.CreateBucket([]byte("widgets")); err != nil { + t.Fatal(err) + } + return errors.New("rollback this commit") + }); err == nil || err.Error() != "rollback this commit" { + t.Fatalf("unexpected error: %s", err) + } else if x != 0 { + t.Fatalf("unexpected x: %d", x) + } +} + +// Ensure that the database can be copied to a file path. +func TestTx_CopyFile(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + + path := tempfile() + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("foo"), []byte("bar")); err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("baz"), []byte("bat")); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + + if err := db.View(func(tx *bolt.Tx) error { + return tx.CopyFile(path, 0600) + }); err != nil { + t.Fatal(err) + } + + db2, err := bolt.Open(path, 0600, nil) + if err != nil { + t.Fatal(err) + } + + if err := db2.View(func(tx *bolt.Tx) error { + if v := tx.Bucket([]byte("widgets")).Get([]byte("foo")); !bytes.Equal(v, []byte("bar")) { + t.Fatalf("unexpected value: %v", v) + } + if v := tx.Bucket([]byte("widgets")).Get([]byte("baz")); !bytes.Equal(v, []byte("bat")) { + t.Fatalf("unexpected value: %v", v) + } + return nil + }); err != nil { + t.Fatal(err) + } + + if err := db2.Close(); err != nil { + t.Fatal(err) + } +} + +type failWriterError struct{} + +func (failWriterError) Error() string { + return "error injected for tests" +} + +type failWriter struct { + // fail after this many bytes + After int +} + +func (f *failWriter) Write(p []byte) (n int, err error) { + n = len(p) + if n > f.After { + n = f.After + err = failWriterError{} + } + f.After -= n + return n, err +} + +// Ensure that Copy handles write errors right. +func TestTx_CopyFile_Error_Meta(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("foo"), []byte("bar")); err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("baz"), []byte("bat")); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + + if err := db.View(func(tx *bolt.Tx) error { + return tx.Copy(&failWriter{}) + }); err == nil || err.Error() != "meta 0 copy: error injected for tests" { + t.Fatalf("unexpected error: %v", err) + } +} + +// Ensure that Copy handles write errors right. +func TestTx_CopyFile_Error_Normal(t *testing.T) { + db := MustOpenDB() + defer db.MustClose() + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("foo"), []byte("bar")); err != nil { + t.Fatal(err) + } + if err := b.Put([]byte("baz"), []byte("bat")); err != nil { + t.Fatal(err) + } + return nil + }); err != nil { + t.Fatal(err) + } + + if err := db.View(func(tx *bolt.Tx) error { + return tx.Copy(&failWriter{3 * db.Info().PageSize}) + }); err == nil || err.Error() != "error injected for tests" { + t.Fatalf("unexpected error: %v", err) + } +} + +func ExampleTx_Rollback() { + // Open the database. + db, err := bolt.Open(tempfile(), 0666, nil) + if err != nil { + log.Fatal(err) + } + defer os.Remove(db.Path()) + + // Create a bucket. + if err := db.Update(func(tx *bolt.Tx) error { + _, err := tx.CreateBucket([]byte("widgets")) + return err + }); err != nil { + log.Fatal(err) + } + + // Set a value for a key. + if err := db.Update(func(tx *bolt.Tx) error { + return tx.Bucket([]byte("widgets")).Put([]byte("foo"), []byte("bar")) + }); err != nil { + log.Fatal(err) + } + + // Update the key but rollback the transaction so it never saves. + tx, err := db.Begin(true) + if err != nil { + log.Fatal(err) + } + b := tx.Bucket([]byte("widgets")) + if err := b.Put([]byte("foo"), []byte("baz")); err != nil { + log.Fatal(err) + } + if err := tx.Rollback(); err != nil { + log.Fatal(err) + } + + // Ensure that our original value is still set. + if err := db.View(func(tx *bolt.Tx) error { + value := tx.Bucket([]byte("widgets")).Get([]byte("foo")) + fmt.Printf("The value for 'foo' is still: %s\n", value) + return nil + }); err != nil { + log.Fatal(err) + } + + // Close database to release file lock. + if err := db.Close(); err != nil { + log.Fatal(err) + } + + // Output: + // The value for 'foo' is still: bar +} + +func ExampleTx_CopyFile() { + // Open the database. + db, err := bolt.Open(tempfile(), 0666, nil) + if err != nil { + log.Fatal(err) + } + defer os.Remove(db.Path()) + + // Create a bucket and a key. + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket([]byte("widgets")) + if err != nil { + return err + } + if err := b.Put([]byte("foo"), []byte("bar")); err != nil { + return err + } + return nil + }); err != nil { + log.Fatal(err) + } + + // Copy the database to another file. + toFile := tempfile() + if err := db.View(func(tx *bolt.Tx) error { + return tx.CopyFile(toFile, 0666) + }); err != nil { + log.Fatal(err) + } + defer os.Remove(toFile) + + // Open the cloned database. + db2, err := bolt.Open(toFile, 0666, nil) + if err != nil { + log.Fatal(err) + } + + // Ensure that the key exists in the copy. + if err := db2.View(func(tx *bolt.Tx) error { + value := tx.Bucket([]byte("widgets")).Get([]byte("foo")) + fmt.Printf("The value for 'foo' in the clone is: %s\n", value) + return nil + }); err != nil { + log.Fatal(err) + } + + // Close database to release file lock. + if err := db.Close(); err != nil { + log.Fatal(err) + } + + if err := db2.Close(); err != nil { + log.Fatal(err) + } + + // Output: + // The value for 'foo' in the clone is: bar +} diff --git a/vendor/github.com/go-yaml/yaml/.travis.yml b/vendor/github.com/go-yaml/yaml/.travis.yml new file mode 100644 index 00000000..004172a2 --- /dev/null +++ b/vendor/github.com/go-yaml/yaml/.travis.yml @@ -0,0 +1,9 @@ +language: go + +go: + - 1.4 + - 1.5 + - 1.6 + - tip + +go_import_path: gopkg.in/yaml.v2 diff --git a/vendor/github.com/go-yaml/yaml/LICENSE b/vendor/github.com/go-yaml/yaml/LICENSE new file mode 100644 index 00000000..8dada3ed --- /dev/null +++ b/vendor/github.com/go-yaml/yaml/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/github.com/go-yaml/yaml/LICENSE.libyaml b/vendor/github.com/go-yaml/yaml/LICENSE.libyaml new file mode 100644 index 00000000..8da58fbf --- /dev/null +++ b/vendor/github.com/go-yaml/yaml/LICENSE.libyaml @@ -0,0 +1,31 @@ +The following files were ported to Go from C files of libyaml, and thus +are still covered by their original copyright and license: + + apic.go + emitterc.go + parserc.go + readerc.go + scannerc.go + writerc.go + yamlh.go + yamlprivateh.go + +Copyright (c) 2006 Kirill Simonov + +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/go-yaml/yaml/README.md b/vendor/github.com/go-yaml/yaml/README.md new file mode 100644 index 00000000..2ed3314c --- /dev/null +++ b/vendor/github.com/go-yaml/yaml/README.md @@ -0,0 +1,135 @@ +# YAML support for the Go language + +Introduction +------------ + +The yaml package enables Go programs to comfortably encode and decode YAML +values. It was developed within [Canonical](https://www.canonical.com) as +part of the [juju](https://juju.ubuntu.com) project, and is based on a +pure Go port of the well-known [libyaml](http://pyyaml.org/wiki/LibYAML) +C library to parse and generate YAML data quickly and reliably. + +Compatibility +------------- + +The yaml package supports most of YAML 1.1 and 1.2, including support for +anchors, tags, map merging, etc. Multi-document unmarshalling is not yet +implemented, and base-60 floats from YAML 1.1 are purposefully not +supported since they're a poor design and are gone in YAML 1.2. + +Installation and usage +---------------------- + +The import path for the package is *gopkg.in/yaml.v2*. + +To install it, run: + + go get gopkg.in/yaml.v2 + +API documentation +----------------- + +If opened in a browser, the import path itself leads to the API documentation: + + * [https://gopkg.in/yaml.v2](https://gopkg.in/yaml.v2) + +API stability +------------- + +The package API for yaml v2 will remain stable as described in [gopkg.in](https://gopkg.in). + + +License +------- + +The yaml package is licensed under the Apache License 2.0. Please see the LICENSE file for details. + + +Example +------- + +Some more examples can be found in the "examples" folder. + +```Go +package main + +import ( + "fmt" + "log" + + "gopkg.in/yaml.v2" +) + +var data = ` +a: Easy! +b: + c: 2 + d: [3, 4] +` + +// Note: struct fields must be public in order for unmarshal to +// correctly populate the data. +type T struct { + A string + B struct { + RenamedC int `yaml:"c"` + D []int `yaml:",flow"` + } +} + +func main() { + t := T{} + + err := yaml.Unmarshal([]byte(data), &t) + if err != nil { + log.Fatalf("error: %v", err) + } + fmt.Printf("--- t:\n%v\n\n", t) + + d, err := yaml.Marshal(&t) + if err != nil { + log.Fatalf("error: %v", err) + } + fmt.Printf("--- t dump:\n%s\n\n", string(d)) + + m := make(map[interface{}]interface{}) + + err = yaml.Unmarshal([]byte(data), &m) + if err != nil { + log.Fatalf("error: %v", err) + } + fmt.Printf("--- m:\n%v\n\n", m) + + d, err = yaml.Marshal(&m) + if err != nil { + log.Fatalf("error: %v", err) + } + fmt.Printf("--- m dump:\n%s\n\n", string(d)) +} +``` + +This example will generate the following output: + +``` +--- t: +{Easy! {2 [3 4]}} + +--- t dump: +a: Easy! +b: + c: 2 + d: [3, 4] + + +--- m: +map[a:Easy! b:map[c:2 d:[3 4]]] + +--- m dump: +a: Easy! +b: + c: 2 + d: + - 3 + - 4 +``` + diff --git a/vendor/github.com/go-yaml/yaml/apic.go b/vendor/github.com/go-yaml/yaml/apic.go new file mode 100644 index 00000000..95ec014e --- /dev/null +++ b/vendor/github.com/go-yaml/yaml/apic.go @@ -0,0 +1,742 @@ +package yaml + +import ( + "io" + "os" +) + +func yaml_insert_token(parser *yaml_parser_t, pos int, token *yaml_token_t) { + //fmt.Println("yaml_insert_token", "pos:", pos, "typ:", token.typ, "head:", parser.tokens_head, "len:", len(parser.tokens)) + + // Check if we can move the queue at the beginning of the buffer. + if parser.tokens_head > 0 && len(parser.tokens) == cap(parser.tokens) { + if parser.tokens_head != len(parser.tokens) { + copy(parser.tokens, parser.tokens[parser.tokens_head:]) + } + parser.tokens = parser.tokens[:len(parser.tokens)-parser.tokens_head] + parser.tokens_head = 0 + } + parser.tokens = append(parser.tokens, *token) + if pos < 0 { + return + } + copy(parser.tokens[parser.tokens_head+pos+1:], parser.tokens[parser.tokens_head+pos:]) + parser.tokens[parser.tokens_head+pos] = *token +} + +// Create a new parser object. +func yaml_parser_initialize(parser *yaml_parser_t) bool { + *parser = yaml_parser_t{ + raw_buffer: make([]byte, 0, input_raw_buffer_size), + buffer: make([]byte, 0, input_buffer_size), + } + return true +} + +// Destroy a parser object. +func yaml_parser_delete(parser *yaml_parser_t) { + *parser = yaml_parser_t{} +} + +// String read handler. +func yaml_string_read_handler(parser *yaml_parser_t, buffer []byte) (n int, err error) { + if parser.input_pos == len(parser.input) { + return 0, io.EOF + } + n = copy(buffer, parser.input[parser.input_pos:]) + parser.input_pos += n + return n, nil +} + +// File read handler. +func yaml_file_read_handler(parser *yaml_parser_t, buffer []byte) (n int, err error) { + return parser.input_file.Read(buffer) +} + +// Set a string input. +func yaml_parser_set_input_string(parser *yaml_parser_t, input []byte) { + if parser.read_handler != nil { + panic("must set the input source only once") + } + parser.read_handler = yaml_string_read_handler + parser.input = input + parser.input_pos = 0 +} + +// Set a file input. +func yaml_parser_set_input_file(parser *yaml_parser_t, file *os.File) { + if parser.read_handler != nil { + panic("must set the input source only once") + } + parser.read_handler = yaml_file_read_handler + parser.input_file = file +} + +// Set the source encoding. +func yaml_parser_set_encoding(parser *yaml_parser_t, encoding yaml_encoding_t) { + if parser.encoding != yaml_ANY_ENCODING { + panic("must set the encoding only once") + } + parser.encoding = encoding +} + +// Create a new emitter object. +func yaml_emitter_initialize(emitter *yaml_emitter_t) bool { + *emitter = yaml_emitter_t{ + buffer: make([]byte, output_buffer_size), + 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), + } + return true +} + +// Destroy an emitter object. +func yaml_emitter_delete(emitter *yaml_emitter_t) { + *emitter = yaml_emitter_t{} +} + +// String write handler. +func yaml_string_write_handler(emitter *yaml_emitter_t, buffer []byte) error { + *emitter.output_buffer = append(*emitter.output_buffer, buffer...) + return nil +} + +// File write handler. +func yaml_file_write_handler(emitter *yaml_emitter_t, buffer []byte) error { + _, err := emitter.output_file.Write(buffer) + return err +} + +// Set a string output. +func yaml_emitter_set_output_string(emitter *yaml_emitter_t, output_buffer *[]byte) { + if emitter.write_handler != nil { + panic("must set the output target only once") + } + emitter.write_handler = yaml_string_write_handler + emitter.output_buffer = output_buffer +} + +// Set a file output. +func yaml_emitter_set_output_file(emitter *yaml_emitter_t, file io.Writer) { + if emitter.write_handler != nil { + panic("must set the output target only once") + } + emitter.write_handler = yaml_file_write_handler + emitter.output_file = file +} + +// Set the output encoding. +func yaml_emitter_set_encoding(emitter *yaml_emitter_t, encoding yaml_encoding_t) { + if emitter.encoding != yaml_ANY_ENCODING { + panic("must set the output encoding only once") + } + emitter.encoding = encoding +} + +// Set the canonical output style. +func yaml_emitter_set_canonical(emitter *yaml_emitter_t, canonical bool) { + emitter.canonical = canonical +} + +//// Set the indentation increment. +func yaml_emitter_set_indent(emitter *yaml_emitter_t, indent int) { + if indent < 2 || indent > 9 { + indent = 2 + } + emitter.best_indent = indent +} + +// Set the preferred line width. +func yaml_emitter_set_width(emitter *yaml_emitter_t, width int) { + if width < 0 { + width = -1 + } + emitter.best_width = width +} + +// Set if unescaped non-ASCII characters are allowed. +func yaml_emitter_set_unicode(emitter *yaml_emitter_t, unicode bool) { + emitter.unicode = unicode +} + +// Set the preferred line break character. +func yaml_emitter_set_break(emitter *yaml_emitter_t, line_break yaml_break_t) { + emitter.line_break = line_break +} + +///* +// * Destroy a token object. +// */ +// +//YAML_DECLARE(void) +//yaml_token_delete(yaml_token_t *token) +//{ +// assert(token); // Non-NULL token object expected. +// +// switch (token.type) +// { +// case YAML_TAG_DIRECTIVE_TOKEN: +// yaml_free(token.data.tag_directive.handle); +// yaml_free(token.data.tag_directive.prefix); +// break; +// +// case YAML_ALIAS_TOKEN: +// yaml_free(token.data.alias.value); +// break; +// +// case YAML_ANCHOR_TOKEN: +// yaml_free(token.data.anchor.value); +// break; +// +// case YAML_TAG_TOKEN: +// yaml_free(token.data.tag.handle); +// yaml_free(token.data.tag.suffix); +// break; +// +// case YAML_SCALAR_TOKEN: +// yaml_free(token.data.scalar.value); +// break; +// +// default: +// break; +// } +// +// memset(token, 0, sizeof(yaml_token_t)); +//} +// +///* +// * Check if a string is a valid UTF-8 sequence. +// * +// * Check 'reader.c' for more details on UTF-8 encoding. +// */ +// +//static int +//yaml_check_utf8(yaml_char_t *start, size_t length) +//{ +// yaml_char_t *end = start+length; +// yaml_char_t *pointer = start; +// +// while (pointer < end) { +// unsigned char octet; +// unsigned int width; +// unsigned int value; +// size_t k; +// +// octet = pointer[0]; +// width = (octet & 0x80) == 0x00 ? 1 : +// (octet & 0xE0) == 0xC0 ? 2 : +// (octet & 0xF0) == 0xE0 ? 3 : +// (octet & 0xF8) == 0xF0 ? 4 : 0; +// value = (octet & 0x80) == 0x00 ? octet & 0x7F : +// (octet & 0xE0) == 0xC0 ? octet & 0x1F : +// (octet & 0xF0) == 0xE0 ? octet & 0x0F : +// (octet & 0xF8) == 0xF0 ? octet & 0x07 : 0; +// if (!width) return 0; +// if (pointer+width > end) return 0; +// for (k = 1; k < width; k ++) { +// octet = pointer[k]; +// if ((octet & 0xC0) != 0x80) return 0; +// value = (value << 6) + (octet & 0x3F); +// } +// if (!((width == 1) || +// (width == 2 && value >= 0x80) || +// (width == 3 && value >= 0x800) || +// (width == 4 && value >= 0x10000))) return 0; +// +// pointer += width; +// } +// +// return 1; +//} +// + +// Create STREAM-START. +func yaml_stream_start_event_initialize(event *yaml_event_t, encoding yaml_encoding_t) bool { + *event = yaml_event_t{ + typ: yaml_STREAM_START_EVENT, + encoding: encoding, + } + return true +} + +// Create STREAM-END. +func yaml_stream_end_event_initialize(event *yaml_event_t) bool { + *event = yaml_event_t{ + typ: yaml_STREAM_END_EVENT, + } + return true +} + +// Create DOCUMENT-START. +func yaml_document_start_event_initialize(event *yaml_event_t, version_directive *yaml_version_directive_t, + tag_directives []yaml_tag_directive_t, implicit bool) bool { + *event = yaml_event_t{ + typ: yaml_DOCUMENT_START_EVENT, + version_directive: version_directive, + tag_directives: tag_directives, + implicit: implicit, + } + return true +} + +// Create DOCUMENT-END. +func yaml_document_end_event_initialize(event *yaml_event_t, implicit bool) bool { + *event = yaml_event_t{ + typ: yaml_DOCUMENT_END_EVENT, + implicit: implicit, + } + return true +} + +///* +// * Create ALIAS. +// */ +// +//YAML_DECLARE(int) +//yaml_alias_event_initialize(event *yaml_event_t, anchor *yaml_char_t) +//{ +// mark yaml_mark_t = { 0, 0, 0 } +// anchor_copy *yaml_char_t = NULL +// +// assert(event) // Non-NULL event object is expected. +// assert(anchor) // Non-NULL anchor is expected. +// +// if (!yaml_check_utf8(anchor, strlen((char *)anchor))) return 0 +// +// anchor_copy = yaml_strdup(anchor) +// if (!anchor_copy) +// return 0 +// +// ALIAS_EVENT_INIT(*event, anchor_copy, mark, mark) +// +// return 1 +//} + +// Create SCALAR. +func yaml_scalar_event_initialize(event *yaml_event_t, anchor, tag, value []byte, plain_implicit, quoted_implicit bool, style yaml_scalar_style_t) bool { + *event = yaml_event_t{ + typ: yaml_SCALAR_EVENT, + anchor: anchor, + tag: tag, + value: value, + implicit: plain_implicit, + quoted_implicit: quoted_implicit, + style: yaml_style_t(style), + } + return true +} + +// Create SEQUENCE-START. +func yaml_sequence_start_event_initialize(event *yaml_event_t, anchor, tag []byte, implicit bool, style yaml_sequence_style_t) bool { + *event = yaml_event_t{ + typ: yaml_SEQUENCE_START_EVENT, + anchor: anchor, + tag: tag, + implicit: implicit, + style: yaml_style_t(style), + } + return true +} + +// Create SEQUENCE-END. +func yaml_sequence_end_event_initialize(event *yaml_event_t) bool { + *event = yaml_event_t{ + typ: yaml_SEQUENCE_END_EVENT, + } + return true +} + +// Create MAPPING-START. +func yaml_mapping_start_event_initialize(event *yaml_event_t, anchor, tag []byte, implicit bool, style yaml_mapping_style_t) bool { + *event = yaml_event_t{ + typ: yaml_MAPPING_START_EVENT, + anchor: anchor, + tag: tag, + implicit: implicit, + style: yaml_style_t(style), + } + return true +} + +// Create MAPPING-END. +func yaml_mapping_end_event_initialize(event *yaml_event_t) bool { + *event = yaml_event_t{ + typ: yaml_MAPPING_END_EVENT, + } + return true +} + +// Destroy an event object. +func yaml_event_delete(event *yaml_event_t) { + *event = yaml_event_t{} +} + +///* +// * Create a document object. +// */ +// +//YAML_DECLARE(int) +//yaml_document_initialize(document *yaml_document_t, +// version_directive *yaml_version_directive_t, +// tag_directives_start *yaml_tag_directive_t, +// tag_directives_end *yaml_tag_directive_t, +// start_implicit int, end_implicit int) +//{ +// struct { +// error yaml_error_type_t +// } context +// struct { +// start *yaml_node_t +// end *yaml_node_t +// top *yaml_node_t +// } nodes = { NULL, NULL, NULL } +// version_directive_copy *yaml_version_directive_t = NULL +// struct { +// start *yaml_tag_directive_t +// end *yaml_tag_directive_t +// top *yaml_tag_directive_t +// } tag_directives_copy = { NULL, NULL, NULL } +// value yaml_tag_directive_t = { NULL, NULL } +// mark yaml_mark_t = { 0, 0, 0 } +// +// assert(document) // Non-NULL document object is expected. +// assert((tag_directives_start && tag_directives_end) || +// (tag_directives_start == tag_directives_end)) +// // Valid tag directives are expected. +// +// if (!STACK_INIT(&context, nodes, INITIAL_STACK_SIZE)) goto error +// +// if (version_directive) { +// version_directive_copy = yaml_malloc(sizeof(yaml_version_directive_t)) +// if (!version_directive_copy) goto error +// version_directive_copy.major = version_directive.major +// version_directive_copy.minor = version_directive.minor +// } +// +// if (tag_directives_start != tag_directives_end) { +// tag_directive *yaml_tag_directive_t +// if (!STACK_INIT(&context, tag_directives_copy, INITIAL_STACK_SIZE)) +// goto error +// for (tag_directive = tag_directives_start +// tag_directive != tag_directives_end; tag_directive ++) { +// assert(tag_directive.handle) +// assert(tag_directive.prefix) +// if (!yaml_check_utf8(tag_directive.handle, +// strlen((char *)tag_directive.handle))) +// goto error +// if (!yaml_check_utf8(tag_directive.prefix, +// strlen((char *)tag_directive.prefix))) +// goto error +// value.handle = yaml_strdup(tag_directive.handle) +// value.prefix = yaml_strdup(tag_directive.prefix) +// if (!value.handle || !value.prefix) goto error +// if (!PUSH(&context, tag_directives_copy, value)) +// goto error +// value.handle = NULL +// value.prefix = NULL +// } +// } +// +// DOCUMENT_INIT(*document, nodes.start, nodes.end, version_directive_copy, +// tag_directives_copy.start, tag_directives_copy.top, +// start_implicit, end_implicit, mark, mark) +// +// return 1 +// +//error: +// STACK_DEL(&context, nodes) +// yaml_free(version_directive_copy) +// while (!STACK_EMPTY(&context, tag_directives_copy)) { +// value yaml_tag_directive_t = POP(&context, tag_directives_copy) +// yaml_free(value.handle) +// yaml_free(value.prefix) +// } +// STACK_DEL(&context, tag_directives_copy) +// yaml_free(value.handle) +// yaml_free(value.prefix) +// +// return 0 +//} +// +///* +// * Destroy a document object. +// */ +// +//YAML_DECLARE(void) +//yaml_document_delete(document *yaml_document_t) +//{ +// struct { +// error yaml_error_type_t +// } context +// tag_directive *yaml_tag_directive_t +// +// context.error = YAML_NO_ERROR // Eliminate a compliler warning. +// +// assert(document) // Non-NULL document object is expected. +// +// while (!STACK_EMPTY(&context, document.nodes)) { +// node yaml_node_t = POP(&context, document.nodes) +// yaml_free(node.tag) +// switch (node.type) { +// case YAML_SCALAR_NODE: +// yaml_free(node.data.scalar.value) +// break +// case YAML_SEQUENCE_NODE: +// STACK_DEL(&context, node.data.sequence.items) +// break +// case YAML_MAPPING_NODE: +// STACK_DEL(&context, node.data.mapping.pairs) +// break +// default: +// assert(0) // Should not happen. +// } +// } +// STACK_DEL(&context, document.nodes) +// +// yaml_free(document.version_directive) +// for (tag_directive = document.tag_directives.start +// tag_directive != document.tag_directives.end +// tag_directive++) { +// yaml_free(tag_directive.handle) +// yaml_free(tag_directive.prefix) +// } +// yaml_free(document.tag_directives.start) +// +// memset(document, 0, sizeof(yaml_document_t)) +//} +// +///** +// * Get a document node. +// */ +// +//YAML_DECLARE(yaml_node_t *) +//yaml_document_get_node(document *yaml_document_t, index int) +//{ +// assert(document) // Non-NULL document object is expected. +// +// if (index > 0 && document.nodes.start + index <= document.nodes.top) { +// return document.nodes.start + index - 1 +// } +// return NULL +//} +// +///** +// * Get the root object. +// */ +// +//YAML_DECLARE(yaml_node_t *) +//yaml_document_get_root_node(document *yaml_document_t) +//{ +// assert(document) // Non-NULL document object is expected. +// +// if (document.nodes.top != document.nodes.start) { +// return document.nodes.start +// } +// return NULL +//} +// +///* +// * Add a scalar node to a document. +// */ +// +//YAML_DECLARE(int) +//yaml_document_add_scalar(document *yaml_document_t, +// tag *yaml_char_t, value *yaml_char_t, length int, +// style yaml_scalar_style_t) +//{ +// struct { +// error yaml_error_type_t +// } context +// mark yaml_mark_t = { 0, 0, 0 } +// tag_copy *yaml_char_t = NULL +// value_copy *yaml_char_t = NULL +// node yaml_node_t +// +// assert(document) // Non-NULL document object is expected. +// assert(value) // Non-NULL value is expected. +// +// if (!tag) { +// tag = (yaml_char_t *)YAML_DEFAULT_SCALAR_TAG +// } +// +// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error +// tag_copy = yaml_strdup(tag) +// if (!tag_copy) goto error +// +// if (length < 0) { +// length = strlen((char *)value) +// } +// +// if (!yaml_check_utf8(value, length)) goto error +// value_copy = yaml_malloc(length+1) +// if (!value_copy) goto error +// memcpy(value_copy, value, length) +// value_copy[length] = '\0' +// +// SCALAR_NODE_INIT(node, tag_copy, value_copy, length, style, mark, mark) +// if (!PUSH(&context, document.nodes, node)) goto error +// +// return document.nodes.top - document.nodes.start +// +//error: +// yaml_free(tag_copy) +// yaml_free(value_copy) +// +// return 0 +//} +// +///* +// * Add a sequence node to a document. +// */ +// +//YAML_DECLARE(int) +//yaml_document_add_sequence(document *yaml_document_t, +// tag *yaml_char_t, style yaml_sequence_style_t) +//{ +// struct { +// error yaml_error_type_t +// } context +// mark yaml_mark_t = { 0, 0, 0 } +// tag_copy *yaml_char_t = NULL +// struct { +// start *yaml_node_item_t +// end *yaml_node_item_t +// top *yaml_node_item_t +// } items = { NULL, NULL, NULL } +// node yaml_node_t +// +// assert(document) // Non-NULL document object is expected. +// +// if (!tag) { +// tag = (yaml_char_t *)YAML_DEFAULT_SEQUENCE_TAG +// } +// +// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error +// tag_copy = yaml_strdup(tag) +// if (!tag_copy) goto error +// +// if (!STACK_INIT(&context, items, INITIAL_STACK_SIZE)) goto error +// +// SEQUENCE_NODE_INIT(node, tag_copy, items.start, items.end, +// style, mark, mark) +// if (!PUSH(&context, document.nodes, node)) goto error +// +// return document.nodes.top - document.nodes.start +// +//error: +// STACK_DEL(&context, items) +// yaml_free(tag_copy) +// +// return 0 +//} +// +///* +// * Add a mapping node to a document. +// */ +// +//YAML_DECLARE(int) +//yaml_document_add_mapping(document *yaml_document_t, +// tag *yaml_char_t, style yaml_mapping_style_t) +//{ +// struct { +// error yaml_error_type_t +// } context +// mark yaml_mark_t = { 0, 0, 0 } +// tag_copy *yaml_char_t = NULL +// struct { +// start *yaml_node_pair_t +// end *yaml_node_pair_t +// top *yaml_node_pair_t +// } pairs = { NULL, NULL, NULL } +// node yaml_node_t +// +// assert(document) // Non-NULL document object is expected. +// +// if (!tag) { +// tag = (yaml_char_t *)YAML_DEFAULT_MAPPING_TAG +// } +// +// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error +// tag_copy = yaml_strdup(tag) +// if (!tag_copy) goto error +// +// if (!STACK_INIT(&context, pairs, INITIAL_STACK_SIZE)) goto error +// +// MAPPING_NODE_INIT(node, tag_copy, pairs.start, pairs.end, +// style, mark, mark) +// if (!PUSH(&context, document.nodes, node)) goto error +// +// return document.nodes.top - document.nodes.start +// +//error: +// STACK_DEL(&context, pairs) +// yaml_free(tag_copy) +// +// return 0 +//} +// +///* +// * Append an item to a sequence node. +// */ +// +//YAML_DECLARE(int) +//yaml_document_append_sequence_item(document *yaml_document_t, +// sequence int, item int) +//{ +// struct { +// error yaml_error_type_t +// } context +// +// assert(document) // Non-NULL document is required. +// assert(sequence > 0 +// && document.nodes.start + sequence <= document.nodes.top) +// // Valid sequence id is required. +// assert(document.nodes.start[sequence-1].type == YAML_SEQUENCE_NODE) +// // A sequence node is required. +// assert(item > 0 && document.nodes.start + item <= document.nodes.top) +// // Valid item id is required. +// +// if (!PUSH(&context, +// document.nodes.start[sequence-1].data.sequence.items, item)) +// return 0 +// +// return 1 +//} +// +///* +// * Append a pair of a key and a value to a mapping node. +// */ +// +//YAML_DECLARE(int) +//yaml_document_append_mapping_pair(document *yaml_document_t, +// mapping int, key int, value int) +//{ +// struct { +// error yaml_error_type_t +// } context +// +// pair yaml_node_pair_t +// +// assert(document) // Non-NULL document is required. +// assert(mapping > 0 +// && document.nodes.start + mapping <= document.nodes.top) +// // Valid mapping id is required. +// assert(document.nodes.start[mapping-1].type == YAML_MAPPING_NODE) +// // A mapping node is required. +// assert(key > 0 && document.nodes.start + key <= document.nodes.top) +// // Valid key id is required. +// assert(value > 0 && document.nodes.start + value <= document.nodes.top) +// // Valid value id is required. +// +// pair.key = key +// pair.value = value +// +// if (!PUSH(&context, +// document.nodes.start[mapping-1].data.mapping.pairs, pair)) +// return 0 +// +// return 1 +//} +// +// diff --git a/vendor/github.com/go-yaml/yaml/decode.go b/vendor/github.com/go-yaml/yaml/decode.go new file mode 100644 index 00000000..e85eb2e3 --- /dev/null +++ b/vendor/github.com/go-yaml/yaml/decode.go @@ -0,0 +1,685 @@ +package yaml + +import ( + "encoding" + "encoding/base64" + "fmt" + "math" + "reflect" + "strconv" + "time" +) + +const ( + documentNode = 1 << iota + mappingNode + sequenceNode + scalarNode + aliasNode +) + +type node struct { + kind int + line, column int + tag string + value string + implicit bool + children []*node + anchors map[string]*node +} + +// ---------------------------------------------------------------------------- +// Parser, produces a node tree out of a libyaml event stream. + +type parser struct { + parser yaml_parser_t + event yaml_event_t + doc *node +} + +func newParser(b []byte) *parser { + p := parser{} + if !yaml_parser_initialize(&p.parser) { + panic("failed to initialize YAML emitter") + } + + if len(b) == 0 { + b = []byte{'\n'} + } + + yaml_parser_set_input_string(&p.parser, b) + + p.skip() + if p.event.typ != yaml_STREAM_START_EVENT { + panic("expected stream start event, got " + strconv.Itoa(int(p.event.typ))) + } + p.skip() + return &p +} + +func (p *parser) destroy() { + if p.event.typ != yaml_NO_EVENT { + yaml_event_delete(&p.event) + } + yaml_parser_delete(&p.parser) +} + +func (p *parser) skip() { + if p.event.typ != yaml_NO_EVENT { + if p.event.typ == yaml_STREAM_END_EVENT { + failf("attempted to go past the end of stream; corrupted value?") + } + yaml_event_delete(&p.event) + } + if !yaml_parser_parse(&p.parser, &p.event) { + p.fail() + } +} + +func (p *parser) fail() { + var where string + var line int + if p.parser.problem_mark.line != 0 { + line = p.parser.problem_mark.line + } else if p.parser.context_mark.line != 0 { + line = p.parser.context_mark.line + } + if line != 0 { + where = "line " + strconv.Itoa(line) + ": " + } + var msg string + if len(p.parser.problem) > 0 { + msg = p.parser.problem + } else { + msg = "unknown problem parsing YAML content" + } + failf("%s%s", where, msg) +} + +func (p *parser) anchor(n *node, anchor []byte) { + if anchor != nil { + p.doc.anchors[string(anchor)] = n + } +} + +func (p *parser) parse() *node { + switch p.event.typ { + case yaml_SCALAR_EVENT: + return p.scalar() + case yaml_ALIAS_EVENT: + return p.alias() + case yaml_MAPPING_START_EVENT: + return p.mapping() + case yaml_SEQUENCE_START_EVENT: + return p.sequence() + case yaml_DOCUMENT_START_EVENT: + return p.document() + case yaml_STREAM_END_EVENT: + // Happens when attempting to decode an empty buffer. + return nil + default: + panic("attempted to parse unknown event: " + strconv.Itoa(int(p.event.typ))) + } +} + +func (p *parser) node(kind int) *node { + return &node{ + kind: kind, + line: p.event.start_mark.line, + column: p.event.start_mark.column, + } +} + +func (p *parser) document() *node { + n := p.node(documentNode) + n.anchors = make(map[string]*node) + p.doc = n + p.skip() + n.children = append(n.children, p.parse()) + if p.event.typ != yaml_DOCUMENT_END_EVENT { + panic("expected end of document event but got " + strconv.Itoa(int(p.event.typ))) + } + p.skip() + return n +} + +func (p *parser) alias() *node { + n := p.node(aliasNode) + n.value = string(p.event.anchor) + p.skip() + return n +} + +func (p *parser) scalar() *node { + n := p.node(scalarNode) + n.value = string(p.event.value) + n.tag = string(p.event.tag) + n.implicit = p.event.implicit + p.anchor(n, p.event.anchor) + p.skip() + return n +} + +func (p *parser) sequence() *node { + n := p.node(sequenceNode) + p.anchor(n, p.event.anchor) + p.skip() + for p.event.typ != yaml_SEQUENCE_END_EVENT { + n.children = append(n.children, p.parse()) + } + p.skip() + return n +} + +func (p *parser) mapping() *node { + n := p.node(mappingNode) + p.anchor(n, p.event.anchor) + p.skip() + for p.event.typ != yaml_MAPPING_END_EVENT { + n.children = append(n.children, p.parse(), p.parse()) + } + p.skip() + return n +} + +// ---------------------------------------------------------------------------- +// Decoder, unmarshals a node into a provided value. + +type decoder struct { + doc *node + aliases map[string]bool + mapType reflect.Type + terrors []string + strict bool +} + +var ( + mapItemType = reflect.TypeOf(MapItem{}) + durationType = reflect.TypeOf(time.Duration(0)) + defaultMapType = reflect.TypeOf(map[interface{}]interface{}{}) + ifaceType = defaultMapType.Elem() +) + +func newDecoder(strict bool) *decoder { + d := &decoder{mapType: defaultMapType, strict: strict} + d.aliases = make(map[string]bool) + return d +} + +func (d *decoder) terror(n *node, tag string, out reflect.Value) { + if n.tag != "" { + tag = n.tag + } + value := n.value + if tag != yaml_SEQ_TAG && tag != yaml_MAP_TAG { + if len(value) > 10 { + value = " `" + value[:7] + "...`" + } else { + value = " `" + value + "`" + } + } + d.terrors = append(d.terrors, fmt.Sprintf("line %d: cannot unmarshal %s%s into %s", n.line+1, shortTag(tag), value, out.Type())) +} + +func (d *decoder) callUnmarshaler(n *node, u Unmarshaler) (good bool) { + terrlen := len(d.terrors) + err := u.UnmarshalYAML(func(v interface{}) (err error) { + defer handleErr(&err) + d.unmarshal(n, reflect.ValueOf(v)) + if len(d.terrors) > terrlen { + issues := d.terrors[terrlen:] + d.terrors = d.terrors[:terrlen] + return &TypeError{issues} + } + return nil + }) + if e, ok := err.(*TypeError); ok { + d.terrors = append(d.terrors, e.Errors...) + return false + } + if err != nil { + fail(err) + } + return true +} + +// d.prepare initializes and dereferences pointers and calls UnmarshalYAML +// if a value is found to implement it. +// It returns the initialized and dereferenced out value, whether +// unmarshalling was already done by UnmarshalYAML, and if so whether +// its types unmarshalled appropriately. +// +// If n holds a null value, prepare returns before doing anything. +func (d *decoder) prepare(n *node, out reflect.Value) (newout reflect.Value, unmarshaled, good bool) { + if n.tag == yaml_NULL_TAG || n.kind == scalarNode && n.tag == "" && (n.value == "null" || n.value == "~" || n.value == "" && n.implicit) { + return out, false, false + } + again := true + for again { + again = false + if out.Kind() == reflect.Ptr { + if out.IsNil() { + out.Set(reflect.New(out.Type().Elem())) + } + out = out.Elem() + again = true + } + if out.CanAddr() { + if u, ok := out.Addr().Interface().(Unmarshaler); ok { + good = d.callUnmarshaler(n, u) + return out, true, good + } + } + } + return out, false, false +} + +func (d *decoder) unmarshal(n *node, out reflect.Value) (good bool) { + switch n.kind { + case documentNode: + return d.document(n, out) + case aliasNode: + return d.alias(n, out) + } + out, unmarshaled, good := d.prepare(n, out) + if unmarshaled { + return good + } + switch n.kind { + case scalarNode: + good = d.scalar(n, out) + case mappingNode: + good = d.mapping(n, out) + case sequenceNode: + good = d.sequence(n, out) + default: + panic("internal error: unknown node kind: " + strconv.Itoa(n.kind)) + } + return good +} + +func (d *decoder) document(n *node, out reflect.Value) (good bool) { + if len(n.children) == 1 { + d.doc = n + d.unmarshal(n.children[0], out) + return true + } + return false +} + +func (d *decoder) alias(n *node, out reflect.Value) (good bool) { + an, ok := d.doc.anchors[n.value] + if !ok { + failf("unknown anchor '%s' referenced", n.value) + } + if d.aliases[n.value] { + failf("anchor '%s' value contains itself", n.value) + } + d.aliases[n.value] = true + good = d.unmarshal(an, out) + delete(d.aliases, n.value) + return good +} + +var zeroValue reflect.Value + +func resetMap(out reflect.Value) { + for _, k := range out.MapKeys() { + out.SetMapIndex(k, zeroValue) + } +} + +func (d *decoder) scalar(n *node, out reflect.Value) (good bool) { + var tag string + var resolved interface{} + if n.tag == "" && !n.implicit { + tag = yaml_STR_TAG + resolved = n.value + } else { + tag, resolved = resolve(n.tag, n.value) + if tag == yaml_BINARY_TAG { + data, err := base64.StdEncoding.DecodeString(resolved.(string)) + if err != nil { + failf("!!binary value contains invalid base64 data") + } + resolved = string(data) + } + } + if resolved == nil { + if out.Kind() == reflect.Map && !out.CanAddr() { + resetMap(out) + } else { + out.Set(reflect.Zero(out.Type())) + } + return true + } + if s, ok := resolved.(string); ok && out.CanAddr() { + if u, ok := out.Addr().Interface().(encoding.TextUnmarshaler); ok { + err := u.UnmarshalText([]byte(s)) + if err != nil { + fail(err) + } + return true + } + } + switch out.Kind() { + case reflect.String: + if tag == yaml_BINARY_TAG { + out.SetString(resolved.(string)) + good = true + } else if resolved != nil { + out.SetString(n.value) + good = true + } + case reflect.Interface: + if resolved == nil { + out.Set(reflect.Zero(out.Type())) + } else { + out.Set(reflect.ValueOf(resolved)) + } + good = true + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + switch resolved := resolved.(type) { + case int: + if !out.OverflowInt(int64(resolved)) { + out.SetInt(int64(resolved)) + good = true + } + case int64: + if !out.OverflowInt(resolved) { + out.SetInt(resolved) + good = true + } + case uint64: + if resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) { + out.SetInt(int64(resolved)) + good = true + } + case float64: + if resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) { + out.SetInt(int64(resolved)) + good = true + } + case string: + if out.Type() == durationType { + d, err := time.ParseDuration(resolved) + if err == nil { + out.SetInt(int64(d)) + good = true + } + } + } + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + switch resolved := resolved.(type) { + case int: + if resolved >= 0 && !out.OverflowUint(uint64(resolved)) { + out.SetUint(uint64(resolved)) + good = true + } + case int64: + if resolved >= 0 && !out.OverflowUint(uint64(resolved)) { + out.SetUint(uint64(resolved)) + good = true + } + case uint64: + if !out.OverflowUint(uint64(resolved)) { + out.SetUint(uint64(resolved)) + good = true + } + case float64: + if resolved <= math.MaxUint64 && !out.OverflowUint(uint64(resolved)) { + out.SetUint(uint64(resolved)) + good = true + } + } + case reflect.Bool: + switch resolved := resolved.(type) { + case bool: + out.SetBool(resolved) + good = true + } + case reflect.Float32, reflect.Float64: + switch resolved := resolved.(type) { + case int: + out.SetFloat(float64(resolved)) + good = true + case int64: + out.SetFloat(float64(resolved)) + good = true + case uint64: + out.SetFloat(float64(resolved)) + good = true + case float64: + out.SetFloat(resolved) + good = true + } + case reflect.Ptr: + if out.Type().Elem() == reflect.TypeOf(resolved) { + // TODO DOes this make sense? When is out a Ptr except when decoding a nil value? + elem := reflect.New(out.Type().Elem()) + elem.Elem().Set(reflect.ValueOf(resolved)) + out.Set(elem) + good = true + } + } + if !good { + d.terror(n, tag, out) + } + return good +} + +func settableValueOf(i interface{}) reflect.Value { + v := reflect.ValueOf(i) + sv := reflect.New(v.Type()).Elem() + sv.Set(v) + return sv +} + +func (d *decoder) sequence(n *node, out reflect.Value) (good bool) { + l := len(n.children) + + var iface reflect.Value + switch out.Kind() { + case reflect.Slice: + out.Set(reflect.MakeSlice(out.Type(), l, l)) + case reflect.Interface: + // No type hints. Will have to use a generic sequence. + iface = out + out = settableValueOf(make([]interface{}, l)) + default: + d.terror(n, yaml_SEQ_TAG, out) + return false + } + et := out.Type().Elem() + + j := 0 + for i := 0; i < l; i++ { + e := reflect.New(et).Elem() + if ok := d.unmarshal(n.children[i], e); ok { + out.Index(j).Set(e) + j++ + } + } + out.Set(out.Slice(0, j)) + if iface.IsValid() { + iface.Set(out) + } + return true +} + +func (d *decoder) mapping(n *node, out reflect.Value) (good bool) { + switch out.Kind() { + case reflect.Struct: + return d.mappingStruct(n, out) + case reflect.Slice: + return d.mappingSlice(n, out) + case reflect.Map: + // okay + case reflect.Interface: + if d.mapType.Kind() == reflect.Map { + iface := out + out = reflect.MakeMap(d.mapType) + iface.Set(out) + } else { + slicev := reflect.New(d.mapType).Elem() + if !d.mappingSlice(n, slicev) { + return false + } + out.Set(slicev) + return true + } + default: + d.terror(n, yaml_MAP_TAG, out) + return false + } + outt := out.Type() + kt := outt.Key() + et := outt.Elem() + + mapType := d.mapType + if outt.Key() == ifaceType && outt.Elem() == ifaceType { + d.mapType = outt + } + + if out.IsNil() { + out.Set(reflect.MakeMap(outt)) + } + l := len(n.children) + for i := 0; i < l; i += 2 { + if isMerge(n.children[i]) { + d.merge(n.children[i+1], out) + continue + } + k := reflect.New(kt).Elem() + if d.unmarshal(n.children[i], k) { + kkind := k.Kind() + if kkind == reflect.Interface { + kkind = k.Elem().Kind() + } + if kkind == reflect.Map || kkind == reflect.Slice { + failf("invalid map key: %#v", k.Interface()) + } + e := reflect.New(et).Elem() + if d.unmarshal(n.children[i+1], e) { + out.SetMapIndex(k, e) + } + } + } + d.mapType = mapType + return true +} + +func (d *decoder) mappingSlice(n *node, out reflect.Value) (good bool) { + outt := out.Type() + if outt.Elem() != mapItemType { + d.terror(n, yaml_MAP_TAG, out) + return false + } + + mapType := d.mapType + d.mapType = outt + + var slice []MapItem + var l = len(n.children) + for i := 0; i < l; i += 2 { + if isMerge(n.children[i]) { + d.merge(n.children[i+1], out) + continue + } + item := MapItem{} + k := reflect.ValueOf(&item.Key).Elem() + if d.unmarshal(n.children[i], k) { + v := reflect.ValueOf(&item.Value).Elem() + if d.unmarshal(n.children[i+1], v) { + slice = append(slice, item) + } + } + } + out.Set(reflect.ValueOf(slice)) + d.mapType = mapType + return true +} + +func (d *decoder) mappingStruct(n *node, out reflect.Value) (good bool) { + sinfo, err := getStructInfo(out.Type()) + if err != nil { + panic(err) + } + name := settableValueOf("") + l := len(n.children) + + var inlineMap reflect.Value + var elemType reflect.Type + if sinfo.InlineMap != -1 { + inlineMap = out.Field(sinfo.InlineMap) + inlineMap.Set(reflect.New(inlineMap.Type()).Elem()) + elemType = inlineMap.Type().Elem() + } + + for i := 0; i < l; i += 2 { + ni := n.children[i] + if isMerge(ni) { + d.merge(n.children[i+1], out) + continue + } + if !d.unmarshal(ni, name) { + continue + } + if info, ok := sinfo.FieldsMap[name.String()]; ok { + var field reflect.Value + if info.Inline == nil { + field = out.Field(info.Num) + } else { + field = out.FieldByIndex(info.Inline) + } + d.unmarshal(n.children[i+1], field) + } else if sinfo.InlineMap != -1 { + if inlineMap.IsNil() { + inlineMap.Set(reflect.MakeMap(inlineMap.Type())) + } + value := reflect.New(elemType).Elem() + d.unmarshal(n.children[i+1], value) + inlineMap.SetMapIndex(name, value) + } else if d.strict { + d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s not found in struct %s", ni.line+1, name.String(), out.Type())) + } + } + return true +} + +func failWantMap() { + failf("map merge requires map or sequence of maps as the value") +} + +func (d *decoder) merge(n *node, out reflect.Value) { + switch n.kind { + case mappingNode: + d.unmarshal(n, out) + case aliasNode: + an, ok := d.doc.anchors[n.value] + if ok && an.kind != mappingNode { + failWantMap() + } + d.unmarshal(n, out) + case sequenceNode: + // Step backwards as earlier nodes take precedence. + 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 { + failWantMap() + } + } else if ni.kind != mappingNode { + failWantMap() + } + d.unmarshal(ni, out) + } + default: + failWantMap() + } +} + +func isMerge(n *node) bool { + return n.kind == scalarNode && n.value == "<<" && (n.implicit == true || n.tag == yaml_MERGE_TAG) +} diff --git a/vendor/github.com/go-yaml/yaml/decode_test.go b/vendor/github.com/go-yaml/yaml/decode_test.go new file mode 100644 index 00000000..e5366c26 --- /dev/null +++ b/vendor/github.com/go-yaml/yaml/decode_test.go @@ -0,0 +1,1032 @@ +package yaml_test + +import ( + "errors" + . "gopkg.in/check.v1" + "gopkg.in/yaml.v2" + "math" + "net" + "reflect" + "strings" + "time" +) + +var unmarshalIntTest = 123 + +var unmarshalTests = []struct { + data string + value interface{} +}{ + { + "", + &struct{}{}, + }, { + "{}", &struct{}{}, + }, { + "v: hi", + map[string]string{"v": "hi"}, + }, { + "v: hi", map[string]interface{}{"v": "hi"}, + }, { + "v: true", + map[string]string{"v": "true"}, + }, { + "v: true", + map[string]interface{}{"v": true}, + }, { + "v: 10", + map[string]interface{}{"v": 10}, + }, { + "v: 0b10", + map[string]interface{}{"v": 2}, + }, { + "v: 0xA", + map[string]interface{}{"v": 10}, + }, { + "v: 4294967296", + map[string]int64{"v": 4294967296}, + }, { + "v: 0.1", + map[string]interface{}{"v": 0.1}, + }, { + "v: .1", + map[string]interface{}{"v": 0.1}, + }, { + "v: .Inf", + map[string]interface{}{"v": math.Inf(+1)}, + }, { + "v: -.Inf", + map[string]interface{}{"v": math.Inf(-1)}, + }, { + "v: -10", + map[string]interface{}{"v": -10}, + }, { + "v: -.1", + map[string]interface{}{"v": -0.1}, + }, + + // Simple values. + { + "123", + &unmarshalIntTest, + }, + + // Floats from spec + { + "canonical: 6.8523e+5", + map[string]interface{}{"canonical": 6.8523e+5}, + }, { + "expo: 685.230_15e+03", + map[string]interface{}{"expo": 685.23015e+03}, + }, { + "fixed: 685_230.15", + map[string]interface{}{"fixed": 685230.15}, + }, { + "neginf: -.inf", + map[string]interface{}{"neginf": math.Inf(-1)}, + }, { + "fixed: 685_230.15", + map[string]float64{"fixed": 685230.15}, + }, + //{"sexa: 190:20:30.15", map[string]interface{}{"sexa": 0}}, // Unsupported + //{"notanum: .NaN", map[string]interface{}{"notanum": math.NaN()}}, // Equality of NaN fails. + + // Bools from spec + { + "canonical: y", + map[string]interface{}{"canonical": true}, + }, { + "answer: NO", + map[string]interface{}{"answer": false}, + }, { + "logical: True", + map[string]interface{}{"logical": true}, + }, { + "option: on", + map[string]interface{}{"option": true}, + }, { + "option: on", + map[string]bool{"option": true}, + }, + // Ints from spec + { + "canonical: 685230", + map[string]interface{}{"canonical": 685230}, + }, { + "decimal: +685_230", + map[string]interface{}{"decimal": 685230}, + }, { + "octal: 02472256", + map[string]interface{}{"octal": 685230}, + }, { + "hexa: 0x_0A_74_AE", + map[string]interface{}{"hexa": 685230}, + }, { + "bin: 0b1010_0111_0100_1010_1110", + map[string]interface{}{"bin": 685230}, + }, { + "bin: -0b101010", + map[string]interface{}{"bin": -42}, + }, { + "decimal: +685_230", + map[string]int{"decimal": 685230}, + }, + + //{"sexa: 190:20:30", map[string]interface{}{"sexa": 0}}, // Unsupported + + // Nulls from spec + { + "empty:", + map[string]interface{}{"empty": nil}, + }, { + "canonical: ~", + map[string]interface{}{"canonical": nil}, + }, { + "english: null", + map[string]interface{}{"english": nil}, + }, { + "~: null key", + map[interface{}]string{nil: "null key"}, + }, { + "empty:", + map[string]*bool{"empty": nil}, + }, + + // Flow sequence + { + "seq: [A,B]", + map[string]interface{}{"seq": []interface{}{"A", "B"}}, + }, { + "seq: [A,B,C,]", + map[string][]string{"seq": []string{"A", "B", "C"}}, + }, { + "seq: [A,1,C]", + map[string][]string{"seq": []string{"A", "1", "C"}}, + }, { + "seq: [A,1,C]", + map[string][]int{"seq": []int{1}}, + }, { + "seq: [A,1,C]", + map[string]interface{}{"seq": []interface{}{"A", 1, "C"}}, + }, + // Block sequence + { + "seq:\n - A\n - B", + map[string]interface{}{"seq": []interface{}{"A", "B"}}, + }, { + "seq:\n - A\n - B\n - C", + map[string][]string{"seq": []string{"A", "B", "C"}}, + }, { + "seq:\n - A\n - 1\n - C", + map[string][]string{"seq": []string{"A", "1", "C"}}, + }, { + "seq:\n - A\n - 1\n - C", + map[string][]int{"seq": []int{1}}, + }, { + "seq:\n - A\n - 1\n - C", + map[string]interface{}{"seq": []interface{}{"A", 1, "C"}}, + }, + + // Literal block scalar + { + "scalar: | # Comment\n\n literal\n\n \ttext\n\n", + map[string]string{"scalar": "\nliteral\n\n\ttext\n"}, + }, + + // Folded block scalar + { + "scalar: > # Comment\n\n folded\n line\n \n next\n line\n * one\n * two\n\n last\n line\n\n", + map[string]string{"scalar": "\nfolded line\nnext line\n * one\n * two\n\nlast line\n"}, + }, + + // Map inside interface with no type hints. + { + "a: {b: c}", + map[interface{}]interface{}{"a": map[interface{}]interface{}{"b": "c"}}, + }, + + // Structs and type conversions. + { + "hello: world", + &struct{ Hello string }{"world"}, + }, { + "a: {b: c}", + &struct{ A struct{ B string } }{struct{ B string }{"c"}}, + }, { + "a: {b: c}", + &struct{ A *struct{ B string } }{&struct{ B string }{"c"}}, + }, { + "a: {b: c}", + &struct{ A map[string]string }{map[string]string{"b": "c"}}, + }, { + "a: {b: c}", + &struct{ A *map[string]string }{&map[string]string{"b": "c"}}, + }, { + "a:", + &struct{ A map[string]string }{}, + }, { + "a: 1", + &struct{ A int }{1}, + }, { + "a: 1", + &struct{ A float64 }{1}, + }, { + "a: 1.0", + &struct{ A int }{1}, + }, { + "a: 1.0", + &struct{ A uint }{1}, + }, { + "a: [1, 2]", + &struct{ A []int }{[]int{1, 2}}, + }, { + "a: 1", + &struct{ B int }{0}, + }, { + "a: 1", + &struct { + B int "a" + }{1}, + }, { + "a: y", + &struct{ A bool }{true}, + }, + + // Some cross type conversions + { + "v: 42", + map[string]uint{"v": 42}, + }, { + "v: -42", + map[string]uint{}, + }, { + "v: 4294967296", + map[string]uint64{"v": 4294967296}, + }, { + "v: -4294967296", + map[string]uint64{}, + }, + + // int + { + "int_max: 2147483647", + map[string]int{"int_max": math.MaxInt32}, + }, + { + "int_min: -2147483648", + map[string]int{"int_min": math.MinInt32}, + }, + { + "int_overflow: 9223372036854775808", // math.MaxInt64 + 1 + map[string]int{}, + }, + + // int64 + { + "int64_max: 9223372036854775807", + map[string]int64{"int64_max": math.MaxInt64}, + }, + { + "int64_max_base2: 0b111111111111111111111111111111111111111111111111111111111111111", + map[string]int64{"int64_max_base2": math.MaxInt64}, + }, + { + "int64_min: -9223372036854775808", + map[string]int64{"int64_min": math.MinInt64}, + }, + { + "int64_neg_base2: -0b111111111111111111111111111111111111111111111111111111111111111", + map[string]int64{"int64_neg_base2": -math.MaxInt64}, + }, + { + "int64_overflow: 9223372036854775808", // math.MaxInt64 + 1 + map[string]int64{}, + }, + + // uint + { + "uint_min: 0", + map[string]uint{"uint_min": 0}, + }, + { + "uint_max: 4294967295", + map[string]uint{"uint_max": math.MaxUint32}, + }, + { + "uint_underflow: -1", + map[string]uint{}, + }, + + // uint64 + { + "uint64_min: 0", + map[string]uint{"uint64_min": 0}, + }, + { + "uint64_max: 18446744073709551615", + map[string]uint64{"uint64_max": math.MaxUint64}, + }, + { + "uint64_max_base2: 0b1111111111111111111111111111111111111111111111111111111111111111", + map[string]uint64{"uint64_max_base2": math.MaxUint64}, + }, + { + "uint64_maxint64: 9223372036854775807", + map[string]uint64{"uint64_maxint64": math.MaxInt64}, + }, + { + "uint64_underflow: -1", + map[string]uint64{}, + }, + + // float32 + { + "float32_max: 3.40282346638528859811704183484516925440e+38", + map[string]float32{"float32_max": math.MaxFloat32}, + }, + { + "float32_nonzero: 1.401298464324817070923729583289916131280e-45", + map[string]float32{"float32_nonzero": math.SmallestNonzeroFloat32}, + }, + { + "float32_maxuint64: 18446744073709551615", + map[string]float32{"float32_maxuint64": float32(math.MaxUint64)}, + }, + { + "float32_maxuint64+1: 18446744073709551616", + map[string]float32{"float32_maxuint64+1": float32(math.MaxUint64 + 1)}, + }, + + // float64 + { + "float64_max: 1.797693134862315708145274237317043567981e+308", + map[string]float64{"float64_max": math.MaxFloat64}, + }, + { + "float64_nonzero: 4.940656458412465441765687928682213723651e-324", + map[string]float64{"float64_nonzero": math.SmallestNonzeroFloat64}, + }, + { + "float64_maxuint64: 18446744073709551615", + map[string]float64{"float64_maxuint64": float64(math.MaxUint64)}, + }, + { + "float64_maxuint64+1: 18446744073709551616", + map[string]float64{"float64_maxuint64+1": float64(math.MaxUint64 + 1)}, + }, + + // Overflow cases. + { + "v: 4294967297", + map[string]int32{}, + }, { + "v: 128", + map[string]int8{}, + }, + + // Quoted values. + { + "'1': '\"2\"'", + map[interface{}]interface{}{"1": "\"2\""}, + }, { + "v:\n- A\n- 'B\n\n C'\n", + map[string][]string{"v": []string{"A", "B\nC"}}, + }, + + // Explicit tags. + { + "v: !!float '1.1'", + map[string]interface{}{"v": 1.1}, + }, { + "v: !!null ''", + map[string]interface{}{"v": nil}, + }, { + "%TAG !y! tag:yaml.org,2002:\n---\nv: !y!int '1'", + map[string]interface{}{"v": 1}, + }, + + // Non-specific tag (Issue #75) + { + "v: ! test", + map[string]interface{}{"v": "test"}, + }, + + // Anchors and aliases. + { + "a: &x 1\nb: &y 2\nc: *x\nd: *y\n", + &struct{ A, B, C, D int }{1, 2, 1, 2}, + }, { + "a: &a {c: 1}\nb: *a", + &struct { + A, B struct { + C int + } + }{struct{ C int }{1}, struct{ C int }{1}}, + }, { + "a: &a [1, 2]\nb: *a", + &struct{ B []int }{[]int{1, 2}}, + }, { + "b: *a\na: &a {c: 1}", + &struct { + A, B struct { + C int + } + }{struct{ C int }{1}, struct{ C int }{1}}, + }, + + // Bug #1133337 + { + "foo: ''", + map[string]*string{"foo": new(string)}, + }, { + "foo: null", + map[string]*string{"foo": nil}, + }, { + "foo: null", + map[string]string{"foo": ""}, + }, { + "foo: null", + map[string]interface{}{"foo": nil}, + }, + + // Support for ~ + { + "foo: ~", + map[string]*string{"foo": nil}, + }, { + "foo: ~", + map[string]string{"foo": ""}, + }, { + "foo: ~", + map[string]interface{}{"foo": nil}, + }, + + // Ignored field + { + "a: 1\nb: 2\n", + &struct { + A int + B int "-" + }{1, 0}, + }, + + // Bug #1191981 + { + "" + + "%YAML 1.1\n" + + "--- !!str\n" + + `"Generic line break (no glyph)\n\` + "\n" + + ` Generic line break (glyphed)\n\` + "\n" + + ` Line separator\u2028\` + "\n" + + ` Paragraph separator\u2029"` + "\n", + "" + + "Generic line break (no glyph)\n" + + "Generic line break (glyphed)\n" + + "Line separator\u2028Paragraph separator\u2029", + }, + + // Struct inlining + { + "a: 1\nb: 2\nc: 3\n", + &struct { + A int + C inlineB `yaml:",inline"` + }{1, inlineB{2, inlineC{3}}}, + }, + + // Map inlining + { + "a: 1\nb: 2\nc: 3\n", + &struct { + A int + C map[string]int `yaml:",inline"` + }{1, map[string]int{"b": 2, "c": 3}}, + }, + + // bug 1243827 + { + "a: -b_c", + map[string]interface{}{"a": "-b_c"}, + }, + { + "a: +b_c", + map[string]interface{}{"a": "+b_c"}, + }, + { + "a: 50cent_of_dollar", + map[string]interface{}{"a": "50cent_of_dollar"}, + }, + + // Duration + { + "a: 3s", + map[string]time.Duration{"a": 3 * time.Second}, + }, + + // Issue #24. + { + "a: ", + map[string]string{"a": ""}, + }, + + // Base 60 floats are obsolete and unsupported. + { + "a: 1:1\n", + map[string]string{"a": "1:1"}, + }, + + // Binary data. + { + "a: !!binary gIGC\n", + map[string]string{"a": "\x80\x81\x82"}, + }, { + "a: !!binary |\n " + strings.Repeat("kJCQ", 17) + "kJ\n CQ\n", + map[string]string{"a": strings.Repeat("\x90", 54)}, + }, { + "a: !!binary |\n " + strings.Repeat("A", 70) + "\n ==\n", + map[string]string{"a": strings.Repeat("\x00", 52)}, + }, + + // Ordered maps. + { + "{b: 2, a: 1, d: 4, c: 3, sub: {e: 5}}", + &yaml.MapSlice{{"b", 2}, {"a", 1}, {"d", 4}, {"c", 3}, {"sub", yaml.MapSlice{{"e", 5}}}}, + }, + + // Issue #39. + { + "a:\n b:\n c: d\n", + map[string]struct{ B interface{} }{"a": {map[interface{}]interface{}{"c": "d"}}}, + }, + + // Custom map type. + { + "a: {b: c}", + M{"a": M{"b": "c"}}, + }, + + // Support encoding.TextUnmarshaler. + { + "a: 1.2.3.4\n", + map[string]net.IP{"a": net.IPv4(1, 2, 3, 4)}, + }, + { + "a: 2015-02-24T18:19:39Z\n", + map[string]time.Time{"a": time.Unix(1424801979, 0).In(time.UTC)}, + }, + + // Encode empty lists as zero-length slices. + { + "a: []", + &struct{ A []int }{[]int{}}, + }, + + // UTF-16-LE + { + "\xff\xfe\xf1\x00o\x00\xf1\x00o\x00:\x00 \x00v\x00e\x00r\x00y\x00 \x00y\x00e\x00s\x00\n\x00", + M{"ñoño": "very yes"}, + }, + // UTF-16-LE with surrogate. + { + "\xff\xfe\xf1\x00o\x00\xf1\x00o\x00:\x00 \x00v\x00e\x00r\x00y\x00 \x00y\x00e\x00s\x00 \x00=\xd8\xd4\xdf\n\x00", + M{"ñoño": "very yes 🟔"}, + }, + + // UTF-16-BE + { + "\xfe\xff\x00\xf1\x00o\x00\xf1\x00o\x00:\x00 \x00v\x00e\x00r\x00y\x00 \x00y\x00e\x00s\x00\n", + M{"ñoño": "very yes"}, + }, + // UTF-16-BE with surrogate. + { + "\xfe\xff\x00\xf1\x00o\x00\xf1\x00o\x00:\x00 \x00v\x00e\x00r\x00y\x00 \x00y\x00e\x00s\x00 \xd8=\xdf\xd4\x00\n", + M{"ñoño": "very yes 🟔"}, + }, + + // YAML Float regex shouldn't match this + { + "a: 123456e1\n", + M{"a": "123456e1"}, + }, { + "a: 123456E1\n", + M{"a": "123456E1"}, + }, +} + +type M map[interface{}]interface{} + +type inlineB struct { + B int + inlineC `yaml:",inline"` +} + +type inlineC struct { + C int +} + +func (s *S) TestUnmarshal(c *C) { + for i, item := range unmarshalTests { + c.Logf("test %d: %q", i, item.data) + t := reflect.ValueOf(item.value).Type() + var value interface{} + switch t.Kind() { + case reflect.Map: + value = reflect.MakeMap(t).Interface() + case reflect.String: + value = reflect.New(t).Interface() + case reflect.Ptr: + value = reflect.New(t.Elem()).Interface() + default: + c.Fatalf("missing case for %s", t) + } + err := yaml.Unmarshal([]byte(item.data), value) + if _, ok := err.(*yaml.TypeError); !ok { + c.Assert(err, IsNil) + } + if t.Kind() == reflect.String { + c.Assert(*value.(*string), Equals, item.value) + } else { + c.Assert(value, DeepEquals, item.value) + } + } +} + +func (s *S) TestUnmarshalNaN(c *C) { + value := map[string]interface{}{} + err := yaml.Unmarshal([]byte("notanum: .NaN"), &value) + c.Assert(err, IsNil) + c.Assert(math.IsNaN(value["notanum"].(float64)), Equals, true) +} + +var unmarshalErrorTests = []struct { + data, error string +}{ + {"v: !!float 'error'", "yaml: cannot decode !!str `error` as a !!float"}, + {"v: [A,", "yaml: line 1: did not find expected node content"}, + {"v:\n- [A,", "yaml: line 2: did not find expected node content"}, + {"a: *b\n", "yaml: unknown anchor 'b' referenced"}, + {"a: &a\n b: *a\n", "yaml: anchor 'a' value contains itself"}, + {"value: -", "yaml: block sequence entries are not allowed in this context"}, + {"a: !!binary ==", "yaml: !!binary value contains invalid base64 data"}, + {"{[.]}", `yaml: invalid map key: \[\]interface \{\}\{"\."\}`}, + {"{{.}}", `yaml: invalid map key: map\[interface\ \{\}\]interface \{\}\{".":interface \{\}\(nil\)\}`}, + {"%TAG !%79! tag:yaml.org,2002:\n---\nv: !%79!int '1'", "yaml: did not find expected whitespace"}, +} + +func (s *S) TestUnmarshalErrors(c *C) { + for _, item := range unmarshalErrorTests { + var value interface{} + err := yaml.Unmarshal([]byte(item.data), &value) + c.Assert(err, ErrorMatches, item.error, Commentf("Partial unmarshal: %#v", value)) + } +} + +var unmarshalerTests = []struct { + data, tag string + value interface{} +}{ + {"_: {hi: there}", "!!map", map[interface{}]interface{}{"hi": "there"}}, + {"_: [1,A]", "!!seq", []interface{}{1, "A"}}, + {"_: 10", "!!int", 10}, + {"_: null", "!!null", nil}, + {`_: BAR!`, "!!str", "BAR!"}, + {`_: "BAR!"`, "!!str", "BAR!"}, + {"_: !!foo 'BAR!'", "!!foo", "BAR!"}, + {`_: ""`, "!!str", ""}, +} + +var unmarshalerResult = map[int]error{} + +type unmarshalerType struct { + value interface{} +} + +func (o *unmarshalerType) UnmarshalYAML(unmarshal func(v interface{}) error) error { + if err := unmarshal(&o.value); err != nil { + return err + } + if i, ok := o.value.(int); ok { + if result, ok := unmarshalerResult[i]; ok { + return result + } + } + return nil +} + +type unmarshalerPointer struct { + Field *unmarshalerType "_" +} + +type unmarshalerValue struct { + Field unmarshalerType "_" +} + +func (s *S) TestUnmarshalerPointerField(c *C) { + for _, item := range unmarshalerTests { + obj := &unmarshalerPointer{} + err := yaml.Unmarshal([]byte(item.data), obj) + c.Assert(err, IsNil) + if item.value == nil { + c.Assert(obj.Field, IsNil) + } else { + c.Assert(obj.Field, NotNil, Commentf("Pointer not initialized (%#v)", item.value)) + c.Assert(obj.Field.value, DeepEquals, item.value) + } + } +} + +func (s *S) TestUnmarshalerValueField(c *C) { + for _, item := range unmarshalerTests { + obj := &unmarshalerValue{} + err := yaml.Unmarshal([]byte(item.data), obj) + c.Assert(err, IsNil) + c.Assert(obj.Field, NotNil, Commentf("Pointer not initialized (%#v)", item.value)) + c.Assert(obj.Field.value, DeepEquals, item.value) + } +} + +func (s *S) TestUnmarshalerWholeDocument(c *C) { + obj := &unmarshalerType{} + err := yaml.Unmarshal([]byte(unmarshalerTests[0].data), obj) + c.Assert(err, IsNil) + value, ok := obj.value.(map[interface{}]interface{}) + c.Assert(ok, Equals, true, Commentf("value: %#v", obj.value)) + c.Assert(value["_"], DeepEquals, unmarshalerTests[0].value) +} + +func (s *S) TestUnmarshalerTypeError(c *C) { + unmarshalerResult[2] = &yaml.TypeError{[]string{"foo"}} + unmarshalerResult[4] = &yaml.TypeError{[]string{"bar"}} + defer func() { + delete(unmarshalerResult, 2) + delete(unmarshalerResult, 4) + }() + + type T struct { + Before int + After int + M map[string]*unmarshalerType + } + var v T + data := `{before: A, m: {abc: 1, def: 2, ghi: 3, jkl: 4}, after: B}` + err := yaml.Unmarshal([]byte(data), &v) + c.Assert(err, ErrorMatches, ""+ + "yaml: unmarshal errors:\n"+ + " line 1: cannot unmarshal !!str `A` into int\n"+ + " foo\n"+ + " bar\n"+ + " line 1: cannot unmarshal !!str `B` into int") + c.Assert(v.M["abc"], NotNil) + c.Assert(v.M["def"], IsNil) + c.Assert(v.M["ghi"], NotNil) + c.Assert(v.M["jkl"], IsNil) + + c.Assert(v.M["abc"].value, Equals, 1) + c.Assert(v.M["ghi"].value, Equals, 3) +} + +type proxyTypeError struct{} + +func (v *proxyTypeError) UnmarshalYAML(unmarshal func(interface{}) error) error { + var s string + var a int32 + var b int64 + if err := unmarshal(&s); err != nil { + panic(err) + } + if s == "a" { + if err := unmarshal(&b); err == nil { + panic("should have failed") + } + return unmarshal(&a) + } + if err := unmarshal(&a); err == nil { + panic("should have failed") + } + return unmarshal(&b) +} + +func (s *S) TestUnmarshalerTypeErrorProxying(c *C) { + type T struct { + Before int + After int + M map[string]*proxyTypeError + } + var v T + data := `{before: A, m: {abc: a, def: b}, after: B}` + err := yaml.Unmarshal([]byte(data), &v) + c.Assert(err, ErrorMatches, ""+ + "yaml: unmarshal errors:\n"+ + " line 1: cannot unmarshal !!str `A` into int\n"+ + " line 1: cannot unmarshal !!str `a` into int32\n"+ + " line 1: cannot unmarshal !!str `b` into int64\n"+ + " line 1: cannot unmarshal !!str `B` into int") +} + +type failingUnmarshaler struct{} + +var failingErr = errors.New("failingErr") + +func (ft *failingUnmarshaler) UnmarshalYAML(unmarshal func(interface{}) error) error { + return failingErr +} + +func (s *S) TestUnmarshalerError(c *C) { + err := yaml.Unmarshal([]byte("a: b"), &failingUnmarshaler{}) + c.Assert(err, Equals, failingErr) +} + +type sliceUnmarshaler []int + +func (su *sliceUnmarshaler) UnmarshalYAML(unmarshal func(interface{}) error) error { + var slice []int + err := unmarshal(&slice) + if err == nil { + *su = slice + return nil + } + + var intVal int + err = unmarshal(&intVal) + if err == nil { + *su = []int{intVal} + return nil + } + + return err +} + +func (s *S) TestUnmarshalerRetry(c *C) { + var su sliceUnmarshaler + err := yaml.Unmarshal([]byte("[1, 2, 3]"), &su) + c.Assert(err, IsNil) + c.Assert(su, DeepEquals, sliceUnmarshaler([]int{1, 2, 3})) + + err = yaml.Unmarshal([]byte("1"), &su) + c.Assert(err, IsNil) + c.Assert(su, DeepEquals, sliceUnmarshaler([]int{1})) +} + +// From http://yaml.org/type/merge.html +var mergeTests = ` +anchors: + list: + - &CENTER { "x": 1, "y": 2 } + - &LEFT { "x": 0, "y": 2 } + - &BIG { "r": 10 } + - &SMALL { "r": 1 } + +# All the following maps are equal: + +plain: + # Explicit keys + "x": 1 + "y": 2 + "r": 10 + label: center/big + +mergeOne: + # Merge one map + << : *CENTER + "r": 10 + label: center/big + +mergeMultiple: + # Merge multiple maps + << : [ *CENTER, *BIG ] + label: center/big + +override: + # Override + << : [ *BIG, *LEFT, *SMALL ] + "x": 1 + label: center/big + +shortTag: + # Explicit short merge tag + !!merge "<<" : [ *CENTER, *BIG ] + label: center/big + +longTag: + # Explicit merge long tag + ! "<<" : [ *CENTER, *BIG ] + label: center/big + +inlineMap: + # Inlined map + << : {"x": 1, "y": 2, "r": 10} + label: center/big + +inlineSequenceMap: + # Inlined map in sequence + << : [ *CENTER, {"r": 10} ] + label: center/big +` + +func (s *S) TestMerge(c *C) { + var want = map[interface{}]interface{}{ + "x": 1, + "y": 2, + "r": 10, + "label": "center/big", + } + + var m map[interface{}]interface{} + err := yaml.Unmarshal([]byte(mergeTests), &m) + c.Assert(err, IsNil) + for name, test := range m { + if name == "anchors" { + continue + } + c.Assert(test, DeepEquals, want, Commentf("test %q failed", name)) + } +} + +func (s *S) TestMergeStruct(c *C) { + type Data struct { + X, Y, R int + Label string + } + want := Data{1, 2, 10, "center/big"} + + var m map[string]Data + err := yaml.Unmarshal([]byte(mergeTests), &m) + c.Assert(err, IsNil) + for name, test := range m { + if name == "anchors" { + continue + } + c.Assert(test, Equals, want, Commentf("test %q failed", name)) + } +} + +var unmarshalNullTests = []func() interface{}{ + func() interface{} { var v interface{}; v = "v"; return &v }, + func() interface{} { var s = "s"; return &s }, + func() interface{} { var s = "s"; sptr := &s; return &sptr }, + func() interface{} { var i = 1; return &i }, + func() interface{} { var i = 1; iptr := &i; return &iptr }, + func() interface{} { m := map[string]int{"s": 1}; return &m }, + func() interface{} { m := map[string]int{"s": 1}; return m }, +} + +func (s *S) TestUnmarshalNull(c *C) { + for _, test := range unmarshalNullTests { + item := test() + zero := reflect.Zero(reflect.TypeOf(item).Elem()).Interface() + err := yaml.Unmarshal([]byte("null"), item) + c.Assert(err, IsNil) + if reflect.TypeOf(item).Kind() == reflect.Map { + c.Assert(reflect.ValueOf(item).Interface(), DeepEquals, reflect.MakeMap(reflect.TypeOf(item)).Interface()) + } else { + c.Assert(reflect.ValueOf(item).Elem().Interface(), DeepEquals, zero) + } + } +} + +func (s *S) TestUnmarshalSliceOnPreset(c *C) { + // Issue #48. + v := struct{ A []int }{[]int{1}} + yaml.Unmarshal([]byte("a: [2]"), &v) + c.Assert(v.A, DeepEquals, []int{2}) +} + +func (s *S) TestUnmarshalStrict(c *C) { + v := struct{ A, B int }{} + + err := yaml.UnmarshalStrict([]byte("a: 1\nb: 2"), &v) + c.Check(err, IsNil) + err = yaml.Unmarshal([]byte("a: 1\nb: 2\nc: 3"), &v) + c.Check(err, IsNil) + err = yaml.UnmarshalStrict([]byte("a: 1\nb: 2\nc: 3"), &v) + c.Check(err, ErrorMatches, "yaml: unmarshal errors:\n line 3: field c not found in struct struct { A int; B int }") +} + +//var data []byte +//func init() { +// var err error +// data, err = ioutil.ReadFile("/tmp/file.yaml") +// if err != nil { +// panic(err) +// } +//} +// +//func (s *S) BenchmarkUnmarshal(c *C) { +// var err error +// for i := 0; i < c.N; i++ { +// var v map[string]interface{} +// err = yaml.Unmarshal(data, &v) +// } +// if err != nil { +// panic(err) +// } +//} +// +//func (s *S) BenchmarkMarshal(c *C) { +// var v map[string]interface{} +// yaml.Unmarshal(data, &v) +// c.ResetTimer() +// for i := 0; i < c.N; i++ { +// yaml.Marshal(&v) +// } +//} diff --git a/vendor/github.com/go-yaml/yaml/emitterc.go b/vendor/github.com/go-yaml/yaml/emitterc.go new file mode 100644 index 00000000..dcaf502f --- /dev/null +++ b/vendor/github.com/go-yaml/yaml/emitterc.go @@ -0,0 +1,1684 @@ +package yaml + +import ( + "bytes" +) + +// Flush the buffer if needed. +func flush(emitter *yaml_emitter_t) bool { + if emitter.buffer_pos+5 >= len(emitter.buffer) { + return yaml_emitter_flush(emitter) + } + return true +} + +// Put a character to the output buffer. +func put(emitter *yaml_emitter_t, value byte) bool { + if emitter.buffer_pos+5 >= len(emitter.buffer) && !yaml_emitter_flush(emitter) { + return false + } + emitter.buffer[emitter.buffer_pos] = value + emitter.buffer_pos++ + emitter.column++ + return true +} + +// Put a line break to the output buffer. +func put_break(emitter *yaml_emitter_t) bool { + if emitter.buffer_pos+5 >= len(emitter.buffer) && !yaml_emitter_flush(emitter) { + return false + } + switch emitter.line_break { + case yaml_CR_BREAK: + emitter.buffer[emitter.buffer_pos] = '\r' + emitter.buffer_pos += 1 + case yaml_LN_BREAK: + emitter.buffer[emitter.buffer_pos] = '\n' + emitter.buffer_pos += 1 + case yaml_CRLN_BREAK: + emitter.buffer[emitter.buffer_pos+0] = '\r' + emitter.buffer[emitter.buffer_pos+1] = '\n' + emitter.buffer_pos += 2 + default: + panic("unknown line break setting") + } + emitter.column = 0 + emitter.line++ + return true +} + +// Copy a character from a string into buffer. +func write(emitter *yaml_emitter_t, s []byte, i *int) bool { + if emitter.buffer_pos+5 >= len(emitter.buffer) && !yaml_emitter_flush(emitter) { + return false + } + p := emitter.buffer_pos + w := width(s[*i]) + switch w { + case 4: + emitter.buffer[p+3] = s[*i+3] + fallthrough + case 3: + emitter.buffer[p+2] = s[*i+2] + fallthrough + case 2: + emitter.buffer[p+1] = s[*i+1] + fallthrough + case 1: + emitter.buffer[p+0] = s[*i+0] + default: + panic("unknown character width") + } + emitter.column++ + emitter.buffer_pos += w + *i += w + return true +} + +// Write a whole string into buffer. +func write_all(emitter *yaml_emitter_t, s []byte) bool { + for i := 0; i < len(s); { + if !write(emitter, s, &i) { + return false + } + } + return true +} + +// Copy a line break character from a string into buffer. +func write_break(emitter *yaml_emitter_t, s []byte, i *int) bool { + if s[*i] == '\n' { + if !put_break(emitter) { + return false + } + *i++ + } else { + if !write(emitter, s, i) { + return false + } + emitter.column = 0 + emitter.line++ + } + return true +} + +// Set an emitter error and return false. +func yaml_emitter_set_emitter_error(emitter *yaml_emitter_t, problem string) bool { + emitter.error = yaml_EMITTER_ERROR + emitter.problem = problem + return false +} + +// Emit an event. +func yaml_emitter_emit(emitter *yaml_emitter_t, event *yaml_event_t) bool { + emitter.events = append(emitter.events, *event) + for !yaml_emitter_need_more_events(emitter) { + event := &emitter.events[emitter.events_head] + if !yaml_emitter_analyze_event(emitter, event) { + return false + } + if !yaml_emitter_state_machine(emitter, event) { + return false + } + yaml_event_delete(event) + emitter.events_head++ + } + return true +} + +// Check if we need to accumulate more events before emitting. +// +// We accumulate extra +// - 1 event for DOCUMENT-START +// - 2 events for SEQUENCE-START +// - 3 events for MAPPING-START +// +func yaml_emitter_need_more_events(emitter *yaml_emitter_t) bool { + if emitter.events_head == len(emitter.events) { + return true + } + var accumulate int + switch emitter.events[emitter.events_head].typ { + case yaml_DOCUMENT_START_EVENT: + accumulate = 1 + break + case yaml_SEQUENCE_START_EVENT: + accumulate = 2 + break + case yaml_MAPPING_START_EVENT: + accumulate = 3 + break + default: + return false + } + if len(emitter.events)-emitter.events_head > accumulate { + return false + } + var level int + for i := emitter.events_head; i < len(emitter.events); i++ { + switch emitter.events[i].typ { + case yaml_STREAM_START_EVENT, yaml_DOCUMENT_START_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT: + level++ + case yaml_STREAM_END_EVENT, yaml_DOCUMENT_END_EVENT, yaml_SEQUENCE_END_EVENT, yaml_MAPPING_END_EVENT: + level-- + } + if level == 0 { + return false + } + } + return true +} + +// Append a directive to the directives stack. +func yaml_emitter_append_tag_directive(emitter *yaml_emitter_t, value *yaml_tag_directive_t, allow_duplicates bool) bool { + for i := 0; i < len(emitter.tag_directives); i++ { + if bytes.Equal(value.handle, emitter.tag_directives[i].handle) { + if allow_duplicates { + return true + } + return yaml_emitter_set_emitter_error(emitter, "duplicate %TAG directive") + } + } + + // [Go] Do we actually need to copy this given garbage collection + // and the lack of deallocating destructors? + tag_copy := yaml_tag_directive_t{ + handle: make([]byte, len(value.handle)), + prefix: make([]byte, len(value.prefix)), + } + copy(tag_copy.handle, value.handle) + copy(tag_copy.prefix, value.prefix) + emitter.tag_directives = append(emitter.tag_directives, tag_copy) + return true +} + +// Increase the indentation level. +func yaml_emitter_increase_indent(emitter *yaml_emitter_t, flow, indentless bool) bool { + emitter.indents = append(emitter.indents, emitter.indent) + if emitter.indent < 0 { + if flow { + emitter.indent = emitter.best_indent + } else { + emitter.indent = 0 + } + } else if !indentless { + emitter.indent += emitter.best_indent + } + return true +} + +// State dispatcher. +func yaml_emitter_state_machine(emitter *yaml_emitter_t, event *yaml_event_t) bool { + switch emitter.state { + default: + case yaml_EMIT_STREAM_START_STATE: + return yaml_emitter_emit_stream_start(emitter, event) + + case yaml_EMIT_FIRST_DOCUMENT_START_STATE: + return yaml_emitter_emit_document_start(emitter, event, true) + + case yaml_EMIT_DOCUMENT_START_STATE: + return yaml_emitter_emit_document_start(emitter, event, false) + + case yaml_EMIT_DOCUMENT_CONTENT_STATE: + return yaml_emitter_emit_document_content(emitter, event) + + case yaml_EMIT_DOCUMENT_END_STATE: + return yaml_emitter_emit_document_end(emitter, event) + + case yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE: + return yaml_emitter_emit_flow_sequence_item(emitter, event, true) + + case yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE: + return yaml_emitter_emit_flow_sequence_item(emitter, event, false) + + case yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE: + return yaml_emitter_emit_flow_mapping_key(emitter, event, true) + + case yaml_EMIT_FLOW_MAPPING_KEY_STATE: + return yaml_emitter_emit_flow_mapping_key(emitter, event, false) + + case yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE: + return yaml_emitter_emit_flow_mapping_value(emitter, event, true) + + case yaml_EMIT_FLOW_MAPPING_VALUE_STATE: + return yaml_emitter_emit_flow_mapping_value(emitter, event, false) + + case yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE: + return yaml_emitter_emit_block_sequence_item(emitter, event, true) + + case yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE: + return yaml_emitter_emit_block_sequence_item(emitter, event, false) + + case yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE: + return yaml_emitter_emit_block_mapping_key(emitter, event, true) + + case yaml_EMIT_BLOCK_MAPPING_KEY_STATE: + return yaml_emitter_emit_block_mapping_key(emitter, event, false) + + case yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE: + return yaml_emitter_emit_block_mapping_value(emitter, event, true) + + case yaml_EMIT_BLOCK_MAPPING_VALUE_STATE: + return yaml_emitter_emit_block_mapping_value(emitter, event, false) + + case yaml_EMIT_END_STATE: + return yaml_emitter_set_emitter_error(emitter, "expected nothing after STREAM-END") + } + panic("invalid emitter state") +} + +// Expect STREAM-START. +func yaml_emitter_emit_stream_start(emitter *yaml_emitter_t, event *yaml_event_t) bool { + if event.typ != yaml_STREAM_START_EVENT { + return yaml_emitter_set_emitter_error(emitter, "expected STREAM-START") + } + if emitter.encoding == yaml_ANY_ENCODING { + emitter.encoding = event.encoding + if emitter.encoding == yaml_ANY_ENCODING { + emitter.encoding = yaml_UTF8_ENCODING + } + } + if emitter.best_indent < 2 || emitter.best_indent > 9 { + emitter.best_indent = 2 + } + if emitter.best_width >= 0 && emitter.best_width <= emitter.best_indent*2 { + emitter.best_width = 80 + } + if emitter.best_width < 0 { + emitter.best_width = 1<<31 - 1 + } + if emitter.line_break == yaml_ANY_BREAK { + emitter.line_break = yaml_LN_BREAK + } + + emitter.indent = -1 + emitter.line = 0 + emitter.column = 0 + emitter.whitespace = true + emitter.indention = true + + if emitter.encoding != yaml_UTF8_ENCODING { + if !yaml_emitter_write_bom(emitter) { + return false + } + } + emitter.state = yaml_EMIT_FIRST_DOCUMENT_START_STATE + return true +} + +// Expect DOCUMENT-START or STREAM-END. +func yaml_emitter_emit_document_start(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool { + + if event.typ == yaml_DOCUMENT_START_EVENT { + + if event.version_directive != nil { + if !yaml_emitter_analyze_version_directive(emitter, event.version_directive) { + return false + } + } + + for i := 0; i < len(event.tag_directives); i++ { + tag_directive := &event.tag_directives[i] + if !yaml_emitter_analyze_tag_directive(emitter, tag_directive) { + return false + } + if !yaml_emitter_append_tag_directive(emitter, tag_directive, false) { + return false + } + } + + for i := 0; i < len(default_tag_directives); i++ { + tag_directive := &default_tag_directives[i] + if !yaml_emitter_append_tag_directive(emitter, tag_directive, true) { + return false + } + } + + implicit := event.implicit + if !first || emitter.canonical { + implicit = false + } + + if emitter.open_ended && (event.version_directive != nil || len(event.tag_directives) > 0) { + if !yaml_emitter_write_indicator(emitter, []byte("..."), true, false, false) { + return false + } + if !yaml_emitter_write_indent(emitter) { + return false + } + } + + if event.version_directive != nil { + implicit = false + if !yaml_emitter_write_indicator(emitter, []byte("%YAML"), true, false, false) { + return false + } + if !yaml_emitter_write_indicator(emitter, []byte("1.1"), true, false, false) { + return false + } + if !yaml_emitter_write_indent(emitter) { + return false + } + } + + if len(event.tag_directives) > 0 { + implicit = false + for i := 0; i < len(event.tag_directives); i++ { + tag_directive := &event.tag_directives[i] + if !yaml_emitter_write_indicator(emitter, []byte("%TAG"), true, false, false) { + return false + } + if !yaml_emitter_write_tag_handle(emitter, tag_directive.handle) { + return false + } + if !yaml_emitter_write_tag_content(emitter, tag_directive.prefix, true) { + return false + } + if !yaml_emitter_write_indent(emitter) { + return false + } + } + } + + if yaml_emitter_check_empty_document(emitter) { + implicit = false + } + if !implicit { + if !yaml_emitter_write_indent(emitter) { + return false + } + if !yaml_emitter_write_indicator(emitter, []byte("---"), true, false, false) { + return false + } + if emitter.canonical { + if !yaml_emitter_write_indent(emitter) { + return false + } + } + } + + emitter.state = yaml_EMIT_DOCUMENT_CONTENT_STATE + return true + } + + if event.typ == yaml_STREAM_END_EVENT { + if emitter.open_ended { + if !yaml_emitter_write_indicator(emitter, []byte("..."), true, false, false) { + return false + } + if !yaml_emitter_write_indent(emitter) { + return false + } + } + if !yaml_emitter_flush(emitter) { + return false + } + emitter.state = yaml_EMIT_END_STATE + return true + } + + return yaml_emitter_set_emitter_error(emitter, "expected DOCUMENT-START or STREAM-END") +} + +// Expect the root node. +func yaml_emitter_emit_document_content(emitter *yaml_emitter_t, event *yaml_event_t) bool { + emitter.states = append(emitter.states, yaml_EMIT_DOCUMENT_END_STATE) + return yaml_emitter_emit_node(emitter, event, true, false, false, false) +} + +// Expect DOCUMENT-END. +func yaml_emitter_emit_document_end(emitter *yaml_emitter_t, event *yaml_event_t) bool { + if event.typ != yaml_DOCUMENT_END_EVENT { + return yaml_emitter_set_emitter_error(emitter, "expected DOCUMENT-END") + } + if !yaml_emitter_write_indent(emitter) { + return false + } + if !event.implicit { + // [Go] Allocate the slice elsewhere. + if !yaml_emitter_write_indicator(emitter, []byte("..."), true, false, false) { + return false + } + if !yaml_emitter_write_indent(emitter) { + return false + } + } + if !yaml_emitter_flush(emitter) { + return false + } + emitter.state = yaml_EMIT_DOCUMENT_START_STATE + emitter.tag_directives = emitter.tag_directives[:0] + return true +} + +// Expect a flow item node. +func yaml_emitter_emit_flow_sequence_item(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool { + if first { + if !yaml_emitter_write_indicator(emitter, []byte{'['}, true, true, false) { + return false + } + if !yaml_emitter_increase_indent(emitter, true, false) { + return false + } + emitter.flow_level++ + } + + if event.typ == yaml_SEQUENCE_END_EVENT { + emitter.flow_level-- + emitter.indent = emitter.indents[len(emitter.indents)-1] + emitter.indents = emitter.indents[:len(emitter.indents)-1] + if emitter.canonical && !first { + if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) { + return false + } + if !yaml_emitter_write_indent(emitter) { + return false + } + } + if !yaml_emitter_write_indicator(emitter, []byte{']'}, false, false, false) { + return false + } + emitter.state = emitter.states[len(emitter.states)-1] + emitter.states = emitter.states[:len(emitter.states)-1] + + return true + } + + if !first { + if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) { + return false + } + } + + if emitter.canonical || emitter.column > emitter.best_width { + if !yaml_emitter_write_indent(emitter) { + return false + } + } + emitter.states = append(emitter.states, yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE) + return yaml_emitter_emit_node(emitter, event, false, true, false, false) +} + +// Expect a flow key node. +func yaml_emitter_emit_flow_mapping_key(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool { + if first { + if !yaml_emitter_write_indicator(emitter, []byte{'{'}, true, true, false) { + return false + } + if !yaml_emitter_increase_indent(emitter, true, false) { + return false + } + emitter.flow_level++ + } + + if event.typ == yaml_MAPPING_END_EVENT { + emitter.flow_level-- + emitter.indent = emitter.indents[len(emitter.indents)-1] + emitter.indents = emitter.indents[:len(emitter.indents)-1] + if emitter.canonical && !first { + if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) { + return false + } + if !yaml_emitter_write_indent(emitter) { + return false + } + } + if !yaml_emitter_write_indicator(emitter, []byte{'}'}, false, false, false) { + return false + } + emitter.state = emitter.states[len(emitter.states)-1] + emitter.states = emitter.states[:len(emitter.states)-1] + return true + } + + if !first { + if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) { + return false + } + } + if emitter.canonical || emitter.column > emitter.best_width { + if !yaml_emitter_write_indent(emitter) { + return false + } + } + + if !emitter.canonical && yaml_emitter_check_simple_key(emitter) { + emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE) + return yaml_emitter_emit_node(emitter, event, false, false, true, true) + } + if !yaml_emitter_write_indicator(emitter, []byte{'?'}, true, false, false) { + return false + } + emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_VALUE_STATE) + return yaml_emitter_emit_node(emitter, event, false, false, true, false) +} + +// Expect a flow value node. +func yaml_emitter_emit_flow_mapping_value(emitter *yaml_emitter_t, event *yaml_event_t, simple bool) bool { + if simple { + if !yaml_emitter_write_indicator(emitter, []byte{':'}, false, false, false) { + return false + } + } else { + if emitter.canonical || emitter.column > emitter.best_width { + if !yaml_emitter_write_indent(emitter) { + return false + } + } + if !yaml_emitter_write_indicator(emitter, []byte{':'}, true, false, false) { + return false + } + } + emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_KEY_STATE) + return yaml_emitter_emit_node(emitter, event, false, false, true, false) +} + +// Expect a block item node. +func yaml_emitter_emit_block_sequence_item(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool { + if first { + if !yaml_emitter_increase_indent(emitter, false, emitter.mapping_context && !emitter.indention) { + return false + } + } + if event.typ == yaml_SEQUENCE_END_EVENT { + emitter.indent = emitter.indents[len(emitter.indents)-1] + emitter.indents = emitter.indents[:len(emitter.indents)-1] + emitter.state = emitter.states[len(emitter.states)-1] + emitter.states = emitter.states[:len(emitter.states)-1] + return true + } + if !yaml_emitter_write_indent(emitter) { + return false + } + if !yaml_emitter_write_indicator(emitter, []byte{'-'}, true, false, true) { + return false + } + emitter.states = append(emitter.states, yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE) + return yaml_emitter_emit_node(emitter, event, false, true, false, false) +} + +// Expect a block key node. +func yaml_emitter_emit_block_mapping_key(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool { + if first { + if !yaml_emitter_increase_indent(emitter, false, false) { + return false + } + } + if event.typ == yaml_MAPPING_END_EVENT { + emitter.indent = emitter.indents[len(emitter.indents)-1] + emitter.indents = emitter.indents[:len(emitter.indents)-1] + emitter.state = emitter.states[len(emitter.states)-1] + emitter.states = emitter.states[:len(emitter.states)-1] + return true + } + if !yaml_emitter_write_indent(emitter) { + return false + } + if yaml_emitter_check_simple_key(emitter) { + emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE) + return yaml_emitter_emit_node(emitter, event, false, false, true, true) + } + if !yaml_emitter_write_indicator(emitter, []byte{'?'}, true, false, true) { + return false + } + emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_VALUE_STATE) + return yaml_emitter_emit_node(emitter, event, false, false, true, false) +} + +// Expect a block value node. +func yaml_emitter_emit_block_mapping_value(emitter *yaml_emitter_t, event *yaml_event_t, simple bool) bool { + if simple { + if !yaml_emitter_write_indicator(emitter, []byte{':'}, false, false, false) { + return false + } + } else { + if !yaml_emitter_write_indent(emitter) { + return false + } + if !yaml_emitter_write_indicator(emitter, []byte{':'}, true, false, true) { + return false + } + } + emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_KEY_STATE) + return yaml_emitter_emit_node(emitter, event, false, false, true, false) +} + +// Expect a node. +func yaml_emitter_emit_node(emitter *yaml_emitter_t, event *yaml_event_t, + root bool, sequence bool, mapping bool, simple_key bool) bool { + + emitter.root_context = root + emitter.sequence_context = sequence + emitter.mapping_context = mapping + emitter.simple_key_context = simple_key + + switch event.typ { + case yaml_ALIAS_EVENT: + return yaml_emitter_emit_alias(emitter, event) + case yaml_SCALAR_EVENT: + return yaml_emitter_emit_scalar(emitter, event) + case yaml_SEQUENCE_START_EVENT: + return yaml_emitter_emit_sequence_start(emitter, event) + case yaml_MAPPING_START_EVENT: + return yaml_emitter_emit_mapping_start(emitter, event) + default: + return yaml_emitter_set_emitter_error(emitter, + "expected SCALAR, SEQUENCE-START, MAPPING-START, or ALIAS") + } +} + +// Expect ALIAS. +func yaml_emitter_emit_alias(emitter *yaml_emitter_t, event *yaml_event_t) bool { + if !yaml_emitter_process_anchor(emitter) { + return false + } + emitter.state = emitter.states[len(emitter.states)-1] + emitter.states = emitter.states[:len(emitter.states)-1] + return true +} + +// Expect SCALAR. +func yaml_emitter_emit_scalar(emitter *yaml_emitter_t, event *yaml_event_t) bool { + if !yaml_emitter_select_scalar_style(emitter, event) { + return false + } + if !yaml_emitter_process_anchor(emitter) { + return false + } + if !yaml_emitter_process_tag(emitter) { + return false + } + if !yaml_emitter_increase_indent(emitter, true, false) { + return false + } + if !yaml_emitter_process_scalar(emitter) { + return false + } + emitter.indent = emitter.indents[len(emitter.indents)-1] + emitter.indents = emitter.indents[:len(emitter.indents)-1] + emitter.state = emitter.states[len(emitter.states)-1] + emitter.states = emitter.states[:len(emitter.states)-1] + return true +} + +// Expect SEQUENCE-START. +func yaml_emitter_emit_sequence_start(emitter *yaml_emitter_t, event *yaml_event_t) bool { + if !yaml_emitter_process_anchor(emitter) { + return false + } + if !yaml_emitter_process_tag(emitter) { + return false + } + if emitter.flow_level > 0 || emitter.canonical || event.sequence_style() == yaml_FLOW_SEQUENCE_STYLE || + yaml_emitter_check_empty_sequence(emitter) { + emitter.state = yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE + } else { + emitter.state = yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE + } + return true +} + +// Expect MAPPING-START. +func yaml_emitter_emit_mapping_start(emitter *yaml_emitter_t, event *yaml_event_t) bool { + if !yaml_emitter_process_anchor(emitter) { + return false + } + if !yaml_emitter_process_tag(emitter) { + return false + } + if emitter.flow_level > 0 || emitter.canonical || event.mapping_style() == yaml_FLOW_MAPPING_STYLE || + yaml_emitter_check_empty_mapping(emitter) { + emitter.state = yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE + } else { + emitter.state = yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE + } + return true +} + +// Check if the document content is an empty scalar. +func yaml_emitter_check_empty_document(emitter *yaml_emitter_t) bool { + return false // [Go] Huh? +} + +// Check if the next events represent an empty sequence. +func yaml_emitter_check_empty_sequence(emitter *yaml_emitter_t) bool { + if len(emitter.events)-emitter.events_head < 2 { + return false + } + return emitter.events[emitter.events_head].typ == yaml_SEQUENCE_START_EVENT && + emitter.events[emitter.events_head+1].typ == yaml_SEQUENCE_END_EVENT +} + +// Check if the next events represent an empty mapping. +func yaml_emitter_check_empty_mapping(emitter *yaml_emitter_t) bool { + if len(emitter.events)-emitter.events_head < 2 { + return false + } + return emitter.events[emitter.events_head].typ == yaml_MAPPING_START_EVENT && + emitter.events[emitter.events_head+1].typ == yaml_MAPPING_END_EVENT +} + +// Check if the next node can be expressed as a simple key. +func yaml_emitter_check_simple_key(emitter *yaml_emitter_t) bool { + length := 0 + switch emitter.events[emitter.events_head].typ { + case yaml_ALIAS_EVENT: + length += len(emitter.anchor_data.anchor) + case yaml_SCALAR_EVENT: + if emitter.scalar_data.multiline { + return false + } + length += len(emitter.anchor_data.anchor) + + len(emitter.tag_data.handle) + + len(emitter.tag_data.suffix) + + len(emitter.scalar_data.value) + case yaml_SEQUENCE_START_EVENT: + if !yaml_emitter_check_empty_sequence(emitter) { + return false + } + length += len(emitter.anchor_data.anchor) + + len(emitter.tag_data.handle) + + len(emitter.tag_data.suffix) + case yaml_MAPPING_START_EVENT: + if !yaml_emitter_check_empty_mapping(emitter) { + return false + } + length += len(emitter.anchor_data.anchor) + + len(emitter.tag_data.handle) + + len(emitter.tag_data.suffix) + default: + return false + } + return length <= 128 +} + +// Determine an acceptable scalar style. +func yaml_emitter_select_scalar_style(emitter *yaml_emitter_t, event *yaml_event_t) bool { + + no_tag := len(emitter.tag_data.handle) == 0 && len(emitter.tag_data.suffix) == 0 + if no_tag && !event.implicit && !event.quoted_implicit { + return yaml_emitter_set_emitter_error(emitter, "neither tag nor implicit flags are specified") + } + + style := event.scalar_style() + if style == yaml_ANY_SCALAR_STYLE { + style = yaml_PLAIN_SCALAR_STYLE + } + if emitter.canonical { + style = yaml_DOUBLE_QUOTED_SCALAR_STYLE + } + if emitter.simple_key_context && emitter.scalar_data.multiline { + style = yaml_DOUBLE_QUOTED_SCALAR_STYLE + } + + if style == yaml_PLAIN_SCALAR_STYLE { + if emitter.flow_level > 0 && !emitter.scalar_data.flow_plain_allowed || + emitter.flow_level == 0 && !emitter.scalar_data.block_plain_allowed { + style = yaml_SINGLE_QUOTED_SCALAR_STYLE + } + if len(emitter.scalar_data.value) == 0 && (emitter.flow_level > 0 || emitter.simple_key_context) { + style = yaml_SINGLE_QUOTED_SCALAR_STYLE + } + if no_tag && !event.implicit { + style = yaml_SINGLE_QUOTED_SCALAR_STYLE + } + } + if style == yaml_SINGLE_QUOTED_SCALAR_STYLE { + if !emitter.scalar_data.single_quoted_allowed { + style = yaml_DOUBLE_QUOTED_SCALAR_STYLE + } + } + if style == yaml_LITERAL_SCALAR_STYLE || style == yaml_FOLDED_SCALAR_STYLE { + if !emitter.scalar_data.block_allowed || emitter.flow_level > 0 || emitter.simple_key_context { + style = yaml_DOUBLE_QUOTED_SCALAR_STYLE + } + } + + if no_tag && !event.quoted_implicit && style != yaml_PLAIN_SCALAR_STYLE { + emitter.tag_data.handle = []byte{'!'} + } + emitter.scalar_data.style = style + return true +} + +// Write an achor. +func yaml_emitter_process_anchor(emitter *yaml_emitter_t) bool { + if emitter.anchor_data.anchor == nil { + return true + } + c := []byte{'&'} + if emitter.anchor_data.alias { + c[0] = '*' + } + if !yaml_emitter_write_indicator(emitter, c, true, false, false) { + return false + } + return yaml_emitter_write_anchor(emitter, emitter.anchor_data.anchor) +} + +// Write a tag. +func yaml_emitter_process_tag(emitter *yaml_emitter_t) bool { + if len(emitter.tag_data.handle) == 0 && len(emitter.tag_data.suffix) == 0 { + return true + } + if len(emitter.tag_data.handle) > 0 { + if !yaml_emitter_write_tag_handle(emitter, emitter.tag_data.handle) { + return false + } + if len(emitter.tag_data.suffix) > 0 { + if !yaml_emitter_write_tag_content(emitter, emitter.tag_data.suffix, false) { + return false + } + } + } else { + // [Go] Allocate these slices elsewhere. + if !yaml_emitter_write_indicator(emitter, []byte("!<"), true, false, false) { + return false + } + if !yaml_emitter_write_tag_content(emitter, emitter.tag_data.suffix, false) { + return false + } + if !yaml_emitter_write_indicator(emitter, []byte{'>'}, false, false, false) { + return false + } + } + return true +} + +// Write a scalar. +func yaml_emitter_process_scalar(emitter *yaml_emitter_t) bool { + switch emitter.scalar_data.style { + case yaml_PLAIN_SCALAR_STYLE: + return yaml_emitter_write_plain_scalar(emitter, emitter.scalar_data.value, !emitter.simple_key_context) + + case yaml_SINGLE_QUOTED_SCALAR_STYLE: + return yaml_emitter_write_single_quoted_scalar(emitter, emitter.scalar_data.value, !emitter.simple_key_context) + + case yaml_DOUBLE_QUOTED_SCALAR_STYLE: + return yaml_emitter_write_double_quoted_scalar(emitter, emitter.scalar_data.value, !emitter.simple_key_context) + + case yaml_LITERAL_SCALAR_STYLE: + return yaml_emitter_write_literal_scalar(emitter, emitter.scalar_data.value) + + case yaml_FOLDED_SCALAR_STYLE: + return yaml_emitter_write_folded_scalar(emitter, emitter.scalar_data.value) + } + panic("unknown scalar style") +} + +// Check if a %YAML directive is valid. +func yaml_emitter_analyze_version_directive(emitter *yaml_emitter_t, version_directive *yaml_version_directive_t) bool { + if version_directive.major != 1 || version_directive.minor != 1 { + return yaml_emitter_set_emitter_error(emitter, "incompatible %YAML directive") + } + return true +} + +// Check if a %TAG directive is valid. +func yaml_emitter_analyze_tag_directive(emitter *yaml_emitter_t, tag_directive *yaml_tag_directive_t) bool { + handle := tag_directive.handle + prefix := tag_directive.prefix + if len(handle) == 0 { + return yaml_emitter_set_emitter_error(emitter, "tag handle must not be empty") + } + if handle[0] != '!' { + return yaml_emitter_set_emitter_error(emitter, "tag handle must start with '!'") + } + if handle[len(handle)-1] != '!' { + return yaml_emitter_set_emitter_error(emitter, "tag handle must end with '!'") + } + for i := 1; i < len(handle)-1; i += width(handle[i]) { + if !is_alpha(handle, i) { + return yaml_emitter_set_emitter_error(emitter, "tag handle must contain alphanumerical characters only") + } + } + if len(prefix) == 0 { + return yaml_emitter_set_emitter_error(emitter, "tag prefix must not be empty") + } + return true +} + +// Check if an anchor is valid. +func yaml_emitter_analyze_anchor(emitter *yaml_emitter_t, anchor []byte, alias bool) bool { + if len(anchor) == 0 { + problem := "anchor value must not be empty" + if alias { + problem = "alias value must not be empty" + } + return yaml_emitter_set_emitter_error(emitter, problem) + } + for i := 0; i < len(anchor); i += width(anchor[i]) { + if !is_alpha(anchor, i) { + problem := "anchor value must contain alphanumerical characters only" + if alias { + problem = "alias value must contain alphanumerical characters only" + } + return yaml_emitter_set_emitter_error(emitter, problem) + } + } + emitter.anchor_data.anchor = anchor + emitter.anchor_data.alias = alias + return true +} + +// Check if a tag is valid. +func yaml_emitter_analyze_tag(emitter *yaml_emitter_t, tag []byte) bool { + if len(tag) == 0 { + return yaml_emitter_set_emitter_error(emitter, "tag value must not be empty") + } + for i := 0; i < len(emitter.tag_directives); i++ { + tag_directive := &emitter.tag_directives[i] + if bytes.HasPrefix(tag, tag_directive.prefix) { + emitter.tag_data.handle = tag_directive.handle + emitter.tag_data.suffix = tag[len(tag_directive.prefix):] + return true + } + } + emitter.tag_data.suffix = tag + return true +} + +// Check if a scalar is valid. +func yaml_emitter_analyze_scalar(emitter *yaml_emitter_t, value []byte) bool { + var ( + block_indicators = false + flow_indicators = false + line_breaks = false + special_characters = false + + leading_space = false + leading_break = false + trailing_space = false + trailing_break = false + break_space = false + space_break = false + + preceded_by_whitespace = false + followed_by_whitespace = false + previous_space = false + previous_break = false + ) + + emitter.scalar_data.value = value + + if len(value) == 0 { + emitter.scalar_data.multiline = false + emitter.scalar_data.flow_plain_allowed = false + emitter.scalar_data.block_plain_allowed = true + emitter.scalar_data.single_quoted_allowed = true + emitter.scalar_data.block_allowed = false + return true + } + + if len(value) >= 3 && ((value[0] == '-' && value[1] == '-' && value[2] == '-') || (value[0] == '.' && value[1] == '.' && value[2] == '.')) { + block_indicators = true + flow_indicators = true + } + + preceded_by_whitespace = true + for i, w := 0, 0; i < len(value); i += w { + w = width(value[i]) + followed_by_whitespace = i+w >= len(value) || is_blank(value, i+w) + + if i == 0 { + switch value[i] { + case '#', ',', '[', ']', '{', '}', '&', '*', '!', '|', '>', '\'', '"', '%', '@', '`': + flow_indicators = true + block_indicators = true + case '?', ':': + flow_indicators = true + if followed_by_whitespace { + block_indicators = true + } + case '-': + if followed_by_whitespace { + flow_indicators = true + block_indicators = true + } + } + } else { + switch value[i] { + case ',', '?', '[', ']', '{', '}': + flow_indicators = true + case ':': + flow_indicators = true + if followed_by_whitespace { + block_indicators = true + } + case '#': + if preceded_by_whitespace { + flow_indicators = true + block_indicators = true + } + } + } + + if !is_printable(value, i) || !is_ascii(value, i) && !emitter.unicode { + special_characters = true + } + if is_space(value, i) { + if i == 0 { + leading_space = true + } + if i+width(value[i]) == len(value) { + trailing_space = true + } + if previous_break { + break_space = true + } + previous_space = true + previous_break = false + } else if is_break(value, i) { + line_breaks = true + if i == 0 { + leading_break = true + } + if i+width(value[i]) == len(value) { + trailing_break = true + } + if previous_space { + space_break = true + } + previous_space = false + previous_break = true + } else { + previous_space = false + previous_break = false + } + + // [Go]: Why 'z'? Couldn't be the end of the string as that's the loop condition. + preceded_by_whitespace = is_blankz(value, i) + } + + emitter.scalar_data.multiline = line_breaks + emitter.scalar_data.flow_plain_allowed = true + emitter.scalar_data.block_plain_allowed = true + emitter.scalar_data.single_quoted_allowed = true + emitter.scalar_data.block_allowed = true + + if leading_space || leading_break || trailing_space || trailing_break { + emitter.scalar_data.flow_plain_allowed = false + emitter.scalar_data.block_plain_allowed = false + } + if trailing_space { + emitter.scalar_data.block_allowed = false + } + if break_space { + emitter.scalar_data.flow_plain_allowed = false + emitter.scalar_data.block_plain_allowed = false + emitter.scalar_data.single_quoted_allowed = false + } + if space_break || special_characters { + emitter.scalar_data.flow_plain_allowed = false + emitter.scalar_data.block_plain_allowed = false + emitter.scalar_data.single_quoted_allowed = false + emitter.scalar_data.block_allowed = false + } + if line_breaks { + emitter.scalar_data.flow_plain_allowed = false + emitter.scalar_data.block_plain_allowed = false + } + if flow_indicators { + emitter.scalar_data.flow_plain_allowed = false + } + if block_indicators { + emitter.scalar_data.block_plain_allowed = false + } + return true +} + +// Check if the event data is valid. +func yaml_emitter_analyze_event(emitter *yaml_emitter_t, event *yaml_event_t) bool { + + emitter.anchor_data.anchor = nil + emitter.tag_data.handle = nil + emitter.tag_data.suffix = nil + emitter.scalar_data.value = nil + + switch event.typ { + case yaml_ALIAS_EVENT: + if !yaml_emitter_analyze_anchor(emitter, event.anchor, true) { + return false + } + + case yaml_SCALAR_EVENT: + if len(event.anchor) > 0 { + if !yaml_emitter_analyze_anchor(emitter, event.anchor, false) { + return false + } + } + if len(event.tag) > 0 && (emitter.canonical || (!event.implicit && !event.quoted_implicit)) { + if !yaml_emitter_analyze_tag(emitter, event.tag) { + return false + } + } + if !yaml_emitter_analyze_scalar(emitter, event.value) { + return false + } + + case yaml_SEQUENCE_START_EVENT: + if len(event.anchor) > 0 { + if !yaml_emitter_analyze_anchor(emitter, event.anchor, false) { + return false + } + } + if len(event.tag) > 0 && (emitter.canonical || !event.implicit) { + if !yaml_emitter_analyze_tag(emitter, event.tag) { + return false + } + } + + case yaml_MAPPING_START_EVENT: + if len(event.anchor) > 0 { + if !yaml_emitter_analyze_anchor(emitter, event.anchor, false) { + return false + } + } + if len(event.tag) > 0 && (emitter.canonical || !event.implicit) { + if !yaml_emitter_analyze_tag(emitter, event.tag) { + return false + } + } + } + return true +} + +// Write the BOM character. +func yaml_emitter_write_bom(emitter *yaml_emitter_t) bool { + if !flush(emitter) { + return false + } + pos := emitter.buffer_pos + emitter.buffer[pos+0] = '\xEF' + emitter.buffer[pos+1] = '\xBB' + emitter.buffer[pos+2] = '\xBF' + emitter.buffer_pos += 3 + return true +} + +func yaml_emitter_write_indent(emitter *yaml_emitter_t) bool { + indent := emitter.indent + if indent < 0 { + indent = 0 + } + if !emitter.indention || emitter.column > indent || (emitter.column == indent && !emitter.whitespace) { + if !put_break(emitter) { + return false + } + } + for emitter.column < indent { + if !put(emitter, ' ') { + return false + } + } + emitter.whitespace = true + emitter.indention = true + return true +} + +func yaml_emitter_write_indicator(emitter *yaml_emitter_t, indicator []byte, need_whitespace, is_whitespace, is_indention bool) bool { + if need_whitespace && !emitter.whitespace { + if !put(emitter, ' ') { + return false + } + } + if !write_all(emitter, indicator) { + return false + } + emitter.whitespace = is_whitespace + emitter.indention = (emitter.indention && is_indention) + emitter.open_ended = false + return true +} + +func yaml_emitter_write_anchor(emitter *yaml_emitter_t, value []byte) bool { + if !write_all(emitter, value) { + return false + } + emitter.whitespace = false + emitter.indention = false + return true +} + +func yaml_emitter_write_tag_handle(emitter *yaml_emitter_t, value []byte) bool { + if !emitter.whitespace { + if !put(emitter, ' ') { + return false + } + } + if !write_all(emitter, value) { + return false + } + emitter.whitespace = false + emitter.indention = false + return true +} + +func yaml_emitter_write_tag_content(emitter *yaml_emitter_t, value []byte, need_whitespace bool) bool { + if need_whitespace && !emitter.whitespace { + if !put(emitter, ' ') { + return false + } + } + for i := 0; i < len(value); { + var must_write bool + switch value[i] { + case ';', '/', '?', ':', '@', '&', '=', '+', '$', ',', '_', '.', '~', '*', '\'', '(', ')', '[', ']': + must_write = true + default: + must_write = is_alpha(value, i) + } + if must_write { + if !write(emitter, value, &i) { + return false + } + } else { + w := width(value[i]) + for k := 0; k < w; k++ { + octet := value[i] + i++ + if !put(emitter, '%') { + return false + } + + c := octet >> 4 + if c < 10 { + c += '0' + } else { + c += 'A' - 10 + } + if !put(emitter, c) { + return false + } + + c = octet & 0x0f + if c < 10 { + c += '0' + } else { + c += 'A' - 10 + } + if !put(emitter, c) { + return false + } + } + } + } + emitter.whitespace = false + emitter.indention = false + return true +} + +func yaml_emitter_write_plain_scalar(emitter *yaml_emitter_t, value []byte, allow_breaks bool) bool { + if !emitter.whitespace { + if !put(emitter, ' ') { + return false + } + } + + spaces := false + breaks := false + for i := 0; i < len(value); { + if is_space(value, i) { + if allow_breaks && !spaces && emitter.column > emitter.best_width && !is_space(value, i+1) { + if !yaml_emitter_write_indent(emitter) { + return false + } + i += width(value[i]) + } else { + if !write(emitter, value, &i) { + return false + } + } + spaces = true + } else if is_break(value, i) { + if !breaks && value[i] == '\n' { + if !put_break(emitter) { + return false + } + } + if !write_break(emitter, value, &i) { + return false + } + emitter.indention = true + breaks = true + } else { + if breaks { + if !yaml_emitter_write_indent(emitter) { + return false + } + } + if !write(emitter, value, &i) { + return false + } + emitter.indention = false + spaces = false + breaks = false + } + } + + emitter.whitespace = false + emitter.indention = false + if emitter.root_context { + emitter.open_ended = true + } + + return true +} + +func yaml_emitter_write_single_quoted_scalar(emitter *yaml_emitter_t, value []byte, allow_breaks bool) bool { + + if !yaml_emitter_write_indicator(emitter, []byte{'\''}, true, false, false) { + return false + } + + spaces := false + breaks := false + for i := 0; i < len(value); { + if is_space(value, i) { + if allow_breaks && !spaces && emitter.column > emitter.best_width && i > 0 && i < len(value)-1 && !is_space(value, i+1) { + if !yaml_emitter_write_indent(emitter) { + return false + } + i += width(value[i]) + } else { + if !write(emitter, value, &i) { + return false + } + } + spaces = true + } else if is_break(value, i) { + if !breaks && value[i] == '\n' { + if !put_break(emitter) { + return false + } + } + if !write_break(emitter, value, &i) { + return false + } + emitter.indention = true + breaks = true + } else { + if breaks { + if !yaml_emitter_write_indent(emitter) { + return false + } + } + if value[i] == '\'' { + if !put(emitter, '\'') { + return false + } + } + if !write(emitter, value, &i) { + return false + } + emitter.indention = false + spaces = false + breaks = false + } + } + if !yaml_emitter_write_indicator(emitter, []byte{'\''}, false, false, false) { + return false + } + emitter.whitespace = false + emitter.indention = false + return true +} + +func yaml_emitter_write_double_quoted_scalar(emitter *yaml_emitter_t, value []byte, allow_breaks bool) bool { + spaces := false + if !yaml_emitter_write_indicator(emitter, []byte{'"'}, true, false, false) { + return false + } + + for i := 0; i < len(value); { + if !is_printable(value, i) || (!emitter.unicode && !is_ascii(value, i)) || + is_bom(value, i) || is_break(value, i) || + value[i] == '"' || value[i] == '\\' { + + octet := value[i] + + var w int + var v rune + switch { + case octet&0x80 == 0x00: + w, v = 1, rune(octet&0x7F) + case octet&0xE0 == 0xC0: + w, v = 2, rune(octet&0x1F) + case octet&0xF0 == 0xE0: + w, v = 3, rune(octet&0x0F) + case octet&0xF8 == 0xF0: + w, v = 4, rune(octet&0x07) + } + for k := 1; k < w; k++ { + octet = value[i+k] + v = (v << 6) + (rune(octet) & 0x3F) + } + i += w + + if !put(emitter, '\\') { + return false + } + + var ok bool + switch v { + case 0x00: + ok = put(emitter, '0') + case 0x07: + ok = put(emitter, 'a') + case 0x08: + ok = put(emitter, 'b') + case 0x09: + ok = put(emitter, 't') + case 0x0A: + ok = put(emitter, 'n') + case 0x0b: + ok = put(emitter, 'v') + case 0x0c: + ok = put(emitter, 'f') + case 0x0d: + ok = put(emitter, 'r') + case 0x1b: + ok = put(emitter, 'e') + case 0x22: + ok = put(emitter, '"') + case 0x5c: + ok = put(emitter, '\\') + case 0x85: + ok = put(emitter, 'N') + case 0xA0: + ok = put(emitter, '_') + case 0x2028: + ok = put(emitter, 'L') + case 0x2029: + ok = put(emitter, 'P') + default: + if v <= 0xFF { + ok = put(emitter, 'x') + w = 2 + } else if v <= 0xFFFF { + ok = put(emitter, 'u') + w = 4 + } else { + ok = put(emitter, 'U') + w = 8 + } + for k := (w - 1) * 4; ok && k >= 0; k -= 4 { + digit := byte((v >> uint(k)) & 0x0F) + if digit < 10 { + ok = put(emitter, digit+'0') + } else { + ok = put(emitter, digit+'A'-10) + } + } + } + if !ok { + return false + } + spaces = false + } else if is_space(value, i) { + if allow_breaks && !spaces && emitter.column > emitter.best_width && i > 0 && i < len(value)-1 { + if !yaml_emitter_write_indent(emitter) { + return false + } + if is_space(value, i+1) { + if !put(emitter, '\\') { + return false + } + } + i += width(value[i]) + } else if !write(emitter, value, &i) { + return false + } + spaces = true + } else { + if !write(emitter, value, &i) { + return false + } + spaces = false + } + } + if !yaml_emitter_write_indicator(emitter, []byte{'"'}, false, false, false) { + return false + } + emitter.whitespace = false + emitter.indention = false + return true +} + +func yaml_emitter_write_block_scalar_hints(emitter *yaml_emitter_t, value []byte) bool { + if is_space(value, 0) || is_break(value, 0) { + indent_hint := []byte{'0' + byte(emitter.best_indent)} + if !yaml_emitter_write_indicator(emitter, indent_hint, false, false, false) { + return false + } + } + + emitter.open_ended = false + + var chomp_hint [1]byte + if len(value) == 0 { + chomp_hint[0] = '-' + } else { + i := len(value) - 1 + for value[i]&0xC0 == 0x80 { + i-- + } + if !is_break(value, i) { + chomp_hint[0] = '-' + } else if i == 0 { + chomp_hint[0] = '+' + emitter.open_ended = true + } else { + i-- + for value[i]&0xC0 == 0x80 { + i-- + } + if is_break(value, i) { + chomp_hint[0] = '+' + emitter.open_ended = true + } + } + } + if chomp_hint[0] != 0 { + if !yaml_emitter_write_indicator(emitter, chomp_hint[:], false, false, false) { + return false + } + } + return true +} + +func yaml_emitter_write_literal_scalar(emitter *yaml_emitter_t, value []byte) bool { + if !yaml_emitter_write_indicator(emitter, []byte{'|'}, true, false, false) { + return false + } + if !yaml_emitter_write_block_scalar_hints(emitter, value) { + return false + } + if !put_break(emitter) { + return false + } + emitter.indention = true + emitter.whitespace = true + breaks := true + for i := 0; i < len(value); { + if is_break(value, i) { + if !write_break(emitter, value, &i) { + return false + } + emitter.indention = true + breaks = true + } else { + if breaks { + if !yaml_emitter_write_indent(emitter) { + return false + } + } + if !write(emitter, value, &i) { + return false + } + emitter.indention = false + breaks = false + } + } + + return true +} + +func yaml_emitter_write_folded_scalar(emitter *yaml_emitter_t, value []byte) bool { + if !yaml_emitter_write_indicator(emitter, []byte{'>'}, true, false, false) { + return false + } + if !yaml_emitter_write_block_scalar_hints(emitter, value) { + return false + } + + if !put_break(emitter) { + return false + } + emitter.indention = true + emitter.whitespace = true + + breaks := true + leading_spaces := true + for i := 0; i < len(value); { + if is_break(value, i) { + if !breaks && !leading_spaces && value[i] == '\n' { + k := 0 + for is_break(value, k) { + k += width(value[k]) + } + if !is_blankz(value, k) { + if !put_break(emitter) { + return false + } + } + } + if !write_break(emitter, value, &i) { + return false + } + emitter.indention = true + breaks = true + } else { + if breaks { + if !yaml_emitter_write_indent(emitter) { + return false + } + leading_spaces = is_blank(value, i) + } + if !breaks && is_space(value, i) && !is_space(value, i+1) && emitter.column > emitter.best_width { + if !yaml_emitter_write_indent(emitter) { + return false + } + i += width(value[i]) + } else { + if !write(emitter, value, &i) { + return false + } + } + emitter.indention = false + breaks = false + } + } + return true +} diff --git a/vendor/github.com/go-yaml/yaml/encode.go b/vendor/github.com/go-yaml/yaml/encode.go new file mode 100644 index 00000000..84f84995 --- /dev/null +++ b/vendor/github.com/go-yaml/yaml/encode.go @@ -0,0 +1,306 @@ +package yaml + +import ( + "encoding" + "fmt" + "reflect" + "regexp" + "sort" + "strconv" + "strings" + "time" +) + +type encoder struct { + emitter yaml_emitter_t + event yaml_event_t + out []byte + flow bool +} + +func newEncoder() (e *encoder) { + e = &encoder{} + e.must(yaml_emitter_initialize(&e.emitter)) + yaml_emitter_set_output_string(&e.emitter, &e.out) + yaml_emitter_set_unicode(&e.emitter, true) + e.must(yaml_stream_start_event_initialize(&e.event, yaml_UTF8_ENCODING)) + e.emit() + e.must(yaml_document_start_event_initialize(&e.event, nil, nil, true)) + e.emit() + return e +} + +func (e *encoder) finish() { + e.must(yaml_document_end_event_initialize(&e.event, true)) + e.emit() + e.emitter.open_ended = false + e.must(yaml_stream_end_event_initialize(&e.event)) + e.emit() +} + +func (e *encoder) destroy() { + yaml_emitter_delete(&e.emitter) +} + +func (e *encoder) emit() { + // This will internally delete the e.event value. + if !yaml_emitter_emit(&e.emitter, &e.event) && e.event.typ != yaml_DOCUMENT_END_EVENT && e.event.typ != yaml_STREAM_END_EVENT { + e.must(false) + } +} + +func (e *encoder) must(ok bool) { + if !ok { + msg := e.emitter.problem + if msg == "" { + msg = "unknown problem generating YAML content" + } + failf("%s", msg) + } +} + +func (e *encoder) marshal(tag string, in reflect.Value) { + if !in.IsValid() { + e.nilv() + return + } + iface := in.Interface() + if m, ok := iface.(Marshaler); ok { + v, err := m.MarshalYAML() + if err != nil { + fail(err) + } + if v == nil { + e.nilv() + return + } + in = reflect.ValueOf(v) + } else if m, ok := iface.(encoding.TextMarshaler); ok { + text, err := m.MarshalText() + if err != nil { + fail(err) + } + in = reflect.ValueOf(string(text)) + } + switch in.Kind() { + case reflect.Interface: + if in.IsNil() { + e.nilv() + } else { + e.marshal(tag, in.Elem()) + } + case reflect.Map: + e.mapv(tag, in) + case reflect.Ptr: + if in.IsNil() { + e.nilv() + } else { + e.marshal(tag, in.Elem()) + } + case reflect.Struct: + e.structv(tag, in) + case reflect.Slice: + if in.Type().Elem() == mapItemType { + e.itemsv(tag, in) + } else { + e.slicev(tag, in) + } + case reflect.String: + e.stringv(tag, in) + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + if in.Type() == durationType { + e.stringv(tag, reflect.ValueOf(iface.(time.Duration).String())) + } else { + e.intv(tag, in) + } + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + e.uintv(tag, in) + case reflect.Float32, reflect.Float64: + e.floatv(tag, in) + case reflect.Bool: + e.boolv(tag, in) + default: + panic("cannot marshal type: " + in.Type().String()) + } +} + +func (e *encoder) mapv(tag string, in reflect.Value) { + e.mappingv(tag, func() { + keys := keyList(in.MapKeys()) + sort.Sort(keys) + for _, k := range keys { + e.marshal("", k) + e.marshal("", in.MapIndex(k)) + } + }) +} + +func (e *encoder) itemsv(tag string, in reflect.Value) { + e.mappingv(tag, func() { + slice := in.Convert(reflect.TypeOf([]MapItem{})).Interface().([]MapItem) + for _, item := range slice { + e.marshal("", reflect.ValueOf(item.Key)) + e.marshal("", reflect.ValueOf(item.Value)) + } + }) +} + +func (e *encoder) structv(tag string, in reflect.Value) { + sinfo, err := getStructInfo(in.Type()) + if err != nil { + panic(err) + } + e.mappingv(tag, func() { + for _, info := range sinfo.FieldsList { + var value reflect.Value + if info.Inline == nil { + value = in.Field(info.Num) + } else { + value = in.FieldByIndex(info.Inline) + } + if info.OmitEmpty && isZero(value) { + continue + } + e.marshal("", reflect.ValueOf(info.Key)) + e.flow = info.Flow + e.marshal("", value) + } + if sinfo.InlineMap >= 0 { + m := in.Field(sinfo.InlineMap) + if m.Len() > 0 { + e.flow = false + keys := keyList(m.MapKeys()) + sort.Sort(keys) + for _, k := range keys { + if _, found := sinfo.FieldsMap[k.String()]; found { + panic(fmt.Sprintf("Can't have key %q in inlined map; conflicts with struct field", k.String())) + } + e.marshal("", k) + e.flow = false + e.marshal("", m.MapIndex(k)) + } + } + } + }) +} + +func (e *encoder) mappingv(tag string, f func()) { + implicit := tag == "" + style := yaml_BLOCK_MAPPING_STYLE + if e.flow { + e.flow = false + style = yaml_FLOW_MAPPING_STYLE + } + e.must(yaml_mapping_start_event_initialize(&e.event, nil, []byte(tag), implicit, style)) + e.emit() + f() + e.must(yaml_mapping_end_event_initialize(&e.event)) + e.emit() +} + +func (e *encoder) slicev(tag string, in reflect.Value) { + implicit := tag == "" + style := yaml_BLOCK_SEQUENCE_STYLE + if e.flow { + e.flow = false + style = yaml_FLOW_SEQUENCE_STYLE + } + e.must(yaml_sequence_start_event_initialize(&e.event, nil, []byte(tag), implicit, style)) + e.emit() + n := in.Len() + for i := 0; i < n; i++ { + e.marshal("", in.Index(i)) + } + e.must(yaml_sequence_end_event_initialize(&e.event)) + e.emit() +} + +// isBase60 returns whether s is in base 60 notation as defined in YAML 1.1. +// +// The base 60 float notation in YAML 1.1 is a terrible idea and is unsupported +// in YAML 1.2 and by this package, but these should be marshalled quoted for +// the time being for compatibility with other parsers. +func isBase60Float(s string) (result bool) { + // Fast path. + if s == "" { + return false + } + c := s[0] + if !(c == '+' || c == '-' || c >= '0' && c <= '9') || strings.IndexByte(s, ':') < 0 { + return false + } + // Do the full match. + return base60float.MatchString(s) +} + +// From http://yaml.org/type/float.html, except the regular expression there +// is bogus. In practice parsers do not enforce the "\.[0-9_]*" suffix. +var base60float = regexp.MustCompile(`^[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+(?:\.[0-9_]*)?$`) + +func (e *encoder) stringv(tag string, in reflect.Value) { + var style yaml_scalar_style_t + s := in.String() + rtag, rs := resolve("", s) + if rtag == yaml_BINARY_TAG { + if tag == "" || tag == yaml_STR_TAG { + tag = rtag + s = rs.(string) + } else if tag == yaml_BINARY_TAG { + failf("explicitly tagged !!binary data must be base64-encoded") + } else { + failf("cannot marshal invalid UTF-8 data as %s", shortTag(tag)) + } + } + if tag == "" && (rtag != yaml_STR_TAG || isBase60Float(s)) { + style = yaml_DOUBLE_QUOTED_SCALAR_STYLE + } else if strings.Contains(s, "\n") { + style = yaml_LITERAL_SCALAR_STYLE + } else { + style = yaml_PLAIN_SCALAR_STYLE + } + e.emitScalar(s, "", tag, style) +} + +func (e *encoder) boolv(tag string, in reflect.Value) { + var s string + if in.Bool() { + s = "true" + } else { + s = "false" + } + e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE) +} + +func (e *encoder) intv(tag string, in reflect.Value) { + s := strconv.FormatInt(in.Int(), 10) + e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE) +} + +func (e *encoder) uintv(tag string, in reflect.Value) { + s := strconv.FormatUint(in.Uint(), 10) + e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE) +} + +func (e *encoder) floatv(tag string, in reflect.Value) { + // FIXME: Handle 64 bits here. + s := strconv.FormatFloat(float64(in.Float()), 'g', -1, 32) + switch s { + case "+Inf": + s = ".inf" + case "-Inf": + s = "-.inf" + case "NaN": + s = ".nan" + } + e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE) +} + +func (e *encoder) nilv() { + e.emitScalar("null", "", "", yaml_PLAIN_SCALAR_STYLE) +} + +func (e *encoder) emitScalar(value, anchor, tag string, style yaml_scalar_style_t) { + implicit := tag == "" + e.must(yaml_scalar_event_initialize(&e.event, []byte(anchor), []byte(tag), []byte(value), implicit, implicit, style)) + e.emit() +} diff --git a/vendor/github.com/go-yaml/yaml/encode_test.go b/vendor/github.com/go-yaml/yaml/encode_test.go new file mode 100644 index 00000000..84099bd3 --- /dev/null +++ b/vendor/github.com/go-yaml/yaml/encode_test.go @@ -0,0 +1,501 @@ +package yaml_test + +import ( + "fmt" + "math" + "strconv" + "strings" + "time" + + . "gopkg.in/check.v1" + "gopkg.in/yaml.v2" + "net" + "os" +) + +var marshalIntTest = 123 + +var marshalTests = []struct { + value interface{} + data string +}{ + { + nil, + "null\n", + }, { + &struct{}{}, + "{}\n", + }, { + map[string]string{"v": "hi"}, + "v: hi\n", + }, { + map[string]interface{}{"v": "hi"}, + "v: hi\n", + }, { + map[string]string{"v": "true"}, + "v: \"true\"\n", + }, { + map[string]string{"v": "false"}, + "v: \"false\"\n", + }, { + map[string]interface{}{"v": true}, + "v: true\n", + }, { + map[string]interface{}{"v": false}, + "v: false\n", + }, { + map[string]interface{}{"v": 10}, + "v: 10\n", + }, { + map[string]interface{}{"v": -10}, + "v: -10\n", + }, { + map[string]uint{"v": 42}, + "v: 42\n", + }, { + map[string]interface{}{"v": int64(4294967296)}, + "v: 4294967296\n", + }, { + map[string]int64{"v": int64(4294967296)}, + "v: 4294967296\n", + }, { + map[string]uint64{"v": 4294967296}, + "v: 4294967296\n", + }, { + map[string]interface{}{"v": "10"}, + "v: \"10\"\n", + }, { + map[string]interface{}{"v": 0.1}, + "v: 0.1\n", + }, { + map[string]interface{}{"v": float64(0.1)}, + "v: 0.1\n", + }, { + map[string]interface{}{"v": -0.1}, + "v: -0.1\n", + }, { + map[string]interface{}{"v": math.Inf(+1)}, + "v: .inf\n", + }, { + map[string]interface{}{"v": math.Inf(-1)}, + "v: -.inf\n", + }, { + map[string]interface{}{"v": math.NaN()}, + "v: .nan\n", + }, { + map[string]interface{}{"v": nil}, + "v: null\n", + }, { + map[string]interface{}{"v": ""}, + "v: \"\"\n", + }, { + map[string][]string{"v": []string{"A", "B"}}, + "v:\n- A\n- B\n", + }, { + map[string][]string{"v": []string{"A", "B\nC"}}, + "v:\n- A\n- |-\n B\n C\n", + }, { + map[string][]interface{}{"v": []interface{}{"A", 1, map[string][]int{"B": []int{2, 3}}}}, + "v:\n- A\n- 1\n- B:\n - 2\n - 3\n", + }, { + map[string]interface{}{"a": map[interface{}]interface{}{"b": "c"}}, + "a:\n b: c\n", + }, { + map[string]interface{}{"a": "-"}, + "a: '-'\n", + }, + + // Simple values. + { + &marshalIntTest, + "123\n", + }, + + // Structures + { + &struct{ Hello string }{"world"}, + "hello: world\n", + }, { + &struct { + A struct { + B string + } + }{struct{ B string }{"c"}}, + "a:\n b: c\n", + }, { + &struct { + A *struct { + B string + } + }{&struct{ B string }{"c"}}, + "a:\n b: c\n", + }, { + &struct { + A *struct { + B string + } + }{}, + "a: null\n", + }, { + &struct{ A int }{1}, + "a: 1\n", + }, { + &struct{ A []int }{[]int{1, 2}}, + "a:\n- 1\n- 2\n", + }, { + &struct { + B int "a" + }{1}, + "a: 1\n", + }, { + &struct{ A bool }{true}, + "a: true\n", + }, + + // Conditional flag + { + &struct { + A int "a,omitempty" + B int "b,omitempty" + }{1, 0}, + "a: 1\n", + }, { + &struct { + A int "a,omitempty" + B int "b,omitempty" + }{0, 0}, + "{}\n", + }, { + &struct { + A *struct{ X, y int } "a,omitempty,flow" + }{&struct{ X, y int }{1, 2}}, + "a: {x: 1}\n", + }, { + &struct { + A *struct{ X, y int } "a,omitempty,flow" + }{nil}, + "{}\n", + }, { + &struct { + A *struct{ X, y int } "a,omitempty,flow" + }{&struct{ X, y int }{}}, + "a: {x: 0}\n", + }, { + &struct { + A struct{ X, y int } "a,omitempty,flow" + }{struct{ X, y int }{1, 2}}, + "a: {x: 1}\n", + }, { + &struct { + A struct{ X, y int } "a,omitempty,flow" + }{struct{ X, y int }{0, 1}}, + "{}\n", + }, { + &struct { + A float64 "a,omitempty" + B float64 "b,omitempty" + }{1, 0}, + "a: 1\n", + }, + + // Flow flag + { + &struct { + A []int "a,flow" + }{[]int{1, 2}}, + "a: [1, 2]\n", + }, { + &struct { + A map[string]string "a,flow" + }{map[string]string{"b": "c", "d": "e"}}, + "a: {b: c, d: e}\n", + }, { + &struct { + A struct { + B, D string + } "a,flow" + }{struct{ B, D string }{"c", "e"}}, + "a: {b: c, d: e}\n", + }, + + // Unexported field + { + &struct { + u int + A int + }{0, 1}, + "a: 1\n", + }, + + // Ignored field + { + &struct { + A int + B int "-" + }{1, 2}, + "a: 1\n", + }, + + // Struct inlining + { + &struct { + A int + C inlineB `yaml:",inline"` + }{1, inlineB{2, inlineC{3}}}, + "a: 1\nb: 2\nc: 3\n", + }, + + // Map inlining + { + &struct { + A int + C map[string]int `yaml:",inline"` + }{1, map[string]int{"b": 2, "c": 3}}, + "a: 1\nb: 2\nc: 3\n", + }, + + // Duration + { + map[string]time.Duration{"a": 3 * time.Second}, + "a: 3s\n", + }, + + // Issue #24: bug in map merging logic. + { + map[string]string{"a": ""}, + "a: \n", + }, + + // Issue #34: marshal unsupported base 60 floats quoted for compatibility + // with old YAML 1.1 parsers. + { + map[string]string{"a": "1:1"}, + "a: \"1:1\"\n", + }, + + // Binary data. + { + map[string]string{"a": "\x00"}, + "a: \"\\0\"\n", + }, { + map[string]string{"a": "\x80\x81\x82"}, + "a: !!binary gIGC\n", + }, { + map[string]string{"a": strings.Repeat("\x90", 54)}, + "a: !!binary |\n " + strings.Repeat("kJCQ", 17) + "kJ\n CQ\n", + }, + + // Ordered maps. + { + &yaml.MapSlice{{"b", 2}, {"a", 1}, {"d", 4}, {"c", 3}, {"sub", yaml.MapSlice{{"e", 5}}}}, + "b: 2\na: 1\nd: 4\nc: 3\nsub:\n e: 5\n", + }, + + // Encode unicode as utf-8 rather than in escaped form. + { + map[string]string{"a": "你好"}, + "a: 你好\n", + }, + + // Support encoding.TextMarshaler. + { + map[string]net.IP{"a": net.IPv4(1, 2, 3, 4)}, + "a: 1.2.3.4\n", + }, + { + map[string]time.Time{"a": time.Unix(1424801979, 0)}, + "a: 2015-02-24T18:19:39Z\n", + }, + + // Ensure strings containing ": " are quoted (reported as PR #43, but not reproducible). + { + map[string]string{"a": "b: c"}, + "a: 'b: c'\n", + }, + + // Containing hash mark ('#') in string should be quoted + { + map[string]string{"a": "Hello #comment"}, + "a: 'Hello #comment'\n", + }, + { + map[string]string{"a": "你好 #comment"}, + "a: '你好 #comment'\n", + }, +} + +func (s *S) TestMarshal(c *C) { + defer os.Setenv("TZ", os.Getenv("TZ")) + os.Setenv("TZ", "UTC") + for _, item := range marshalTests { + data, err := yaml.Marshal(item.value) + c.Assert(err, IsNil) + c.Assert(string(data), Equals, item.data) + } +} + +var marshalErrorTests = []struct { + value interface{} + error string + panic string +}{{ + value: &struct { + B int + inlineB ",inline" + }{1, inlineB{2, inlineC{3}}}, + panic: `Duplicated key 'b' in struct struct \{ B int; .*`, +}, { + value: &struct { + A int + B map[string]int ",inline" + }{1, map[string]int{"a": 2}}, + panic: `Can't have key "a" in inlined map; conflicts with struct field`, +}} + +func (s *S) TestMarshalErrors(c *C) { + for _, item := range marshalErrorTests { + if item.panic != "" { + c.Assert(func() { yaml.Marshal(item.value) }, PanicMatches, item.panic) + } else { + _, err := yaml.Marshal(item.value) + c.Assert(err, ErrorMatches, item.error) + } + } +} + +func (s *S) TestMarshalTypeCache(c *C) { + var data []byte + var err error + func() { + type T struct{ A int } + data, err = yaml.Marshal(&T{}) + c.Assert(err, IsNil) + }() + func() { + type T struct{ B int } + data, err = yaml.Marshal(&T{}) + c.Assert(err, IsNil) + }() + c.Assert(string(data), Equals, "b: 0\n") +} + +var marshalerTests = []struct { + data string + value interface{} +}{ + {"_:\n hi: there\n", map[interface{}]interface{}{"hi": "there"}}, + {"_:\n- 1\n- A\n", []interface{}{1, "A"}}, + {"_: 10\n", 10}, + {"_: null\n", nil}, + {"_: BAR!\n", "BAR!"}, +} + +type marshalerType struct { + value interface{} +} + +func (o marshalerType) MarshalText() ([]byte, error) { + panic("MarshalText called on type with MarshalYAML") +} + +func (o marshalerType) MarshalYAML() (interface{}, error) { + return o.value, nil +} + +type marshalerValue struct { + Field marshalerType "_" +} + +func (s *S) TestMarshaler(c *C) { + for _, item := range marshalerTests { + obj := &marshalerValue{} + obj.Field.value = item.value + data, err := yaml.Marshal(obj) + c.Assert(err, IsNil) + c.Assert(string(data), Equals, string(item.data)) + } +} + +func (s *S) TestMarshalerWholeDocument(c *C) { + obj := &marshalerType{} + obj.value = map[string]string{"hello": "world!"} + data, err := yaml.Marshal(obj) + c.Assert(err, IsNil) + c.Assert(string(data), Equals, "hello: world!\n") +} + +type failingMarshaler struct{} + +func (ft *failingMarshaler) MarshalYAML() (interface{}, error) { + return nil, failingErr +} + +func (s *S) TestMarshalerError(c *C) { + _, err := yaml.Marshal(&failingMarshaler{}) + c.Assert(err, Equals, failingErr) +} + +func (s *S) TestSortedOutput(c *C) { + order := []interface{}{ + false, + true, + 1, + uint(1), + 1.0, + 1.1, + 1.2, + 2, + uint(2), + 2.0, + 2.1, + "", + ".1", + ".2", + ".a", + "1", + "2", + "a!10", + "a/2", + "a/10", + "a~10", + "ab/1", + "b/1", + "b/01", + "b/2", + "b/02", + "b/3", + "b/03", + "b1", + "b01", + "b3", + "c2.10", + "c10.2", + "d1", + "d12", + "d12a", + } + m := make(map[interface{}]int) + for _, k := range order { + m[k] = 1 + } + data, err := yaml.Marshal(m) + c.Assert(err, IsNil) + out := "\n" + string(data) + last := 0 + for i, k := range order { + repr := fmt.Sprint(k) + if s, ok := k.(string); ok { + if _, err = strconv.ParseFloat(repr, 32); s == "" || err == nil { + repr = `"` + repr + `"` + } + } + index := strings.Index(out, "\n"+repr+":") + if index == -1 { + c.Fatalf("%#v is not in the output: %#v", k, out) + } + if index < last { + c.Fatalf("%#v was generated before %#v: %q", k, order[i-1], out) + } + last = index + } +} diff --git a/vendor/github.com/go-yaml/yaml/example_embedded_test.go b/vendor/github.com/go-yaml/yaml/example_embedded_test.go new file mode 100644 index 00000000..171c0931 --- /dev/null +++ b/vendor/github.com/go-yaml/yaml/example_embedded_test.go @@ -0,0 +1,41 @@ +package yaml_test + +import ( + "fmt" + "log" + + "gopkg.in/yaml.v2" +) + +// An example showing how to unmarshal embedded +// structs from YAML. + +type StructA struct { + A string `yaml:"a"` +} + +type StructB struct { + // Embedded structs are not treated as embedded in YAML by default. To do that, + // add the ",inline" annotation below + StructA `yaml:",inline"` + B string `yaml:"b"` +} + +var data = ` +a: a string from struct A +b: a string from struct B +` + +func ExampleUnmarshal_embedded() { + var b StructB + + err := yaml.Unmarshal([]byte(data), &b) + if err != nil { + log.Fatalf("cannot unmarshal data: %v", err) + } + fmt.Println(b.A) + fmt.Println(b.B) + // Output: + // a string from struct A + // a string from struct B +} diff --git a/vendor/github.com/go-yaml/yaml/parserc.go b/vendor/github.com/go-yaml/yaml/parserc.go new file mode 100644 index 00000000..81d05dfe --- /dev/null +++ b/vendor/github.com/go-yaml/yaml/parserc.go @@ -0,0 +1,1095 @@ +package yaml + +import ( + "bytes" +) + +// The parser implements the following grammar: +// +// stream ::= STREAM-START implicit_document? explicit_document* STREAM-END +// implicit_document ::= block_node DOCUMENT-END* +// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* +// block_node_or_indentless_sequence ::= +// ALIAS +// | properties (block_content | indentless_block_sequence)? +// | block_content +// | indentless_block_sequence +// block_node ::= ALIAS +// | properties block_content? +// | block_content +// flow_node ::= ALIAS +// | properties flow_content? +// | flow_content +// properties ::= TAG ANCHOR? | ANCHOR TAG? +// block_content ::= block_collection | flow_collection | SCALAR +// flow_content ::= flow_collection | SCALAR +// block_collection ::= block_sequence | block_mapping +// flow_collection ::= flow_sequence | flow_mapping +// block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END +// indentless_sequence ::= (BLOCK-ENTRY block_node?)+ +// block_mapping ::= BLOCK-MAPPING_START +// ((KEY block_node_or_indentless_sequence?)? +// (VALUE block_node_or_indentless_sequence?)?)* +// BLOCK-END +// flow_sequence ::= FLOW-SEQUENCE-START +// (flow_sequence_entry FLOW-ENTRY)* +// flow_sequence_entry? +// FLOW-SEQUENCE-END +// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? +// flow_mapping ::= FLOW-MAPPING-START +// (flow_mapping_entry FLOW-ENTRY)* +// flow_mapping_entry? +// FLOW-MAPPING-END +// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? + +// Peek the next token in the token queue. +func peek_token(parser *yaml_parser_t) *yaml_token_t { + if parser.token_available || yaml_parser_fetch_more_tokens(parser) { + return &parser.tokens[parser.tokens_head] + } + return nil +} + +// Remove the next token from the queue (must be called after peek_token). +func skip_token(parser *yaml_parser_t) { + parser.token_available = false + parser.tokens_parsed++ + parser.stream_end_produced = parser.tokens[parser.tokens_head].typ == yaml_STREAM_END_TOKEN + parser.tokens_head++ +} + +// Get the next event. +func yaml_parser_parse(parser *yaml_parser_t, event *yaml_event_t) bool { + // Erase the event object. + *event = yaml_event_t{} + + // No events after the end of the stream or error. + if parser.stream_end_produced || parser.error != yaml_NO_ERROR || parser.state == yaml_PARSE_END_STATE { + return true + } + + // Generate the next event. + return yaml_parser_state_machine(parser, event) +} + +// Set parser error. +func yaml_parser_set_parser_error(parser *yaml_parser_t, problem string, problem_mark yaml_mark_t) bool { + parser.error = yaml_PARSER_ERROR + parser.problem = problem + parser.problem_mark = problem_mark + return false +} + +func yaml_parser_set_parser_error_context(parser *yaml_parser_t, context string, context_mark yaml_mark_t, problem string, problem_mark yaml_mark_t) bool { + parser.error = yaml_PARSER_ERROR + parser.context = context + parser.context_mark = context_mark + parser.problem = problem + parser.problem_mark = problem_mark + return false +} + +// State dispatcher. +func yaml_parser_state_machine(parser *yaml_parser_t, event *yaml_event_t) bool { + //trace("yaml_parser_state_machine", "state:", parser.state.String()) + + switch parser.state { + case yaml_PARSE_STREAM_START_STATE: + return yaml_parser_parse_stream_start(parser, event) + + case yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE: + return yaml_parser_parse_document_start(parser, event, true) + + case yaml_PARSE_DOCUMENT_START_STATE: + return yaml_parser_parse_document_start(parser, event, false) + + case yaml_PARSE_DOCUMENT_CONTENT_STATE: + return yaml_parser_parse_document_content(parser, event) + + case yaml_PARSE_DOCUMENT_END_STATE: + return yaml_parser_parse_document_end(parser, event) + + case yaml_PARSE_BLOCK_NODE_STATE: + return yaml_parser_parse_node(parser, event, true, false) + + case yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE: + return yaml_parser_parse_node(parser, event, true, true) + + case yaml_PARSE_FLOW_NODE_STATE: + return yaml_parser_parse_node(parser, event, false, false) + + case yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE: + return yaml_parser_parse_block_sequence_entry(parser, event, true) + + case yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE: + return yaml_parser_parse_block_sequence_entry(parser, event, false) + + case yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE: + return yaml_parser_parse_indentless_sequence_entry(parser, event) + + case yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE: + return yaml_parser_parse_block_mapping_key(parser, event, true) + + case yaml_PARSE_BLOCK_MAPPING_KEY_STATE: + return yaml_parser_parse_block_mapping_key(parser, event, false) + + case yaml_PARSE_BLOCK_MAPPING_VALUE_STATE: + return yaml_parser_parse_block_mapping_value(parser, event) + + case yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE: + return yaml_parser_parse_flow_sequence_entry(parser, event, true) + + case yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE: + return yaml_parser_parse_flow_sequence_entry(parser, event, false) + + case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE: + return yaml_parser_parse_flow_sequence_entry_mapping_key(parser, event) + + case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE: + return yaml_parser_parse_flow_sequence_entry_mapping_value(parser, event) + + case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE: + return yaml_parser_parse_flow_sequence_entry_mapping_end(parser, event) + + case yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE: + return yaml_parser_parse_flow_mapping_key(parser, event, true) + + case yaml_PARSE_FLOW_MAPPING_KEY_STATE: + return yaml_parser_parse_flow_mapping_key(parser, event, false) + + case yaml_PARSE_FLOW_MAPPING_VALUE_STATE: + return yaml_parser_parse_flow_mapping_value(parser, event, false) + + case yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE: + return yaml_parser_parse_flow_mapping_value(parser, event, true) + + default: + panic("invalid parser state") + } +} + +// Parse the production: +// stream ::= STREAM-START implicit_document? explicit_document* STREAM-END +// ************ +func yaml_parser_parse_stream_start(parser *yaml_parser_t, event *yaml_event_t) bool { + token := peek_token(parser) + if token == nil { + return false + } + if token.typ != yaml_STREAM_START_TOKEN { + return yaml_parser_set_parser_error(parser, "did not find expected ", token.start_mark) + } + parser.state = yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE + *event = yaml_event_t{ + typ: yaml_STREAM_START_EVENT, + start_mark: token.start_mark, + end_mark: token.end_mark, + encoding: token.encoding, + } + skip_token(parser) + return true +} + +// Parse the productions: +// implicit_document ::= block_node DOCUMENT-END* +// * +// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* +// ************************* +func yaml_parser_parse_document_start(parser *yaml_parser_t, event *yaml_event_t, implicit bool) bool { + + token := peek_token(parser) + if token == nil { + return false + } + + // Parse extra document end indicators. + if !implicit { + for token.typ == yaml_DOCUMENT_END_TOKEN { + skip_token(parser) + token = peek_token(parser) + if token == nil { + return false + } + } + } + + if implicit && token.typ != yaml_VERSION_DIRECTIVE_TOKEN && + token.typ != yaml_TAG_DIRECTIVE_TOKEN && + token.typ != yaml_DOCUMENT_START_TOKEN && + token.typ != yaml_STREAM_END_TOKEN { + // Parse an implicit document. + if !yaml_parser_process_directives(parser, nil, nil) { + return false + } + parser.states = append(parser.states, yaml_PARSE_DOCUMENT_END_STATE) + parser.state = yaml_PARSE_BLOCK_NODE_STATE + + *event = yaml_event_t{ + typ: yaml_DOCUMENT_START_EVENT, + start_mark: token.start_mark, + end_mark: token.end_mark, + } + + } else if token.typ != yaml_STREAM_END_TOKEN { + // Parse an explicit document. + var version_directive *yaml_version_directive_t + var tag_directives []yaml_tag_directive_t + start_mark := token.start_mark + if !yaml_parser_process_directives(parser, &version_directive, &tag_directives) { + return false + } + token = peek_token(parser) + if token == nil { + return false + } + if token.typ != yaml_DOCUMENT_START_TOKEN { + yaml_parser_set_parser_error(parser, + "did not find expected ", token.start_mark) + return false + } + parser.states = append(parser.states, yaml_PARSE_DOCUMENT_END_STATE) + parser.state = yaml_PARSE_DOCUMENT_CONTENT_STATE + end_mark := token.end_mark + + *event = yaml_event_t{ + typ: yaml_DOCUMENT_START_EVENT, + start_mark: start_mark, + end_mark: end_mark, + version_directive: version_directive, + tag_directives: tag_directives, + implicit: false, + } + skip_token(parser) + + } else { + // Parse the stream end. + parser.state = yaml_PARSE_END_STATE + *event = yaml_event_t{ + typ: yaml_STREAM_END_EVENT, + start_mark: token.start_mark, + end_mark: token.end_mark, + } + skip_token(parser) + } + + return true +} + +// Parse the productions: +// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* +// *********** +// +func yaml_parser_parse_document_content(parser *yaml_parser_t, event *yaml_event_t) bool { + token := peek_token(parser) + if token == nil { + return false + } + if token.typ == yaml_VERSION_DIRECTIVE_TOKEN || + token.typ == yaml_TAG_DIRECTIVE_TOKEN || + token.typ == yaml_DOCUMENT_START_TOKEN || + token.typ == yaml_DOCUMENT_END_TOKEN || + token.typ == yaml_STREAM_END_TOKEN { + parser.state = parser.states[len(parser.states)-1] + parser.states = parser.states[:len(parser.states)-1] + return yaml_parser_process_empty_scalar(parser, event, + token.start_mark) + } + return yaml_parser_parse_node(parser, event, true, false) +} + +// Parse the productions: +// implicit_document ::= block_node DOCUMENT-END* +// ************* +// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* +// +func yaml_parser_parse_document_end(parser *yaml_parser_t, event *yaml_event_t) bool { + token := peek_token(parser) + if token == nil { + return false + } + + start_mark := token.start_mark + end_mark := token.start_mark + + implicit := true + if token.typ == yaml_DOCUMENT_END_TOKEN { + end_mark = token.end_mark + skip_token(parser) + implicit = false + } + + parser.tag_directives = parser.tag_directives[:0] + + parser.state = yaml_PARSE_DOCUMENT_START_STATE + *event = yaml_event_t{ + typ: yaml_DOCUMENT_END_EVENT, + start_mark: start_mark, + end_mark: end_mark, + implicit: implicit, + } + return true +} + +// Parse the productions: +// block_node_or_indentless_sequence ::= +// ALIAS +// ***** +// | properties (block_content | indentless_block_sequence)? +// ********** * +// | block_content | indentless_block_sequence +// * +// block_node ::= ALIAS +// ***** +// | properties block_content? +// ********** * +// | block_content +// * +// flow_node ::= ALIAS +// ***** +// | properties flow_content? +// ********** * +// | flow_content +// * +// properties ::= TAG ANCHOR? | ANCHOR TAG? +// ************************* +// block_content ::= block_collection | flow_collection | SCALAR +// ****** +// flow_content ::= flow_collection | SCALAR +// ****** +func yaml_parser_parse_node(parser *yaml_parser_t, event *yaml_event_t, block, indentless_sequence bool) bool { + //defer trace("yaml_parser_parse_node", "block:", block, "indentless_sequence:", indentless_sequence)() + + token := peek_token(parser) + if token == nil { + return false + } + + if token.typ == yaml_ALIAS_TOKEN { + parser.state = parser.states[len(parser.states)-1] + parser.states = parser.states[:len(parser.states)-1] + *event = yaml_event_t{ + typ: yaml_ALIAS_EVENT, + start_mark: token.start_mark, + end_mark: token.end_mark, + anchor: token.value, + } + skip_token(parser) + return true + } + + start_mark := token.start_mark + end_mark := token.start_mark + + var tag_token bool + var tag_handle, tag_suffix, anchor []byte + var tag_mark yaml_mark_t + if token.typ == yaml_ANCHOR_TOKEN { + anchor = token.value + start_mark = token.start_mark + end_mark = token.end_mark + skip_token(parser) + token = peek_token(parser) + if token == nil { + return false + } + if token.typ == yaml_TAG_TOKEN { + tag_token = true + tag_handle = token.value + tag_suffix = token.suffix + tag_mark = token.start_mark + end_mark = token.end_mark + skip_token(parser) + token = peek_token(parser) + if token == nil { + return false + } + } + } else if token.typ == yaml_TAG_TOKEN { + tag_token = true + tag_handle = token.value + tag_suffix = token.suffix + start_mark = token.start_mark + tag_mark = token.start_mark + end_mark = token.end_mark + skip_token(parser) + token = peek_token(parser) + if token == nil { + return false + } + if token.typ == yaml_ANCHOR_TOKEN { + anchor = token.value + end_mark = token.end_mark + skip_token(parser) + token = peek_token(parser) + if token == nil { + return false + } + } + } + + var tag []byte + if tag_token { + if len(tag_handle) == 0 { + tag = tag_suffix + tag_suffix = nil + } else { + for i := range parser.tag_directives { + if bytes.Equal(parser.tag_directives[i].handle, tag_handle) { + tag = append([]byte(nil), parser.tag_directives[i].prefix...) + tag = append(tag, tag_suffix...) + break + } + } + if len(tag) == 0 { + yaml_parser_set_parser_error_context(parser, + "while parsing a node", start_mark, + "found undefined tag handle", tag_mark) + return false + } + } + } + + implicit := len(tag) == 0 + if indentless_sequence && token.typ == yaml_BLOCK_ENTRY_TOKEN { + end_mark = token.end_mark + parser.state = yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE + *event = yaml_event_t{ + typ: yaml_SEQUENCE_START_EVENT, + start_mark: start_mark, + end_mark: end_mark, + anchor: anchor, + tag: tag, + implicit: implicit, + style: yaml_style_t(yaml_BLOCK_SEQUENCE_STYLE), + } + return true + } + if token.typ == yaml_SCALAR_TOKEN { + var plain_implicit, quoted_implicit bool + end_mark = token.end_mark + if (len(tag) == 0 && token.style == yaml_PLAIN_SCALAR_STYLE) || (len(tag) == 1 && tag[0] == '!') { + plain_implicit = true + } else if len(tag) == 0 { + quoted_implicit = true + } + parser.state = parser.states[len(parser.states)-1] + parser.states = parser.states[:len(parser.states)-1] + + *event = yaml_event_t{ + typ: yaml_SCALAR_EVENT, + start_mark: start_mark, + end_mark: end_mark, + anchor: anchor, + tag: tag, + value: token.value, + implicit: plain_implicit, + quoted_implicit: quoted_implicit, + style: yaml_style_t(token.style), + } + skip_token(parser) + return true + } + if token.typ == yaml_FLOW_SEQUENCE_START_TOKEN { + // [Go] Some of the events below can be merged as they differ only on style. + end_mark = token.end_mark + parser.state = yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE + *event = yaml_event_t{ + typ: yaml_SEQUENCE_START_EVENT, + start_mark: start_mark, + end_mark: end_mark, + anchor: anchor, + tag: tag, + implicit: implicit, + style: yaml_style_t(yaml_FLOW_SEQUENCE_STYLE), + } + return true + } + if token.typ == yaml_FLOW_MAPPING_START_TOKEN { + end_mark = token.end_mark + parser.state = yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE + *event = yaml_event_t{ + typ: yaml_MAPPING_START_EVENT, + start_mark: start_mark, + end_mark: end_mark, + anchor: anchor, + tag: tag, + implicit: implicit, + style: yaml_style_t(yaml_FLOW_MAPPING_STYLE), + } + return true + } + if block && token.typ == yaml_BLOCK_SEQUENCE_START_TOKEN { + end_mark = token.end_mark + parser.state = yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE + *event = yaml_event_t{ + typ: yaml_SEQUENCE_START_EVENT, + start_mark: start_mark, + end_mark: end_mark, + anchor: anchor, + tag: tag, + implicit: implicit, + style: yaml_style_t(yaml_BLOCK_SEQUENCE_STYLE), + } + return true + } + if block && token.typ == yaml_BLOCK_MAPPING_START_TOKEN { + end_mark = token.end_mark + parser.state = yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE + *event = yaml_event_t{ + typ: yaml_MAPPING_START_EVENT, + start_mark: start_mark, + end_mark: end_mark, + anchor: anchor, + tag: tag, + implicit: implicit, + style: yaml_style_t(yaml_BLOCK_MAPPING_STYLE), + } + return true + } + if len(anchor) > 0 || len(tag) > 0 { + parser.state = parser.states[len(parser.states)-1] + parser.states = parser.states[:len(parser.states)-1] + + *event = yaml_event_t{ + typ: yaml_SCALAR_EVENT, + start_mark: start_mark, + end_mark: end_mark, + anchor: anchor, + tag: tag, + implicit: implicit, + quoted_implicit: false, + style: yaml_style_t(yaml_PLAIN_SCALAR_STYLE), + } + return true + } + + context := "while parsing a flow node" + if block { + context = "while parsing a block node" + } + yaml_parser_set_parser_error_context(parser, context, start_mark, + "did not find expected node content", token.start_mark) + return false +} + +// Parse the productions: +// block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END +// ******************** *********** * ********* +// +func yaml_parser_parse_block_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool { + if first { + token := peek_token(parser) + parser.marks = append(parser.marks, token.start_mark) + skip_token(parser) + } + + token := peek_token(parser) + if token == nil { + return false + } + + if token.typ == yaml_BLOCK_ENTRY_TOKEN { + mark := token.end_mark + skip_token(parser) + token = peek_token(parser) + if token == nil { + return false + } + if token.typ != yaml_BLOCK_ENTRY_TOKEN && token.typ != yaml_BLOCK_END_TOKEN { + parser.states = append(parser.states, yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE) + return yaml_parser_parse_node(parser, event, true, false) + } else { + parser.state = yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE + return yaml_parser_process_empty_scalar(parser, event, mark) + } + } + if token.typ == yaml_BLOCK_END_TOKEN { + parser.state = parser.states[len(parser.states)-1] + parser.states = parser.states[:len(parser.states)-1] + parser.marks = parser.marks[:len(parser.marks)-1] + + *event = yaml_event_t{ + typ: yaml_SEQUENCE_END_EVENT, + start_mark: token.start_mark, + end_mark: token.end_mark, + } + + skip_token(parser) + return true + } + + context_mark := parser.marks[len(parser.marks)-1] + parser.marks = parser.marks[:len(parser.marks)-1] + return yaml_parser_set_parser_error_context(parser, + "while parsing a block collection", context_mark, + "did not find expected '-' indicator", token.start_mark) +} + +// Parse the productions: +// indentless_sequence ::= (BLOCK-ENTRY block_node?)+ +// *********** * +func yaml_parser_parse_indentless_sequence_entry(parser *yaml_parser_t, event *yaml_event_t) bool { + token := peek_token(parser) + if token == nil { + return false + } + + if token.typ == yaml_BLOCK_ENTRY_TOKEN { + mark := token.end_mark + skip_token(parser) + token = peek_token(parser) + if token == nil { + return false + } + if token.typ != yaml_BLOCK_ENTRY_TOKEN && + token.typ != yaml_KEY_TOKEN && + token.typ != yaml_VALUE_TOKEN && + token.typ != yaml_BLOCK_END_TOKEN { + parser.states = append(parser.states, yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE) + return yaml_parser_parse_node(parser, event, true, false) + } + parser.state = yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE + return yaml_parser_process_empty_scalar(parser, event, mark) + } + parser.state = parser.states[len(parser.states)-1] + parser.states = parser.states[:len(parser.states)-1] + + *event = yaml_event_t{ + typ: yaml_SEQUENCE_END_EVENT, + start_mark: token.start_mark, + end_mark: token.start_mark, // [Go] Shouldn't this be token.end_mark? + } + return true +} + +// Parse the productions: +// block_mapping ::= BLOCK-MAPPING_START +// ******************* +// ((KEY block_node_or_indentless_sequence?)? +// *** * +// (VALUE block_node_or_indentless_sequence?)?)* +// +// BLOCK-END +// ********* +// +func yaml_parser_parse_block_mapping_key(parser *yaml_parser_t, event *yaml_event_t, first bool) bool { + if first { + token := peek_token(parser) + parser.marks = append(parser.marks, token.start_mark) + skip_token(parser) + } + + token := peek_token(parser) + if token == nil { + return false + } + + if token.typ == yaml_KEY_TOKEN { + mark := token.end_mark + skip_token(parser) + token = peek_token(parser) + if token == nil { + return false + } + if token.typ != yaml_KEY_TOKEN && + token.typ != yaml_VALUE_TOKEN && + token.typ != yaml_BLOCK_END_TOKEN { + parser.states = append(parser.states, yaml_PARSE_BLOCK_MAPPING_VALUE_STATE) + return yaml_parser_parse_node(parser, event, true, true) + } else { + parser.state = yaml_PARSE_BLOCK_MAPPING_VALUE_STATE + return yaml_parser_process_empty_scalar(parser, event, mark) + } + } else if token.typ == yaml_BLOCK_END_TOKEN { + parser.state = parser.states[len(parser.states)-1] + parser.states = parser.states[:len(parser.states)-1] + parser.marks = parser.marks[:len(parser.marks)-1] + *event = yaml_event_t{ + typ: yaml_MAPPING_END_EVENT, + start_mark: token.start_mark, + end_mark: token.end_mark, + } + skip_token(parser) + return true + } + + context_mark := parser.marks[len(parser.marks)-1] + parser.marks = parser.marks[:len(parser.marks)-1] + return yaml_parser_set_parser_error_context(parser, + "while parsing a block mapping", context_mark, + "did not find expected key", token.start_mark) +} + +// Parse the productions: +// block_mapping ::= BLOCK-MAPPING_START +// +// ((KEY block_node_or_indentless_sequence?)? +// +// (VALUE block_node_or_indentless_sequence?)?)* +// ***** * +// BLOCK-END +// +// +func yaml_parser_parse_block_mapping_value(parser *yaml_parser_t, event *yaml_event_t) bool { + token := peek_token(parser) + if token == nil { + return false + } + if token.typ == yaml_VALUE_TOKEN { + mark := token.end_mark + skip_token(parser) + token = peek_token(parser) + if token == nil { + return false + } + if token.typ != yaml_KEY_TOKEN && + token.typ != yaml_VALUE_TOKEN && + token.typ != yaml_BLOCK_END_TOKEN { + parser.states = append(parser.states, yaml_PARSE_BLOCK_MAPPING_KEY_STATE) + return yaml_parser_parse_node(parser, event, true, true) + } + parser.state = yaml_PARSE_BLOCK_MAPPING_KEY_STATE + return yaml_parser_process_empty_scalar(parser, event, mark) + } + parser.state = yaml_PARSE_BLOCK_MAPPING_KEY_STATE + return yaml_parser_process_empty_scalar(parser, event, token.start_mark) +} + +// Parse the productions: +// flow_sequence ::= FLOW-SEQUENCE-START +// ******************* +// (flow_sequence_entry FLOW-ENTRY)* +// * ********** +// flow_sequence_entry? +// * +// FLOW-SEQUENCE-END +// ***************** +// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? +// * +// +func yaml_parser_parse_flow_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool { + if first { + token := peek_token(parser) + parser.marks = append(parser.marks, token.start_mark) + skip_token(parser) + } + token := peek_token(parser) + if token == nil { + return false + } + if token.typ != yaml_FLOW_SEQUENCE_END_TOKEN { + if !first { + if token.typ == yaml_FLOW_ENTRY_TOKEN { + skip_token(parser) + token = peek_token(parser) + if token == nil { + return false + } + } else { + context_mark := parser.marks[len(parser.marks)-1] + parser.marks = parser.marks[:len(parser.marks)-1] + return yaml_parser_set_parser_error_context(parser, + "while parsing a flow sequence", context_mark, + "did not find expected ',' or ']'", token.start_mark) + } + } + + if token.typ == yaml_KEY_TOKEN { + parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE + *event = yaml_event_t{ + typ: yaml_MAPPING_START_EVENT, + start_mark: token.start_mark, + end_mark: token.end_mark, + implicit: true, + style: yaml_style_t(yaml_FLOW_MAPPING_STYLE), + } + skip_token(parser) + return true + } else if token.typ != yaml_FLOW_SEQUENCE_END_TOKEN { + parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE) + return yaml_parser_parse_node(parser, event, false, false) + } + } + + parser.state = parser.states[len(parser.states)-1] + parser.states = parser.states[:len(parser.states)-1] + parser.marks = parser.marks[:len(parser.marks)-1] + + *event = yaml_event_t{ + typ: yaml_SEQUENCE_END_EVENT, + start_mark: token.start_mark, + end_mark: token.end_mark, + } + + skip_token(parser) + return true +} + +// +// Parse the productions: +// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? +// *** * +// +func yaml_parser_parse_flow_sequence_entry_mapping_key(parser *yaml_parser_t, event *yaml_event_t) bool { + token := peek_token(parser) + if token == nil { + return false + } + if token.typ != yaml_VALUE_TOKEN && + token.typ != yaml_FLOW_ENTRY_TOKEN && + token.typ != yaml_FLOW_SEQUENCE_END_TOKEN { + parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE) + return yaml_parser_parse_node(parser, event, false, false) + } + mark := token.end_mark + skip_token(parser) + parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE + return yaml_parser_process_empty_scalar(parser, event, mark) +} + +// Parse the productions: +// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? +// ***** * +// +func yaml_parser_parse_flow_sequence_entry_mapping_value(parser *yaml_parser_t, event *yaml_event_t) bool { + token := peek_token(parser) + if token == nil { + return false + } + if token.typ == yaml_VALUE_TOKEN { + skip_token(parser) + token := peek_token(parser) + if token == nil { + return false + } + if token.typ != yaml_FLOW_ENTRY_TOKEN && token.typ != yaml_FLOW_SEQUENCE_END_TOKEN { + parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE) + return yaml_parser_parse_node(parser, event, false, false) + } + } + parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE + return yaml_parser_process_empty_scalar(parser, event, token.start_mark) +} + +// Parse the productions: +// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? +// * +// +func yaml_parser_parse_flow_sequence_entry_mapping_end(parser *yaml_parser_t, event *yaml_event_t) bool { + token := peek_token(parser) + if token == nil { + return false + } + parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE + *event = yaml_event_t{ + typ: yaml_MAPPING_END_EVENT, + start_mark: token.start_mark, + end_mark: token.start_mark, // [Go] Shouldn't this be end_mark? + } + return true +} + +// Parse the productions: +// flow_mapping ::= FLOW-MAPPING-START +// ****************** +// (flow_mapping_entry FLOW-ENTRY)* +// * ********** +// flow_mapping_entry? +// ****************** +// FLOW-MAPPING-END +// **************** +// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? +// * *** * +// +func yaml_parser_parse_flow_mapping_key(parser *yaml_parser_t, event *yaml_event_t, first bool) bool { + if first { + token := peek_token(parser) + parser.marks = append(parser.marks, token.start_mark) + skip_token(parser) + } + + token := peek_token(parser) + if token == nil { + return false + } + + if token.typ != yaml_FLOW_MAPPING_END_TOKEN { + if !first { + if token.typ == yaml_FLOW_ENTRY_TOKEN { + skip_token(parser) + token = peek_token(parser) + if token == nil { + return false + } + } else { + context_mark := parser.marks[len(parser.marks)-1] + parser.marks = parser.marks[:len(parser.marks)-1] + return yaml_parser_set_parser_error_context(parser, + "while parsing a flow mapping", context_mark, + "did not find expected ',' or '}'", token.start_mark) + } + } + + if token.typ == yaml_KEY_TOKEN { + skip_token(parser) + token = peek_token(parser) + if token == nil { + return false + } + if token.typ != yaml_VALUE_TOKEN && + token.typ != yaml_FLOW_ENTRY_TOKEN && + token.typ != yaml_FLOW_MAPPING_END_TOKEN { + parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_VALUE_STATE) + return yaml_parser_parse_node(parser, event, false, false) + } else { + parser.state = yaml_PARSE_FLOW_MAPPING_VALUE_STATE + return yaml_parser_process_empty_scalar(parser, event, token.start_mark) + } + } else if token.typ != yaml_FLOW_MAPPING_END_TOKEN { + parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE) + return yaml_parser_parse_node(parser, event, false, false) + } + } + + parser.state = parser.states[len(parser.states)-1] + parser.states = parser.states[:len(parser.states)-1] + parser.marks = parser.marks[:len(parser.marks)-1] + *event = yaml_event_t{ + typ: yaml_MAPPING_END_EVENT, + start_mark: token.start_mark, + end_mark: token.end_mark, + } + skip_token(parser) + return true +} + +// Parse the productions: +// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? +// * ***** * +// +func yaml_parser_parse_flow_mapping_value(parser *yaml_parser_t, event *yaml_event_t, empty bool) bool { + token := peek_token(parser) + if token == nil { + return false + } + if empty { + parser.state = yaml_PARSE_FLOW_MAPPING_KEY_STATE + return yaml_parser_process_empty_scalar(parser, event, token.start_mark) + } + if token.typ == yaml_VALUE_TOKEN { + skip_token(parser) + token = peek_token(parser) + if token == nil { + return false + } + if token.typ != yaml_FLOW_ENTRY_TOKEN && token.typ != yaml_FLOW_MAPPING_END_TOKEN { + parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_KEY_STATE) + return yaml_parser_parse_node(parser, event, false, false) + } + } + parser.state = yaml_PARSE_FLOW_MAPPING_KEY_STATE + return yaml_parser_process_empty_scalar(parser, event, token.start_mark) +} + +// Generate an empty scalar event. +func yaml_parser_process_empty_scalar(parser *yaml_parser_t, event *yaml_event_t, mark yaml_mark_t) bool { + *event = yaml_event_t{ + typ: yaml_SCALAR_EVENT, + start_mark: mark, + end_mark: mark, + value: nil, // Empty + implicit: true, + style: yaml_style_t(yaml_PLAIN_SCALAR_STYLE), + } + return true +} + +var default_tag_directives = []yaml_tag_directive_t{ + {[]byte("!"), []byte("!")}, + {[]byte("!!"), []byte("tag:yaml.org,2002:")}, +} + +// Parse directives. +func yaml_parser_process_directives(parser *yaml_parser_t, + version_directive_ref **yaml_version_directive_t, + tag_directives_ref *[]yaml_tag_directive_t) bool { + + var version_directive *yaml_version_directive_t + var tag_directives []yaml_tag_directive_t + + token := peek_token(parser) + if token == nil { + return false + } + + for token.typ == yaml_VERSION_DIRECTIVE_TOKEN || token.typ == yaml_TAG_DIRECTIVE_TOKEN { + if token.typ == yaml_VERSION_DIRECTIVE_TOKEN { + if version_directive != nil { + yaml_parser_set_parser_error(parser, + "found duplicate %YAML directive", token.start_mark) + return false + } + if token.major != 1 || token.minor != 1 { + yaml_parser_set_parser_error(parser, + "found incompatible YAML document", token.start_mark) + return false + } + version_directive = &yaml_version_directive_t{ + major: token.major, + minor: token.minor, + } + } else if token.typ == yaml_TAG_DIRECTIVE_TOKEN { + value := yaml_tag_directive_t{ + handle: token.value, + prefix: token.prefix, + } + if !yaml_parser_append_tag_directive(parser, value, false, token.start_mark) { + return false + } + tag_directives = append(tag_directives, value) + } + + skip_token(parser) + token = peek_token(parser) + if token == nil { + return false + } + } + + for i := range default_tag_directives { + if !yaml_parser_append_tag_directive(parser, default_tag_directives[i], true, token.start_mark) { + return false + } + } + + if version_directive_ref != nil { + *version_directive_ref = version_directive + } + if tag_directives_ref != nil { + *tag_directives_ref = tag_directives + } + return true +} + +// Append a tag directive to the directives stack. +func yaml_parser_append_tag_directive(parser *yaml_parser_t, value yaml_tag_directive_t, allow_duplicates bool, mark yaml_mark_t) bool { + for i := range parser.tag_directives { + if bytes.Equal(value.handle, parser.tag_directives[i].handle) { + if allow_duplicates { + return true + } + return yaml_parser_set_parser_error(parser, "found duplicate %TAG directive", mark) + } + } + + // [Go] I suspect the copy is unnecessary. This was likely done + // because there was no way to track ownership of the data. + value_copy := yaml_tag_directive_t{ + handle: make([]byte, len(value.handle)), + prefix: make([]byte, len(value.prefix)), + } + copy(value_copy.handle, value.handle) + copy(value_copy.prefix, value.prefix) + parser.tag_directives = append(parser.tag_directives, value_copy) + return true +} diff --git a/vendor/github.com/go-yaml/yaml/readerc.go b/vendor/github.com/go-yaml/yaml/readerc.go new file mode 100644 index 00000000..f4507917 --- /dev/null +++ b/vendor/github.com/go-yaml/yaml/readerc.go @@ -0,0 +1,394 @@ +package yaml + +import ( + "io" +) + +// Set the reader error and return 0. +func yaml_parser_set_reader_error(parser *yaml_parser_t, problem string, offset int, value int) bool { + parser.error = yaml_READER_ERROR + parser.problem = problem + parser.problem_offset = offset + parser.problem_value = value + return false +} + +// Byte order marks. +const ( + bom_UTF8 = "\xef\xbb\xbf" + bom_UTF16LE = "\xff\xfe" + bom_UTF16BE = "\xfe\xff" +) + +// Determine the input stream encoding by checking the BOM symbol. If no BOM is +// found, the UTF-8 encoding is assumed. Return 1 on success, 0 on failure. +func yaml_parser_determine_encoding(parser *yaml_parser_t) bool { + // Ensure that we had enough bytes in the raw buffer. + for !parser.eof && len(parser.raw_buffer)-parser.raw_buffer_pos < 3 { + if !yaml_parser_update_raw_buffer(parser) { + return false + } + } + + // Determine the encoding. + buf := parser.raw_buffer + pos := parser.raw_buffer_pos + avail := len(buf) - pos + if avail >= 2 && buf[pos] == bom_UTF16LE[0] && buf[pos+1] == bom_UTF16LE[1] { + parser.encoding = yaml_UTF16LE_ENCODING + parser.raw_buffer_pos += 2 + parser.offset += 2 + } else if avail >= 2 && buf[pos] == bom_UTF16BE[0] && buf[pos+1] == bom_UTF16BE[1] { + parser.encoding = yaml_UTF16BE_ENCODING + parser.raw_buffer_pos += 2 + parser.offset += 2 + } else if avail >= 3 && buf[pos] == bom_UTF8[0] && buf[pos+1] == bom_UTF8[1] && buf[pos+2] == bom_UTF8[2] { + parser.encoding = yaml_UTF8_ENCODING + parser.raw_buffer_pos += 3 + parser.offset += 3 + } else { + parser.encoding = yaml_UTF8_ENCODING + } + return true +} + +// Update the raw buffer. +func yaml_parser_update_raw_buffer(parser *yaml_parser_t) bool { + size_read := 0 + + // Return if the raw buffer is full. + if parser.raw_buffer_pos == 0 && len(parser.raw_buffer) == cap(parser.raw_buffer) { + return true + } + + // Return on EOF. + if parser.eof { + return true + } + + // Move the remaining bytes in the raw buffer to the beginning. + if parser.raw_buffer_pos > 0 && parser.raw_buffer_pos < len(parser.raw_buffer) { + copy(parser.raw_buffer, parser.raw_buffer[parser.raw_buffer_pos:]) + } + parser.raw_buffer = parser.raw_buffer[:len(parser.raw_buffer)-parser.raw_buffer_pos] + parser.raw_buffer_pos = 0 + + // Call the read handler to fill the buffer. + size_read, err := parser.read_handler(parser, parser.raw_buffer[len(parser.raw_buffer):cap(parser.raw_buffer)]) + parser.raw_buffer = parser.raw_buffer[:len(parser.raw_buffer)+size_read] + if err == io.EOF { + parser.eof = true + } else if err != nil { + return yaml_parser_set_reader_error(parser, "input error: "+err.Error(), parser.offset, -1) + } + return true +} + +// Ensure that the buffer contains at least `length` characters. +// Return true on success, false on failure. +// +// The length is supposed to be significantly less that the buffer size. +func yaml_parser_update_buffer(parser *yaml_parser_t, length int) bool { + if parser.read_handler == nil { + panic("read handler must be set") + } + + // If the EOF flag is set and the raw buffer is empty, do nothing. + if parser.eof && parser.raw_buffer_pos == len(parser.raw_buffer) { + return true + } + + // Return if the buffer contains enough characters. + if parser.unread >= length { + return true + } + + // Determine the input encoding if it is not known yet. + if parser.encoding == yaml_ANY_ENCODING { + if !yaml_parser_determine_encoding(parser) { + return false + } + } + + // Move the unread characters to the beginning of the buffer. + buffer_len := len(parser.buffer) + if parser.buffer_pos > 0 && parser.buffer_pos < buffer_len { + copy(parser.buffer, parser.buffer[parser.buffer_pos:]) + buffer_len -= parser.buffer_pos + parser.buffer_pos = 0 + } else if parser.buffer_pos == buffer_len { + buffer_len = 0 + parser.buffer_pos = 0 + } + + // Open the whole buffer for writing, and cut it before returning. + parser.buffer = parser.buffer[:cap(parser.buffer)] + + // Fill the buffer until it has enough characters. + first := true + for parser.unread < length { + + // Fill the raw buffer if necessary. + if !first || parser.raw_buffer_pos == len(parser.raw_buffer) { + if !yaml_parser_update_raw_buffer(parser) { + parser.buffer = parser.buffer[:buffer_len] + return false + } + } + first = false + + // Decode the raw buffer. + inner: + for parser.raw_buffer_pos != len(parser.raw_buffer) { + var value rune + var width int + + raw_unread := len(parser.raw_buffer) - parser.raw_buffer_pos + + // Decode the next character. + switch parser.encoding { + case yaml_UTF8_ENCODING: + // Decode a UTF-8 character. Check RFC 3629 + // (http://www.ietf.org/rfc/rfc3629.txt) for more details. + // + // The following table (taken from the RFC) is used for + // decoding. + // + // Char. number range | UTF-8 octet sequence + // (hexadecimal) | (binary) + // --------------------+------------------------------------ + // 0000 0000-0000 007F | 0xxxxxxx + // 0000 0080-0000 07FF | 110xxxxx 10xxxxxx + // 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx + // 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + // + // Additionally, the characters in the range 0xD800-0xDFFF + // are prohibited as they are reserved for use with UTF-16 + // surrogate pairs. + + // Determine the length of the UTF-8 sequence. + octet := parser.raw_buffer[parser.raw_buffer_pos] + switch { + case octet&0x80 == 0x00: + width = 1 + case octet&0xE0 == 0xC0: + width = 2 + case octet&0xF0 == 0xE0: + width = 3 + case octet&0xF8 == 0xF0: + width = 4 + default: + // The leading octet is invalid. + return yaml_parser_set_reader_error(parser, + "invalid leading UTF-8 octet", + parser.offset, int(octet)) + } + + // Check if the raw buffer contains an incomplete character. + if width > raw_unread { + if parser.eof { + return yaml_parser_set_reader_error(parser, + "incomplete UTF-8 octet sequence", + parser.offset, -1) + } + break inner + } + + // Decode the leading octet. + switch { + case octet&0x80 == 0x00: + value = rune(octet & 0x7F) + case octet&0xE0 == 0xC0: + value = rune(octet & 0x1F) + case octet&0xF0 == 0xE0: + value = rune(octet & 0x0F) + case octet&0xF8 == 0xF0: + value = rune(octet & 0x07) + default: + value = 0 + } + + // Check and decode the trailing octets. + for k := 1; k < width; k++ { + octet = parser.raw_buffer[parser.raw_buffer_pos+k] + + // Check if the octet is valid. + if (octet & 0xC0) != 0x80 { + return yaml_parser_set_reader_error(parser, + "invalid trailing UTF-8 octet", + parser.offset+k, int(octet)) + } + + // Decode the octet. + value = (value << 6) + rune(octet&0x3F) + } + + // Check the length of the sequence against the value. + switch { + case width == 1: + case width == 2 && value >= 0x80: + case width == 3 && value >= 0x800: + case width == 4 && value >= 0x10000: + default: + return yaml_parser_set_reader_error(parser, + "invalid length of a UTF-8 sequence", + parser.offset, -1) + } + + // Check the range of the value. + if value >= 0xD800 && value <= 0xDFFF || value > 0x10FFFF { + return yaml_parser_set_reader_error(parser, + "invalid Unicode character", + parser.offset, int(value)) + } + + case yaml_UTF16LE_ENCODING, yaml_UTF16BE_ENCODING: + var low, high int + if parser.encoding == yaml_UTF16LE_ENCODING { + low, high = 0, 1 + } else { + low, high = 1, 0 + } + + // The UTF-16 encoding is not as simple as one might + // naively think. Check RFC 2781 + // (http://www.ietf.org/rfc/rfc2781.txt). + // + // Normally, two subsequent bytes describe a Unicode + // character. However a special technique (called a + // surrogate pair) is used for specifying character + // values larger than 0xFFFF. + // + // A surrogate pair consists of two pseudo-characters: + // high surrogate area (0xD800-0xDBFF) + // low surrogate area (0xDC00-0xDFFF) + // + // The following formulas are used for decoding + // and encoding characters using surrogate pairs: + // + // U = U' + 0x10000 (0x01 00 00 <= U <= 0x10 FF FF) + // U' = yyyyyyyyyyxxxxxxxxxx (0 <= U' <= 0x0F FF FF) + // W1 = 110110yyyyyyyyyy + // W2 = 110111xxxxxxxxxx + // + // where U is the character value, W1 is the high surrogate + // area, W2 is the low surrogate area. + + // Check for incomplete UTF-16 character. + if raw_unread < 2 { + if parser.eof { + return yaml_parser_set_reader_error(parser, + "incomplete UTF-16 character", + parser.offset, -1) + } + break inner + } + + // Get the character. + value = rune(parser.raw_buffer[parser.raw_buffer_pos+low]) + + (rune(parser.raw_buffer[parser.raw_buffer_pos+high]) << 8) + + // Check for unexpected low surrogate area. + if value&0xFC00 == 0xDC00 { + return yaml_parser_set_reader_error(parser, + "unexpected low surrogate area", + parser.offset, int(value)) + } + + // Check for a high surrogate area. + if value&0xFC00 == 0xD800 { + width = 4 + + // Check for incomplete surrogate pair. + if raw_unread < 4 { + if parser.eof { + return yaml_parser_set_reader_error(parser, + "incomplete UTF-16 surrogate pair", + parser.offset, -1) + } + break inner + } + + // Get the next character. + value2 := rune(parser.raw_buffer[parser.raw_buffer_pos+low+2]) + + (rune(parser.raw_buffer[parser.raw_buffer_pos+high+2]) << 8) + + // Check for a low surrogate area. + if value2&0xFC00 != 0xDC00 { + return yaml_parser_set_reader_error(parser, + "expected low surrogate area", + parser.offset+2, int(value2)) + } + + // Generate the value of the surrogate pair. + value = 0x10000 + ((value & 0x3FF) << 10) + (value2 & 0x3FF) + } else { + width = 2 + } + + default: + panic("impossible") + } + + // Check if the character is in the allowed range: + // #x9 | #xA | #xD | [#x20-#x7E] (8 bit) + // | #x85 | [#xA0-#xD7FF] | [#xE000-#xFFFD] (16 bit) + // | [#x10000-#x10FFFF] (32 bit) + switch { + case value == 0x09: + case value == 0x0A: + case value == 0x0D: + case value >= 0x20 && value <= 0x7E: + case value == 0x85: + case value >= 0xA0 && value <= 0xD7FF: + case value >= 0xE000 && value <= 0xFFFD: + case value >= 0x10000 && value <= 0x10FFFF: + default: + return yaml_parser_set_reader_error(parser, + "control characters are not allowed", + parser.offset, int(value)) + } + + // Move the raw pointers. + parser.raw_buffer_pos += width + parser.offset += width + + // Finally put the character into the buffer. + if value <= 0x7F { + // 0000 0000-0000 007F . 0xxxxxxx + parser.buffer[buffer_len+0] = byte(value) + buffer_len += 1 + } else if value <= 0x7FF { + // 0000 0080-0000 07FF . 110xxxxx 10xxxxxx + parser.buffer[buffer_len+0] = byte(0xC0 + (value >> 6)) + parser.buffer[buffer_len+1] = byte(0x80 + (value & 0x3F)) + buffer_len += 2 + } else if value <= 0xFFFF { + // 0000 0800-0000 FFFF . 1110xxxx 10xxxxxx 10xxxxxx + parser.buffer[buffer_len+0] = byte(0xE0 + (value >> 12)) + parser.buffer[buffer_len+1] = byte(0x80 + ((value >> 6) & 0x3F)) + parser.buffer[buffer_len+2] = byte(0x80 + (value & 0x3F)) + buffer_len += 3 + } else { + // 0001 0000-0010 FFFF . 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + parser.buffer[buffer_len+0] = byte(0xF0 + (value >> 18)) + parser.buffer[buffer_len+1] = byte(0x80 + ((value >> 12) & 0x3F)) + parser.buffer[buffer_len+2] = byte(0x80 + ((value >> 6) & 0x3F)) + parser.buffer[buffer_len+3] = byte(0x80 + (value & 0x3F)) + buffer_len += 4 + } + + parser.unread++ + } + + // On EOF, put NUL into the buffer and return. + if parser.eof { + parser.buffer[buffer_len] = 0 + buffer_len++ + parser.unread++ + break + } + } + parser.buffer = parser.buffer[:buffer_len] + return true +} diff --git a/vendor/github.com/go-yaml/yaml/resolve.go b/vendor/github.com/go-yaml/yaml/resolve.go new file mode 100644 index 00000000..232313cc --- /dev/null +++ b/vendor/github.com/go-yaml/yaml/resolve.go @@ -0,0 +1,208 @@ +package yaml + +import ( + "encoding/base64" + "math" + "regexp" + "strconv" + "strings" + "unicode/utf8" +) + +type resolveMapItem struct { + value interface{} + tag string +} + +var resolveTable = make([]byte, 256) +var resolveMap = make(map[string]resolveMapItem) + +func init() { + t := resolveTable + t[int('+')] = 'S' // Sign + t[int('-')] = 'S' + for _, c := range "0123456789" { + t[int(c)] = 'D' // Digit + } + for _, c := range "yYnNtTfFoO~" { + t[int(c)] = 'M' // In map + } + t[int('.')] = '.' // Float (potentially in map) + + var resolveMapList = []struct { + v interface{} + tag string + l []string + }{ + {true, yaml_BOOL_TAG, []string{"y", "Y", "yes", "Yes", "YES"}}, + {true, yaml_BOOL_TAG, []string{"true", "True", "TRUE"}}, + {true, yaml_BOOL_TAG, []string{"on", "On", "ON"}}, + {false, yaml_BOOL_TAG, []string{"n", "N", "no", "No", "NO"}}, + {false, yaml_BOOL_TAG, []string{"false", "False", "FALSE"}}, + {false, yaml_BOOL_TAG, []string{"off", "Off", "OFF"}}, + {nil, yaml_NULL_TAG, []string{"", "~", "null", "Null", "NULL"}}, + {math.NaN(), yaml_FLOAT_TAG, []string{".nan", ".NaN", ".NAN"}}, + {math.Inf(+1), yaml_FLOAT_TAG, []string{".inf", ".Inf", ".INF"}}, + {math.Inf(+1), yaml_FLOAT_TAG, []string{"+.inf", "+.Inf", "+.INF"}}, + {math.Inf(-1), yaml_FLOAT_TAG, []string{"-.inf", "-.Inf", "-.INF"}}, + {"<<", yaml_MERGE_TAG, []string{"<<"}}, + } + + m := resolveMap + for _, item := range resolveMapList { + for _, s := range item.l { + m[s] = resolveMapItem{item.v, item.tag} + } + } +} + +const longTagPrefix = "tag:yaml.org,2002:" + +func shortTag(tag string) string { + // TODO This can easily be made faster and produce less garbage. + if strings.HasPrefix(tag, longTagPrefix) { + return "!!" + tag[len(longTagPrefix):] + } + return tag +} + +func longTag(tag string) string { + if strings.HasPrefix(tag, "!!") { + return longTagPrefix + tag[2:] + } + return tag +} + +func resolvableTag(tag string) bool { + switch tag { + case "", yaml_STR_TAG, yaml_BOOL_TAG, yaml_INT_TAG, yaml_FLOAT_TAG, yaml_NULL_TAG: + return true + } + return false +} + +var yamlStyleFloat = regexp.MustCompile(`^[-+]?[0-9]*\.?[0-9]+([eE][-+][0-9]+)?$`) + +func resolve(tag string, in string) (rtag string, out interface{}) { + if !resolvableTag(tag) { + return tag, in + } + + defer func() { + switch tag { + case "", rtag, yaml_STR_TAG, yaml_BINARY_TAG: + return + } + failf("cannot decode %s `%s` as a %s", shortTag(rtag), in, shortTag(tag)) + }() + + // Any data is accepted as a !!str or !!binary. + // Otherwise, the prefix is enough of a hint about what it might be. + hint := byte('N') + if in != "" { + hint = resolveTable[in[0]] + } + if hint != 0 && tag != yaml_STR_TAG && tag != yaml_BINARY_TAG { + // Handle things we can lookup in a map. + if item, ok := resolveMap[in]; ok { + return item.tag, item.value + } + + // Base 60 floats are a bad idea, were dropped in YAML 1.2, and + // are purposefully unsupported here. They're still quoted on + // the way out for compatibility with other parser, though. + + switch hint { + case 'M': + // We've already checked the map above. + + case '.': + // Not in the map, so maybe a normal float. + floatv, err := strconv.ParseFloat(in, 64) + if err == nil { + return yaml_FLOAT_TAG, floatv + } + + case 'D', 'S': + // Int, float, or timestamp. + plain := strings.Replace(in, "_", "", -1) + intv, err := strconv.ParseInt(plain, 0, 64) + if err == nil { + if intv == int64(int(intv)) { + return yaml_INT_TAG, int(intv) + } else { + return yaml_INT_TAG, intv + } + } + uintv, err := strconv.ParseUint(plain, 0, 64) + if err == nil { + return yaml_INT_TAG, uintv + } + if yamlStyleFloat.MatchString(plain) { + floatv, err := strconv.ParseFloat(plain, 64) + if err == nil { + return yaml_FLOAT_TAG, floatv + } + } + if strings.HasPrefix(plain, "0b") { + intv, err := strconv.ParseInt(plain[2:], 2, 64) + if err == nil { + if intv == int64(int(intv)) { + return yaml_INT_TAG, int(intv) + } else { + return yaml_INT_TAG, intv + } + } + uintv, err := strconv.ParseUint(plain[2:], 2, 64) + if err == nil { + return yaml_INT_TAG, uintv + } + } else if strings.HasPrefix(plain, "-0b") { + intv, err := strconv.ParseInt(plain[3:], 2, 64) + if err == nil { + if intv == int64(int(intv)) { + return yaml_INT_TAG, -int(intv) + } else { + return yaml_INT_TAG, -intv + } + } + } + // XXX Handle timestamps here. + + default: + panic("resolveTable item not yet handled: " + string(rune(hint)) + " (with " + in + ")") + } + } + if tag == yaml_BINARY_TAG { + return yaml_BINARY_TAG, in + } + if utf8.ValidString(in) { + return yaml_STR_TAG, in + } + return yaml_BINARY_TAG, encodeBase64(in) +} + +// encodeBase64 encodes s as base64 that is broken up into multiple lines +// as appropriate for the resulting length. +func encodeBase64(s string) string { + const lineLen = 70 + encLen := base64.StdEncoding.EncodedLen(len(s)) + lines := encLen/lineLen + 1 + buf := make([]byte, encLen*2+lines) + in := buf[0:encLen] + out := buf[encLen:] + base64.StdEncoding.Encode(in, []byte(s)) + k := 0 + for i := 0; i < len(in); i += lineLen { + j := i + lineLen + if j > len(in) { + j = len(in) + } + k += copy(out[k:], in[i:j]) + if lines > 1 { + out[k] = '\n' + k++ + } + } + return string(out[:k]) +} diff --git a/vendor/github.com/go-yaml/yaml/scannerc.go b/vendor/github.com/go-yaml/yaml/scannerc.go new file mode 100644 index 00000000..07448445 --- /dev/null +++ b/vendor/github.com/go-yaml/yaml/scannerc.go @@ -0,0 +1,2711 @@ +package yaml + +import ( + "bytes" + "fmt" +) + +// Introduction +// ************ +// +// The following notes assume that you are familiar with the YAML specification +// (http://yaml.org/spec/1.2/spec.html). We mostly follow it, although in +// some cases we are less restrictive that it requires. +// +// The process of transforming a YAML stream into a sequence of events is +// divided on two steps: Scanning and Parsing. +// +// The Scanner transforms the input stream into a sequence of tokens, while the +// parser transform the sequence of tokens produced by the Scanner into a +// sequence of parsing events. +// +// The Scanner is rather clever and complicated. The Parser, on the contrary, +// is a straightforward implementation of a recursive-descendant parser (or, +// LL(1) parser, as it is usually called). +// +// Actually there are two issues of Scanning that might be called "clever", the +// rest is quite straightforward. The issues are "block collection start" and +// "simple keys". Both issues are explained below in details. +// +// Here the Scanning step is explained and implemented. We start with the list +// of all the tokens produced by the Scanner together with short descriptions. +// +// Now, tokens: +// +// STREAM-START(encoding) # The stream start. +// STREAM-END # The stream end. +// VERSION-DIRECTIVE(major,minor) # The '%YAML' directive. +// TAG-DIRECTIVE(handle,prefix) # The '%TAG' directive. +// DOCUMENT-START # '---' +// DOCUMENT-END # '...' +// BLOCK-SEQUENCE-START # Indentation increase denoting a block +// BLOCK-MAPPING-START # sequence or a block mapping. +// BLOCK-END # Indentation decrease. +// FLOW-SEQUENCE-START # '[' +// FLOW-SEQUENCE-END # ']' +// BLOCK-SEQUENCE-START # '{' +// BLOCK-SEQUENCE-END # '}' +// BLOCK-ENTRY # '-' +// FLOW-ENTRY # ',' +// KEY # '?' or nothing (simple keys). +// VALUE # ':' +// ALIAS(anchor) # '*anchor' +// ANCHOR(anchor) # '&anchor' +// TAG(handle,suffix) # '!handle!suffix' +// SCALAR(value,style) # A scalar. +// +// The following two tokens are "virtual" tokens denoting the beginning and the +// end of the stream: +// +// STREAM-START(encoding) +// STREAM-END +// +// We pass the information about the input stream encoding with the +// STREAM-START token. +// +// The next two tokens are responsible for tags: +// +// VERSION-DIRECTIVE(major,minor) +// TAG-DIRECTIVE(handle,prefix) +// +// Example: +// +// %YAML 1.1 +// %TAG ! !foo +// %TAG !yaml! tag:yaml.org,2002: +// --- +// +// The correspoding sequence of tokens: +// +// STREAM-START(utf-8) +// VERSION-DIRECTIVE(1,1) +// TAG-DIRECTIVE("!","!foo") +// TAG-DIRECTIVE("!yaml","tag:yaml.org,2002:") +// DOCUMENT-START +// STREAM-END +// +// Note that the VERSION-DIRECTIVE and TAG-DIRECTIVE tokens occupy a whole +// line. +// +// The document start and end indicators are represented by: +// +// DOCUMENT-START +// DOCUMENT-END +// +// Note that if a YAML stream contains an implicit document (without '---' +// and '...' indicators), no DOCUMENT-START and DOCUMENT-END tokens will be +// produced. +// +// In the following examples, we present whole documents together with the +// produced tokens. +// +// 1. An implicit document: +// +// 'a scalar' +// +// Tokens: +// +// STREAM-START(utf-8) +// SCALAR("a scalar",single-quoted) +// STREAM-END +// +// 2. An explicit document: +// +// --- +// 'a scalar' +// ... +// +// Tokens: +// +// STREAM-START(utf-8) +// DOCUMENT-START +// SCALAR("a scalar",single-quoted) +// DOCUMENT-END +// STREAM-END +// +// 3. Several documents in a stream: +// +// 'a scalar' +// --- +// 'another scalar' +// --- +// 'yet another scalar' +// +// Tokens: +// +// STREAM-START(utf-8) +// SCALAR("a scalar",single-quoted) +// DOCUMENT-START +// SCALAR("another scalar",single-quoted) +// DOCUMENT-START +// SCALAR("yet another scalar",single-quoted) +// STREAM-END +// +// We have already introduced the SCALAR token above. The following tokens are +// used to describe aliases, anchors, tag, and scalars: +// +// ALIAS(anchor) +// ANCHOR(anchor) +// TAG(handle,suffix) +// SCALAR(value,style) +// +// The following series of examples illustrate the usage of these tokens: +// +// 1. A recursive sequence: +// +// &A [ *A ] +// +// Tokens: +// +// STREAM-START(utf-8) +// ANCHOR("A") +// FLOW-SEQUENCE-START +// ALIAS("A") +// FLOW-SEQUENCE-END +// STREAM-END +// +// 2. A tagged scalar: +// +// !!float "3.14" # A good approximation. +// +// Tokens: +// +// STREAM-START(utf-8) +// TAG("!!","float") +// SCALAR("3.14",double-quoted) +// STREAM-END +// +// 3. Various scalar styles: +// +// --- # Implicit empty plain scalars do not produce tokens. +// --- a plain scalar +// --- 'a single-quoted scalar' +// --- "a double-quoted scalar" +// --- |- +// a literal scalar +// --- >- +// a folded +// scalar +// +// Tokens: +// +// STREAM-START(utf-8) +// DOCUMENT-START +// DOCUMENT-START +// SCALAR("a plain scalar",plain) +// DOCUMENT-START +// SCALAR("a single-quoted scalar",single-quoted) +// DOCUMENT-START +// SCALAR("a double-quoted scalar",double-quoted) +// DOCUMENT-START +// SCALAR("a literal scalar",literal) +// DOCUMENT-START +// SCALAR("a folded scalar",folded) +// STREAM-END +// +// Now it's time to review collection-related tokens. We will start with +// flow collections: +// +// FLOW-SEQUENCE-START +// FLOW-SEQUENCE-END +// FLOW-MAPPING-START +// FLOW-MAPPING-END +// FLOW-ENTRY +// KEY +// VALUE +// +// The tokens FLOW-SEQUENCE-START, FLOW-SEQUENCE-END, FLOW-MAPPING-START, and +// FLOW-MAPPING-END represent the indicators '[', ']', '{', and '}' +// correspondingly. FLOW-ENTRY represent the ',' indicator. Finally the +// indicators '?' and ':', which are used for denoting mapping keys and values, +// are represented by the KEY and VALUE tokens. +// +// The following examples show flow collections: +// +// 1. A flow sequence: +// +// [item 1, item 2, item 3] +// +// Tokens: +// +// STREAM-START(utf-8) +// FLOW-SEQUENCE-START +// SCALAR("item 1",plain) +// FLOW-ENTRY +// SCALAR("item 2",plain) +// FLOW-ENTRY +// SCALAR("item 3",plain) +// FLOW-SEQUENCE-END +// STREAM-END +// +// 2. A flow mapping: +// +// { +// a simple key: a value, # Note that the KEY token is produced. +// ? a complex key: another value, +// } +// +// Tokens: +// +// STREAM-START(utf-8) +// FLOW-MAPPING-START +// KEY +// SCALAR("a simple key",plain) +// VALUE +// SCALAR("a value",plain) +// FLOW-ENTRY +// KEY +// SCALAR("a complex key",plain) +// VALUE +// SCALAR("another value",plain) +// FLOW-ENTRY +// FLOW-MAPPING-END +// STREAM-END +// +// A simple key is a key which is not denoted by the '?' indicator. Note that +// the Scanner still produce the KEY token whenever it encounters a simple key. +// +// For scanning block collections, the following tokens are used (note that we +// repeat KEY and VALUE here): +// +// BLOCK-SEQUENCE-START +// BLOCK-MAPPING-START +// BLOCK-END +// BLOCK-ENTRY +// KEY +// VALUE +// +// The tokens BLOCK-SEQUENCE-START and BLOCK-MAPPING-START denote indentation +// increase that precedes a block collection (cf. the INDENT token in Python). +// The token BLOCK-END denote indentation decrease that ends a block collection +// (cf. the DEDENT token in Python). However YAML has some syntax pecularities +// that makes detections of these tokens more complex. +// +// The tokens BLOCK-ENTRY, KEY, and VALUE are used to represent the indicators +// '-', '?', and ':' correspondingly. +// +// The following examples show how the tokens BLOCK-SEQUENCE-START, +// BLOCK-MAPPING-START, and BLOCK-END are emitted by the Scanner: +// +// 1. Block sequences: +// +// - item 1 +// - item 2 +// - +// - item 3.1 +// - item 3.2 +// - +// key 1: value 1 +// key 2: value 2 +// +// Tokens: +// +// STREAM-START(utf-8) +// BLOCK-SEQUENCE-START +// BLOCK-ENTRY +// SCALAR("item 1",plain) +// BLOCK-ENTRY +// SCALAR("item 2",plain) +// BLOCK-ENTRY +// BLOCK-SEQUENCE-START +// BLOCK-ENTRY +// SCALAR("item 3.1",plain) +// BLOCK-ENTRY +// SCALAR("item 3.2",plain) +// BLOCK-END +// BLOCK-ENTRY +// BLOCK-MAPPING-START +// KEY +// SCALAR("key 1",plain) +// VALUE +// SCALAR("value 1",plain) +// KEY +// SCALAR("key 2",plain) +// VALUE +// SCALAR("value 2",plain) +// BLOCK-END +// BLOCK-END +// STREAM-END +// +// 2. Block mappings: +// +// a simple key: a value # The KEY token is produced here. +// ? a complex key +// : another value +// a mapping: +// key 1: value 1 +// key 2: value 2 +// a sequence: +// - item 1 +// - item 2 +// +// Tokens: +// +// STREAM-START(utf-8) +// BLOCK-MAPPING-START +// KEY +// SCALAR("a simple key",plain) +// VALUE +// SCALAR("a value",plain) +// KEY +// SCALAR("a complex key",plain) +// VALUE +// SCALAR("another value",plain) +// KEY +// SCALAR("a mapping",plain) +// BLOCK-MAPPING-START +// KEY +// SCALAR("key 1",plain) +// VALUE +// SCALAR("value 1",plain) +// KEY +// SCALAR("key 2",plain) +// VALUE +// SCALAR("value 2",plain) +// BLOCK-END +// KEY +// SCALAR("a sequence",plain) +// VALUE +// BLOCK-SEQUENCE-START +// BLOCK-ENTRY +// SCALAR("item 1",plain) +// BLOCK-ENTRY +// SCALAR("item 2",plain) +// BLOCK-END +// BLOCK-END +// STREAM-END +// +// YAML does not always require to start a new block collection from a new +// line. If the current line contains only '-', '?', and ':' indicators, a new +// block collection may start at the current line. The following examples +// illustrate this case: +// +// 1. Collections in a sequence: +// +// - - item 1 +// - item 2 +// - key 1: value 1 +// key 2: value 2 +// - ? complex key +// : complex value +// +// Tokens: +// +// STREAM-START(utf-8) +// BLOCK-SEQUENCE-START +// BLOCK-ENTRY +// BLOCK-SEQUENCE-START +// BLOCK-ENTRY +// SCALAR("item 1",plain) +// BLOCK-ENTRY +// SCALAR("item 2",plain) +// BLOCK-END +// BLOCK-ENTRY +// BLOCK-MAPPING-START +// KEY +// SCALAR("key 1",plain) +// VALUE +// SCALAR("value 1",plain) +// KEY +// SCALAR("key 2",plain) +// VALUE +// SCALAR("value 2",plain) +// BLOCK-END +// BLOCK-ENTRY +// BLOCK-MAPPING-START +// KEY +// SCALAR("complex key") +// VALUE +// SCALAR("complex value") +// BLOCK-END +// BLOCK-END +// STREAM-END +// +// 2. Collections in a mapping: +// +// ? a sequence +// : - item 1 +// - item 2 +// ? a mapping +// : key 1: value 1 +// key 2: value 2 +// +// Tokens: +// +// STREAM-START(utf-8) +// BLOCK-MAPPING-START +// KEY +// SCALAR("a sequence",plain) +// VALUE +// BLOCK-SEQUENCE-START +// BLOCK-ENTRY +// SCALAR("item 1",plain) +// BLOCK-ENTRY +// SCALAR("item 2",plain) +// BLOCK-END +// KEY +// SCALAR("a mapping",plain) +// VALUE +// BLOCK-MAPPING-START +// KEY +// SCALAR("key 1",plain) +// VALUE +// SCALAR("value 1",plain) +// KEY +// SCALAR("key 2",plain) +// VALUE +// SCALAR("value 2",plain) +// BLOCK-END +// BLOCK-END +// STREAM-END +// +// YAML also permits non-indented sequences if they are included into a block +// mapping. In this case, the token BLOCK-SEQUENCE-START is not produced: +// +// key: +// - item 1 # BLOCK-SEQUENCE-START is NOT produced here. +// - item 2 +// +// Tokens: +// +// STREAM-START(utf-8) +// BLOCK-MAPPING-START +// KEY +// SCALAR("key",plain) +// VALUE +// BLOCK-ENTRY +// SCALAR("item 1",plain) +// BLOCK-ENTRY +// SCALAR("item 2",plain) +// BLOCK-END +// + +// Ensure that the buffer contains the required number of characters. +// Return true on success, false on failure (reader error or memory error). +func cache(parser *yaml_parser_t, length int) bool { + // [Go] This was inlined: !cache(A, B) -> unread < B && !update(A, B) + return parser.unread >= length || yaml_parser_update_buffer(parser, length) +} + +// Advance the buffer pointer. +func skip(parser *yaml_parser_t) { + parser.mark.index++ + parser.mark.column++ + parser.unread-- + parser.buffer_pos += width(parser.buffer[parser.buffer_pos]) +} + +func skip_line(parser *yaml_parser_t) { + if is_crlf(parser.buffer, parser.buffer_pos) { + parser.mark.index += 2 + parser.mark.column = 0 + parser.mark.line++ + parser.unread -= 2 + parser.buffer_pos += 2 + } else if is_break(parser.buffer, parser.buffer_pos) { + parser.mark.index++ + parser.mark.column = 0 + parser.mark.line++ + parser.unread-- + parser.buffer_pos += width(parser.buffer[parser.buffer_pos]) + } +} + +// Copy a character to a string buffer and advance pointers. +func read(parser *yaml_parser_t, s []byte) []byte { + w := width(parser.buffer[parser.buffer_pos]) + if w == 0 { + panic("invalid character sequence") + } + if len(s) == 0 { + s = make([]byte, 0, 32) + } + if w == 1 && len(s)+w <= cap(s) { + s = s[:len(s)+1] + s[len(s)-1] = parser.buffer[parser.buffer_pos] + parser.buffer_pos++ + } else { + s = append(s, parser.buffer[parser.buffer_pos:parser.buffer_pos+w]...) + parser.buffer_pos += w + } + parser.mark.index++ + parser.mark.column++ + parser.unread-- + return s +} + +// Copy a line break character to a string buffer and advance pointers. +func read_line(parser *yaml_parser_t, s []byte) []byte { + buf := parser.buffer + pos := parser.buffer_pos + switch { + case buf[pos] == '\r' && buf[pos+1] == '\n': + // CR LF . LF + s = append(s, '\n') + parser.buffer_pos += 2 + parser.mark.index++ + parser.unread-- + case buf[pos] == '\r' || buf[pos] == '\n': + // CR|LF . LF + s = append(s, '\n') + parser.buffer_pos += 1 + case buf[pos] == '\xC2' && buf[pos+1] == '\x85': + // NEL . LF + s = append(s, '\n') + parser.buffer_pos += 2 + case buf[pos] == '\xE2' && buf[pos+1] == '\x80' && (buf[pos+2] == '\xA8' || buf[pos+2] == '\xA9'): + // LS|PS . LS|PS + s = append(s, buf[parser.buffer_pos:pos+3]...) + parser.buffer_pos += 3 + default: + return s + } + parser.mark.index++ + parser.mark.column = 0 + parser.mark.line++ + parser.unread-- + return s +} + +// Get the next token. +func yaml_parser_scan(parser *yaml_parser_t, token *yaml_token_t) bool { + // Erase the token object. + *token = yaml_token_t{} // [Go] Is this necessary? + + // No tokens after STREAM-END or error. + if parser.stream_end_produced || parser.error != yaml_NO_ERROR { + return true + } + + // Ensure that the tokens queue contains enough tokens. + if !parser.token_available { + if !yaml_parser_fetch_more_tokens(parser) { + return false + } + } + + // Fetch the next token from the queue. + *token = parser.tokens[parser.tokens_head] + parser.tokens_head++ + parser.tokens_parsed++ + parser.token_available = false + + if token.typ == yaml_STREAM_END_TOKEN { + parser.stream_end_produced = true + } + return true +} + +// Set the scanner error and return false. +func yaml_parser_set_scanner_error(parser *yaml_parser_t, context string, context_mark yaml_mark_t, problem string) bool { + parser.error = yaml_SCANNER_ERROR + parser.context = context + parser.context_mark = context_mark + parser.problem = problem + parser.problem_mark = parser.mark + return false +} + +func yaml_parser_set_scanner_tag_error(parser *yaml_parser_t, directive bool, context_mark yaml_mark_t, problem string) bool { + context := "while parsing a tag" + if directive { + context = "while parsing a %TAG directive" + } + return yaml_parser_set_scanner_error(parser, context, context_mark, problem) +} + +func trace(args ...interface{}) func() { + pargs := append([]interface{}{"+++"}, args...) + fmt.Println(pargs...) + pargs = append([]interface{}{"---"}, args...) + return func() { fmt.Println(pargs...) } +} + +// Ensure that the tokens queue contains at least one token which can be +// returned to the Parser. +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) { + return false + } + + 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) { + return false + } + } + + parser.token_available = true + return true +} + +// The dispatcher for token fetchers. +func yaml_parser_fetch_next_token(parser *yaml_parser_t) bool { + // Ensure that the buffer is initialized. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + + // Check if we just started scanning. Fetch STREAM-START then. + if !parser.stream_start_produced { + return yaml_parser_fetch_stream_start(parser) + } + + // Eat whitespaces and comments until we reach the next token. + if !yaml_parser_scan_to_next_token(parser) { + 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 + } + + // Ensure that the buffer contains at least 4 characters. 4 is the length + // of the longest indicators ('--- ' and '... '). + if parser.unread < 4 && !yaml_parser_update_buffer(parser, 4) { + return false + } + + // Is it the end of the stream? + if is_z(parser.buffer, parser.buffer_pos) { + return yaml_parser_fetch_stream_end(parser) + } + + // Is it a directive? + if parser.mark.column == 0 && parser.buffer[parser.buffer_pos] == '%' { + return yaml_parser_fetch_directive(parser) + } + + buf := parser.buffer + pos := parser.buffer_pos + + // Is it the document start indicator? + if parser.mark.column == 0 && buf[pos] == '-' && buf[pos+1] == '-' && buf[pos+2] == '-' && is_blankz(buf, pos+3) { + return yaml_parser_fetch_document_indicator(parser, yaml_DOCUMENT_START_TOKEN) + } + + // Is it the document end indicator? + if parser.mark.column == 0 && buf[pos] == '.' && buf[pos+1] == '.' && buf[pos+2] == '.' && is_blankz(buf, pos+3) { + return yaml_parser_fetch_document_indicator(parser, yaml_DOCUMENT_END_TOKEN) + } + + // Is it the flow sequence start indicator? + if buf[pos] == '[' { + return yaml_parser_fetch_flow_collection_start(parser, yaml_FLOW_SEQUENCE_START_TOKEN) + } + + // Is it the flow mapping start indicator? + if parser.buffer[parser.buffer_pos] == '{' { + return yaml_parser_fetch_flow_collection_start(parser, yaml_FLOW_MAPPING_START_TOKEN) + } + + // Is it the flow sequence end indicator? + if parser.buffer[parser.buffer_pos] == ']' { + return yaml_parser_fetch_flow_collection_end(parser, + yaml_FLOW_SEQUENCE_END_TOKEN) + } + + // Is it the flow mapping end indicator? + if parser.buffer[parser.buffer_pos] == '}' { + return yaml_parser_fetch_flow_collection_end(parser, + yaml_FLOW_MAPPING_END_TOKEN) + } + + // Is it the flow entry indicator? + if parser.buffer[parser.buffer_pos] == ',' { + return yaml_parser_fetch_flow_entry(parser) + } + + // Is it the block entry indicator? + if parser.buffer[parser.buffer_pos] == '-' && is_blankz(parser.buffer, parser.buffer_pos+1) { + return yaml_parser_fetch_block_entry(parser) + } + + // Is it the key indicator? + if parser.buffer[parser.buffer_pos] == '?' && (parser.flow_level > 0 || is_blankz(parser.buffer, parser.buffer_pos+1)) { + return yaml_parser_fetch_key(parser) + } + + // Is it the value indicator? + if parser.buffer[parser.buffer_pos] == ':' && (parser.flow_level > 0 || is_blankz(parser.buffer, parser.buffer_pos+1)) { + return yaml_parser_fetch_value(parser) + } + + // Is it an alias? + if parser.buffer[parser.buffer_pos] == '*' { + return yaml_parser_fetch_anchor(parser, yaml_ALIAS_TOKEN) + } + + // Is it an anchor? + if parser.buffer[parser.buffer_pos] == '&' { + return yaml_parser_fetch_anchor(parser, yaml_ANCHOR_TOKEN) + } + + // Is it a tag? + if parser.buffer[parser.buffer_pos] == '!' { + return yaml_parser_fetch_tag(parser) + } + + // Is it a literal scalar? + if parser.buffer[parser.buffer_pos] == '|' && parser.flow_level == 0 { + return yaml_parser_fetch_block_scalar(parser, true) + } + + // Is it a folded scalar? + if parser.buffer[parser.buffer_pos] == '>' && parser.flow_level == 0 { + return yaml_parser_fetch_block_scalar(parser, false) + } + + // Is it a single-quoted scalar? + if parser.buffer[parser.buffer_pos] == '\'' { + return yaml_parser_fetch_flow_scalar(parser, true) + } + + // Is it a double-quoted scalar? + if parser.buffer[parser.buffer_pos] == '"' { + return yaml_parser_fetch_flow_scalar(parser, false) + } + + // Is it a plain scalar? + // + // A plain scalar may start with any non-blank characters except + // + // '-', '?', ':', ',', '[', ']', '{', '}', + // '#', '&', '*', '!', '|', '>', '\'', '\"', + // '%', '@', '`'. + // + // In the block context (and, for the '-' indicator, in the flow context + // too), it may also start with the characters + // + // '-', '?', ':' + // + // if it is followed by a non-space character. + // + // The last rule is more restrictive than the specification requires. + // [Go] Make this logic more reasonable. + //switch parser.buffer[parser.buffer_pos] { + //case '-', '?', ':', ',', '?', '-', ',', ':', ']', '[', '}', '{', '&', '#', '!', '*', '>', '|', '"', '\'', '@', '%', '-', '`': + //} + if !(is_blankz(parser.buffer, parser.buffer_pos) || parser.buffer[parser.buffer_pos] == '-' || + parser.buffer[parser.buffer_pos] == '?' || parser.buffer[parser.buffer_pos] == ':' || + parser.buffer[parser.buffer_pos] == ',' || parser.buffer[parser.buffer_pos] == '[' || + parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '{' || + parser.buffer[parser.buffer_pos] == '}' || parser.buffer[parser.buffer_pos] == '#' || + parser.buffer[parser.buffer_pos] == '&' || parser.buffer[parser.buffer_pos] == '*' || + parser.buffer[parser.buffer_pos] == '!' || parser.buffer[parser.buffer_pos] == '|' || + parser.buffer[parser.buffer_pos] == '>' || parser.buffer[parser.buffer_pos] == '\'' || + parser.buffer[parser.buffer_pos] == '"' || parser.buffer[parser.buffer_pos] == '%' || + parser.buffer[parser.buffer_pos] == '@' || parser.buffer[parser.buffer_pos] == '`') || + (parser.buffer[parser.buffer_pos] == '-' && !is_blank(parser.buffer, parser.buffer_pos+1)) || + (parser.flow_level == 0 && + (parser.buffer[parser.buffer_pos] == '?' || parser.buffer[parser.buffer_pos] == ':') && + !is_blankz(parser.buffer, parser.buffer_pos+1)) { + return yaml_parser_fetch_plain_scalar(parser) + } + + // If we don't determine the token type so far, it is an error. + return yaml_parser_set_scanner_error(parser, + "while scanning for the next token", parser.mark, + "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 + } + } + return true +} + +// Check if a simple key may start at the current position and add it if +// needed. +func yaml_parser_save_simple_key(parser *yaml_parser_t) bool { + // A simple key is required at the current position if the scanner is in + // the block context and the current column coincides with the indentation + // level. + + required := parser.flow_level == 0 && parser.indent == parser.mark.column + + // A simple key is required only when it is the first token in the current + // line. Therefore it is always allowed. But we add a check anyway. + if required && !parser.simple_key_allowed { + panic("should not happen") + } + + // + // If the current position may start a simple key, save it. + // + if parser.simple_key_allowed { + simple_key := yaml_simple_key_t{ + possible: true, + required: required, + token_number: parser.tokens_parsed + (len(parser.tokens) - parser.tokens_head), + } + simple_key.mark = parser.mark + + if !yaml_parser_remove_simple_key(parser) { + return false + } + parser.simple_keys[len(parser.simple_keys)-1] = simple_key + } + return true +} + +// Remove a potential simple key at the current flow level. +func yaml_parser_remove_simple_key(parser *yaml_parser_t) bool { + i := len(parser.simple_keys) - 1 + if parser.simple_keys[i].possible { + // If the key is required, it is an error. + if parser.simple_keys[i].required { + return yaml_parser_set_scanner_error(parser, + "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 + return true +} + +// 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{}) + + // Increase the flow level. + parser.flow_level++ + return true +} + +// Decrease the flow level. +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] + } + return true +} + +// Push the current indentation level to the stack and set the new level +// the current column is greater than the indentation level. In this case, +// append or insert the specified token into the token queue. +func yaml_parser_roll_indent(parser *yaml_parser_t, column, number int, typ yaml_token_type_t, mark yaml_mark_t) bool { + // In the flow context, do nothing. + if parser.flow_level > 0 { + return true + } + + if parser.indent < column { + // Push the current indentation level to the stack and set the new + // indentation level. + parser.indents = append(parser.indents, parser.indent) + parser.indent = column + + // Create a token and insert it into the queue. + token := yaml_token_t{ + typ: typ, + start_mark: mark, + end_mark: mark, + } + if number > -1 { + number -= parser.tokens_parsed + } + yaml_insert_token(parser, number, &token) + } + return true +} + +// Pop indentation levels from the indents stack until the current level +// becomes less or equal to the column. For each indentation level, append +// the BLOCK-END token. +func yaml_parser_unroll_indent(parser *yaml_parser_t, column int) bool { + // In the flow context, do nothing. + if parser.flow_level > 0 { + return true + } + + // Loop through the indentation levels in the stack. + for parser.indent > column { + // Create a token and append it to the queue. + token := yaml_token_t{ + typ: yaml_BLOCK_END_TOKEN, + start_mark: parser.mark, + end_mark: parser.mark, + } + yaml_insert_token(parser, -1, &token) + + // Pop the indentation level. + parser.indent = parser.indents[len(parser.indents)-1] + parser.indents = parser.indents[:len(parser.indents)-1] + } + return true +} + +// Initialize the scanner and produce the STREAM-START token. +func yaml_parser_fetch_stream_start(parser *yaml_parser_t) bool { + + // Set the initial indentation. + parser.indent = -1 + + // Initialize the simple key stack. + parser.simple_keys = append(parser.simple_keys, yaml_simple_key_t{}) + + // A simple key is allowed at the beginning of the stream. + parser.simple_key_allowed = true + + // We have started. + parser.stream_start_produced = true + + // Create the STREAM-START token and append it to the queue. + token := yaml_token_t{ + typ: yaml_STREAM_START_TOKEN, + start_mark: parser.mark, + end_mark: parser.mark, + encoding: parser.encoding, + } + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce the STREAM-END token and shut down the scanner. +func yaml_parser_fetch_stream_end(parser *yaml_parser_t) bool { + + // Force new line. + if parser.mark.column != 0 { + parser.mark.column = 0 + parser.mark.line++ + } + + // Reset the indentation level. + if !yaml_parser_unroll_indent(parser, -1) { + return false + } + + // Reset simple keys. + if !yaml_parser_remove_simple_key(parser) { + return false + } + + parser.simple_key_allowed = false + + // Create the STREAM-END token and append it to the queue. + token := yaml_token_t{ + typ: yaml_STREAM_END_TOKEN, + start_mark: parser.mark, + end_mark: parser.mark, + } + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce a VERSION-DIRECTIVE or TAG-DIRECTIVE token. +func yaml_parser_fetch_directive(parser *yaml_parser_t) bool { + // Reset the indentation level. + if !yaml_parser_unroll_indent(parser, -1) { + return false + } + + // Reset simple keys. + if !yaml_parser_remove_simple_key(parser) { + return false + } + + parser.simple_key_allowed = false + + // Create the YAML-DIRECTIVE or TAG-DIRECTIVE token. + token := yaml_token_t{} + if !yaml_parser_scan_directive(parser, &token) { + return false + } + // Append the token to the queue. + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce the DOCUMENT-START or DOCUMENT-END token. +func yaml_parser_fetch_document_indicator(parser *yaml_parser_t, typ yaml_token_type_t) bool { + // Reset the indentation level. + if !yaml_parser_unroll_indent(parser, -1) { + return false + } + + // Reset simple keys. + if !yaml_parser_remove_simple_key(parser) { + return false + } + + parser.simple_key_allowed = false + + // Consume the token. + start_mark := parser.mark + + skip(parser) + skip(parser) + skip(parser) + + end_mark := parser.mark + + // Create the DOCUMENT-START or DOCUMENT-END token. + token := yaml_token_t{ + typ: typ, + start_mark: start_mark, + end_mark: end_mark, + } + // Append the token to the queue. + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce the FLOW-SEQUENCE-START or FLOW-MAPPING-START token. +func yaml_parser_fetch_flow_collection_start(parser *yaml_parser_t, typ yaml_token_type_t) bool { + // The indicators '[' and '{' may start a simple key. + if !yaml_parser_save_simple_key(parser) { + return false + } + + // Increase the flow level. + if !yaml_parser_increase_flow_level(parser) { + return false + } + + // A simple key may follow the indicators '[' and '{'. + parser.simple_key_allowed = true + + // Consume the token. + start_mark := parser.mark + skip(parser) + end_mark := parser.mark + + // Create the FLOW-SEQUENCE-START of FLOW-MAPPING-START token. + token := yaml_token_t{ + typ: typ, + start_mark: start_mark, + end_mark: end_mark, + } + // Append the token to the queue. + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce the FLOW-SEQUENCE-END or FLOW-MAPPING-END token. +func yaml_parser_fetch_flow_collection_end(parser *yaml_parser_t, typ yaml_token_type_t) bool { + // Reset any potential simple key on the current flow level. + if !yaml_parser_remove_simple_key(parser) { + return false + } + + // Decrease the flow level. + if !yaml_parser_decrease_flow_level(parser) { + return false + } + + // No simple keys after the indicators ']' and '}'. + parser.simple_key_allowed = false + + // Consume the token. + + start_mark := parser.mark + skip(parser) + end_mark := parser.mark + + // Create the FLOW-SEQUENCE-END of FLOW-MAPPING-END token. + token := yaml_token_t{ + typ: typ, + start_mark: start_mark, + end_mark: end_mark, + } + // Append the token to the queue. + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce the FLOW-ENTRY token. +func yaml_parser_fetch_flow_entry(parser *yaml_parser_t) bool { + // Reset any potential simple keys on the current flow level. + if !yaml_parser_remove_simple_key(parser) { + return false + } + + // Simple keys are allowed after ','. + parser.simple_key_allowed = true + + // Consume the token. + start_mark := parser.mark + skip(parser) + end_mark := parser.mark + + // Create the FLOW-ENTRY token and append it to the queue. + token := yaml_token_t{ + typ: yaml_FLOW_ENTRY_TOKEN, + start_mark: start_mark, + end_mark: end_mark, + } + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce the BLOCK-ENTRY token. +func yaml_parser_fetch_block_entry(parser *yaml_parser_t) bool { + // Check if the scanner is in the block context. + if parser.flow_level == 0 { + // Check if we are allowed to start a new entry. + if !parser.simple_key_allowed { + return yaml_parser_set_scanner_error(parser, "", parser.mark, + "block sequence entries are not allowed in this context") + } + // Add the BLOCK-SEQUENCE-START token if needed. + if !yaml_parser_roll_indent(parser, parser.mark.column, -1, yaml_BLOCK_SEQUENCE_START_TOKEN, parser.mark) { + return false + } + } else { + // It is an error for the '-' indicator to occur in the flow context, + // but we let the Parser detect and report about it because the Parser + // is able to point to the context. + } + + // Reset any potential simple keys on the current flow level. + if !yaml_parser_remove_simple_key(parser) { + return false + } + + // Simple keys are allowed after '-'. + parser.simple_key_allowed = true + + // Consume the token. + start_mark := parser.mark + skip(parser) + end_mark := parser.mark + + // Create the BLOCK-ENTRY token and append it to the queue. + token := yaml_token_t{ + typ: yaml_BLOCK_ENTRY_TOKEN, + start_mark: start_mark, + end_mark: end_mark, + } + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce the KEY token. +func yaml_parser_fetch_key(parser *yaml_parser_t) bool { + + // In the block context, additional checks are required. + if parser.flow_level == 0 { + // Check if we are allowed to start a new key (not nessesary simple). + if !parser.simple_key_allowed { + return yaml_parser_set_scanner_error(parser, "", parser.mark, + "mapping keys are not allowed in this context") + } + // Add the BLOCK-MAPPING-START token if needed. + if !yaml_parser_roll_indent(parser, parser.mark.column, -1, yaml_BLOCK_MAPPING_START_TOKEN, parser.mark) { + return false + } + } + + // Reset any potential simple keys on the current flow level. + if !yaml_parser_remove_simple_key(parser) { + return false + } + + // Simple keys are allowed after '?' in the block context. + parser.simple_key_allowed = parser.flow_level == 0 + + // Consume the token. + start_mark := parser.mark + skip(parser) + end_mark := parser.mark + + // Create the KEY token and append it to the queue. + token := yaml_token_t{ + typ: yaml_KEY_TOKEN, + start_mark: start_mark, + end_mark: end_mark, + } + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce the VALUE token. +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 { + // Create the KEY token and insert it into the queue. + token := yaml_token_t{ + typ: yaml_KEY_TOKEN, + start_mark: simple_key.mark, + end_mark: simple_key.mark, + } + yaml_insert_token(parser, simple_key.token_number-parser.tokens_parsed, &token) + + // In the block context, we may need to add the BLOCK-MAPPING-START token. + if !yaml_parser_roll_indent(parser, simple_key.mark.column, + simple_key.token_number, + yaml_BLOCK_MAPPING_START_TOKEN, simple_key.mark) { + return false + } + + // Remove the simple key. + simple_key.possible = false + + // A simple key cannot follow another simple key. + parser.simple_key_allowed = false + + } else { + // The ':' indicator follows a complex key. + + // In the block context, extra checks are required. + if parser.flow_level == 0 { + + // Check if we are allowed to start a complex value. + if !parser.simple_key_allowed { + return yaml_parser_set_scanner_error(parser, "", parser.mark, + "mapping values are not allowed in this context") + } + + // Add the BLOCK-MAPPING-START token if needed. + if !yaml_parser_roll_indent(parser, parser.mark.column, -1, yaml_BLOCK_MAPPING_START_TOKEN, parser.mark) { + return false + } + } + + // Simple keys after ':' are allowed in the block context. + parser.simple_key_allowed = parser.flow_level == 0 + } + + // Consume the token. + start_mark := parser.mark + skip(parser) + end_mark := parser.mark + + // Create the VALUE token and append it to the queue. + token := yaml_token_t{ + typ: yaml_VALUE_TOKEN, + start_mark: start_mark, + end_mark: end_mark, + } + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce the ALIAS or ANCHOR token. +func yaml_parser_fetch_anchor(parser *yaml_parser_t, typ yaml_token_type_t) bool { + // An anchor or an alias could be a simple key. + if !yaml_parser_save_simple_key(parser) { + return false + } + + // A simple key cannot follow an anchor or an alias. + parser.simple_key_allowed = false + + // Create the ALIAS or ANCHOR token and append it to the queue. + var token yaml_token_t + if !yaml_parser_scan_anchor(parser, &token, typ) { + return false + } + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce the TAG token. +func yaml_parser_fetch_tag(parser *yaml_parser_t) bool { + // A tag could be a simple key. + if !yaml_parser_save_simple_key(parser) { + return false + } + + // A simple key cannot follow a tag. + parser.simple_key_allowed = false + + // Create the TAG token and append it to the queue. + var token yaml_token_t + if !yaml_parser_scan_tag(parser, &token) { + return false + } + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce the SCALAR(...,literal) or SCALAR(...,folded) tokens. +func yaml_parser_fetch_block_scalar(parser *yaml_parser_t, literal bool) bool { + // Remove any potential simple keys. + if !yaml_parser_remove_simple_key(parser) { + return false + } + + // A simple key may follow a block scalar. + parser.simple_key_allowed = true + + // Create the SCALAR token and append it to the queue. + var token yaml_token_t + if !yaml_parser_scan_block_scalar(parser, &token, literal) { + return false + } + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce the SCALAR(...,single-quoted) or SCALAR(...,double-quoted) tokens. +func yaml_parser_fetch_flow_scalar(parser *yaml_parser_t, single bool) bool { + // A plain scalar could be a simple key. + if !yaml_parser_save_simple_key(parser) { + return false + } + + // A simple key cannot follow a flow scalar. + parser.simple_key_allowed = false + + // Create the SCALAR token and append it to the queue. + var token yaml_token_t + if !yaml_parser_scan_flow_scalar(parser, &token, single) { + return false + } + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce the SCALAR(...,plain) token. +func yaml_parser_fetch_plain_scalar(parser *yaml_parser_t) bool { + // A plain scalar could be a simple key. + if !yaml_parser_save_simple_key(parser) { + return false + } + + // A simple key cannot follow a flow scalar. + parser.simple_key_allowed = false + + // Create the SCALAR token and append it to the queue. + var token yaml_token_t + if !yaml_parser_scan_plain_scalar(parser, &token) { + return false + } + yaml_insert_token(parser, -1, &token) + return true +} + +// Eat whitespaces and comments until the next token is found. +func yaml_parser_scan_to_next_token(parser *yaml_parser_t) bool { + + // Until the next token is not found. + for { + // Allow the BOM mark to start a line. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + if parser.mark.column == 0 && is_bom(parser.buffer, parser.buffer_pos) { + skip(parser) + } + + // Eat whitespaces. + // Tabs are allowed: + // - in the flow context + // - in the block context, but not at the beginning of the line or + // after '-', '?', or ':' (complex value). + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + + for parser.buffer[parser.buffer_pos] == ' ' || ((parser.flow_level > 0 || !parser.simple_key_allowed) && parser.buffer[parser.buffer_pos] == '\t') { + skip(parser) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + + // Eat a comment until a line break. + if parser.buffer[parser.buffer_pos] == '#' { + for !is_breakz(parser.buffer, parser.buffer_pos) { + skip(parser) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + } + + // If it is a line break, eat it. + if is_break(parser.buffer, parser.buffer_pos) { + if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { + return false + } + skip_line(parser) + + // In the block context, a new line may start a simple key. + if parser.flow_level == 0 { + parser.simple_key_allowed = true + } + } else { + break // We have found a token. + } + } + + return true +} + +// Scan a YAML-DIRECTIVE or TAG-DIRECTIVE token. +// +// Scope: +// %YAML 1.1 # a comment \n +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// %TAG !yaml! tag:yaml.org,2002: \n +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// +func yaml_parser_scan_directive(parser *yaml_parser_t, token *yaml_token_t) bool { + // Eat '%'. + start_mark := parser.mark + skip(parser) + + // Scan the directive name. + var name []byte + if !yaml_parser_scan_directive_name(parser, start_mark, &name) { + return false + } + + // Is it a YAML directive? + if bytes.Equal(name, []byte("YAML")) { + // Scan the VERSION directive value. + var major, minor int8 + if !yaml_parser_scan_version_directive_value(parser, start_mark, &major, &minor) { + return false + } + end_mark := parser.mark + + // Create a VERSION-DIRECTIVE token. + *token = yaml_token_t{ + typ: yaml_VERSION_DIRECTIVE_TOKEN, + start_mark: start_mark, + end_mark: end_mark, + major: major, + minor: minor, + } + + // Is it a TAG directive? + } else if bytes.Equal(name, []byte("TAG")) { + // Scan the TAG directive value. + var handle, prefix []byte + if !yaml_parser_scan_tag_directive_value(parser, start_mark, &handle, &prefix) { + return false + } + end_mark := parser.mark + + // Create a TAG-DIRECTIVE token. + *token = yaml_token_t{ + typ: yaml_TAG_DIRECTIVE_TOKEN, + start_mark: start_mark, + end_mark: end_mark, + value: handle, + prefix: prefix, + } + + // Unknown directive. + } else { + yaml_parser_set_scanner_error(parser, "while scanning a directive", + start_mark, "found unknown directive name") + return false + } + + // Eat the rest of the line including any comments. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + + for is_blank(parser.buffer, parser.buffer_pos) { + skip(parser) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + + if parser.buffer[parser.buffer_pos] == '#' { + for !is_breakz(parser.buffer, parser.buffer_pos) { + skip(parser) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + } + + // Check if we are at the end of the line. + if !is_breakz(parser.buffer, parser.buffer_pos) { + yaml_parser_set_scanner_error(parser, "while scanning a directive", + start_mark, "did not find expected comment or line break") + return false + } + + // Eat a line break. + if is_break(parser.buffer, parser.buffer_pos) { + if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { + return false + } + skip_line(parser) + } + + return true +} + +// Scan the directive name. +// +// Scope: +// %YAML 1.1 # a comment \n +// ^^^^ +// %TAG !yaml! tag:yaml.org,2002: \n +// ^^^ +// +func yaml_parser_scan_directive_name(parser *yaml_parser_t, start_mark yaml_mark_t, name *[]byte) bool { + // Consume the directive name. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + + var s []byte + for is_alpha(parser.buffer, parser.buffer_pos) { + s = read(parser, s) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + + // Check if the name is empty. + if len(s) == 0 { + yaml_parser_set_scanner_error(parser, "while scanning a directive", + start_mark, "could not find expected directive name") + return false + } + + // Check for an blank character after the name. + if !is_blankz(parser.buffer, parser.buffer_pos) { + yaml_parser_set_scanner_error(parser, "while scanning a directive", + start_mark, "found unexpected non-alphabetical character") + return false + } + *name = s + return true +} + +// Scan the value of VERSION-DIRECTIVE. +// +// Scope: +// %YAML 1.1 # a comment \n +// ^^^^^^ +func yaml_parser_scan_version_directive_value(parser *yaml_parser_t, start_mark yaml_mark_t, major, minor *int8) bool { + // Eat whitespaces. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + for is_blank(parser.buffer, parser.buffer_pos) { + skip(parser) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + + // Consume the major version number. + if !yaml_parser_scan_version_directive_number(parser, start_mark, major) { + return false + } + + // Eat '.'. + if parser.buffer[parser.buffer_pos] != '.' { + return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive", + start_mark, "did not find expected digit or '.' character") + } + + skip(parser) + + // Consume the minor version number. + if !yaml_parser_scan_version_directive_number(parser, start_mark, minor) { + return false + } + return true +} + +const max_number_length = 2 + +// Scan the version number of VERSION-DIRECTIVE. +// +// Scope: +// %YAML 1.1 # a comment \n +// ^ +// %YAML 1.1 # a comment \n +// ^ +func yaml_parser_scan_version_directive_number(parser *yaml_parser_t, start_mark yaml_mark_t, number *int8) bool { + + // Repeat while the next character is digit. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + var value, length int8 + for is_digit(parser.buffer, parser.buffer_pos) { + // Check if the number is too long. + length++ + if length > max_number_length { + return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive", + start_mark, "found extremely long version number") + } + value = value*10 + int8(as_digit(parser.buffer, parser.buffer_pos)) + skip(parser) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + + // Check if the number was present. + if length == 0 { + return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive", + start_mark, "did not find expected version number") + } + *number = value + return true +} + +// Scan the value of a TAG-DIRECTIVE token. +// +// Scope: +// %TAG !yaml! tag:yaml.org,2002: \n +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// +func yaml_parser_scan_tag_directive_value(parser *yaml_parser_t, start_mark yaml_mark_t, handle, prefix *[]byte) bool { + var handle_value, prefix_value []byte + + // Eat whitespaces. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + + for is_blank(parser.buffer, parser.buffer_pos) { + skip(parser) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + + // Scan a handle. + if !yaml_parser_scan_tag_handle(parser, true, start_mark, &handle_value) { + return false + } + + // Expect a whitespace. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + if !is_blank(parser.buffer, parser.buffer_pos) { + yaml_parser_set_scanner_error(parser, "while scanning a %TAG directive", + start_mark, "did not find expected whitespace") + return false + } + + // Eat whitespaces. + for is_blank(parser.buffer, parser.buffer_pos) { + skip(parser) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + + // Scan a prefix. + if !yaml_parser_scan_tag_uri(parser, true, nil, start_mark, &prefix_value) { + return false + } + + // Expect a whitespace or line break. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + if !is_blankz(parser.buffer, parser.buffer_pos) { + yaml_parser_set_scanner_error(parser, "while scanning a %TAG directive", + start_mark, "did not find expected whitespace or line break") + return false + } + + *handle = handle_value + *prefix = prefix_value + return true +} + +func yaml_parser_scan_anchor(parser *yaml_parser_t, token *yaml_token_t, typ yaml_token_type_t) bool { + var s []byte + + // Eat the indicator character. + start_mark := parser.mark + skip(parser) + + // Consume the value. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + + for is_alpha(parser.buffer, parser.buffer_pos) { + s = read(parser, s) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + + end_mark := parser.mark + + /* + * Check if length of the anchor is greater than 0 and it is followed by + * a whitespace character or one of the indicators: + * + * '?', ':', ',', ']', '}', '%', '@', '`'. + */ + + if len(s) == 0 || + !(is_blankz(parser.buffer, parser.buffer_pos) || parser.buffer[parser.buffer_pos] == '?' || + parser.buffer[parser.buffer_pos] == ':' || parser.buffer[parser.buffer_pos] == ',' || + parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '}' || + parser.buffer[parser.buffer_pos] == '%' || parser.buffer[parser.buffer_pos] == '@' || + parser.buffer[parser.buffer_pos] == '`') { + context := "while scanning an alias" + if typ == yaml_ANCHOR_TOKEN { + context = "while scanning an anchor" + } + yaml_parser_set_scanner_error(parser, context, start_mark, + "did not find expected alphabetic or numeric character") + return false + } + + // Create a token. + *token = yaml_token_t{ + typ: typ, + start_mark: start_mark, + end_mark: end_mark, + value: s, + } + + return true +} + +/* + * Scan a TAG token. + */ + +func yaml_parser_scan_tag(parser *yaml_parser_t, token *yaml_token_t) bool { + var handle, suffix []byte + + start_mark := parser.mark + + // Check if the tag is in the canonical form. + if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { + return false + } + + if parser.buffer[parser.buffer_pos+1] == '<' { + // Keep the handle as '' + + // Eat '!<' + skip(parser) + skip(parser) + + // Consume the tag value. + if !yaml_parser_scan_tag_uri(parser, false, nil, start_mark, &suffix) { + return false + } + + // Check for '>' and eat it. + if parser.buffer[parser.buffer_pos] != '>' { + yaml_parser_set_scanner_error(parser, "while scanning a tag", + start_mark, "did not find the expected '>'") + return false + } + + skip(parser) + } else { + // The tag has either the '!suffix' or the '!handle!suffix' form. + + // First, try to scan a handle. + if !yaml_parser_scan_tag_handle(parser, false, start_mark, &handle) { + return false + } + + // Check if it is, indeed, handle. + if handle[0] == '!' && len(handle) > 1 && handle[len(handle)-1] == '!' { + // Scan the suffix now. + if !yaml_parser_scan_tag_uri(parser, false, nil, start_mark, &suffix) { + return false + } + } else { + // It wasn't a handle after all. Scan the rest of the tag. + if !yaml_parser_scan_tag_uri(parser, false, handle, start_mark, &suffix) { + return false + } + + // Set the handle to '!'. + handle = []byte{'!'} + + // A special case: the '!' tag. Set the handle to '' and the + // suffix to '!'. + if len(suffix) == 0 { + handle, suffix = suffix, handle + } + } + } + + // Check the character which ends the tag. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + if !is_blankz(parser.buffer, parser.buffer_pos) { + yaml_parser_set_scanner_error(parser, "while scanning a tag", + start_mark, "did not find expected whitespace or line break") + return false + } + + end_mark := parser.mark + + // Create a token. + *token = yaml_token_t{ + typ: yaml_TAG_TOKEN, + start_mark: start_mark, + end_mark: end_mark, + value: handle, + suffix: suffix, + } + return true +} + +// Scan a tag handle. +func yaml_parser_scan_tag_handle(parser *yaml_parser_t, directive bool, start_mark yaml_mark_t, handle *[]byte) bool { + // Check the initial '!' character. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + if parser.buffer[parser.buffer_pos] != '!' { + yaml_parser_set_scanner_tag_error(parser, directive, + start_mark, "did not find expected '!'") + return false + } + + var s []byte + + // Copy the '!' character. + s = read(parser, s) + + // Copy all subsequent alphabetical and numerical characters. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + for is_alpha(parser.buffer, parser.buffer_pos) { + s = read(parser, s) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + + // Check if the trailing character is '!' and copy it. + if parser.buffer[parser.buffer_pos] == '!' { + s = read(parser, s) + } else { + // It's either the '!' tag or not really a tag handle. If it's a %TAG + // directive, it's an error. If it's a tag token, it must be a part of URI. + if directive && string(s) != "!" { + yaml_parser_set_scanner_tag_error(parser, directive, + start_mark, "did not find expected '!'") + return false + } + } + + *handle = s + return true +} + +// Scan a tag. +func yaml_parser_scan_tag_uri(parser *yaml_parser_t, directive bool, head []byte, start_mark yaml_mark_t, uri *[]byte) bool { + //size_t length = head ? strlen((char *)head) : 0 + var s []byte + hasTag := len(head) > 0 + + // Copy the head if needed. + // + // Note that we don't copy the leading '!' character. + if len(head) > 1 { + s = append(s, head[1:]...) + } + + // Scan the tag. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + + // The set of characters that may appear in URI is as follows: + // + // '0'-'9', 'A'-'Z', 'a'-'z', '_', '-', ';', '/', '?', ':', '@', '&', + // '=', '+', '$', ',', '.', '!', '~', '*', '\'', '(', ')', '[', ']', + // '%'. + // [Go] Convert this into more reasonable logic. + for is_alpha(parser.buffer, parser.buffer_pos) || parser.buffer[parser.buffer_pos] == ';' || + parser.buffer[parser.buffer_pos] == '/' || parser.buffer[parser.buffer_pos] == '?' || + parser.buffer[parser.buffer_pos] == ':' || parser.buffer[parser.buffer_pos] == '@' || + parser.buffer[parser.buffer_pos] == '&' || parser.buffer[parser.buffer_pos] == '=' || + parser.buffer[parser.buffer_pos] == '+' || parser.buffer[parser.buffer_pos] == '$' || + parser.buffer[parser.buffer_pos] == ',' || parser.buffer[parser.buffer_pos] == '.' || + parser.buffer[parser.buffer_pos] == '!' || parser.buffer[parser.buffer_pos] == '~' || + parser.buffer[parser.buffer_pos] == '*' || parser.buffer[parser.buffer_pos] == '\'' || + parser.buffer[parser.buffer_pos] == '(' || parser.buffer[parser.buffer_pos] == ')' || + parser.buffer[parser.buffer_pos] == '[' || parser.buffer[parser.buffer_pos] == ']' || + parser.buffer[parser.buffer_pos] == '%' { + // Check if it is a URI-escape sequence. + if parser.buffer[parser.buffer_pos] == '%' { + if !yaml_parser_scan_uri_escapes(parser, directive, start_mark, &s) { + return false + } + } else { + s = read(parser, s) + } + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + hasTag = true + } + + if !hasTag { + yaml_parser_set_scanner_tag_error(parser, directive, + start_mark, "did not find expected tag URI") + return false + } + *uri = s + return true +} + +// Decode an URI-escape sequence corresponding to a single UTF-8 character. +func yaml_parser_scan_uri_escapes(parser *yaml_parser_t, directive bool, start_mark yaml_mark_t, s *[]byte) bool { + + // Decode the required number of characters. + w := 1024 + for w > 0 { + // Check for a URI-escaped octet. + if parser.unread < 3 && !yaml_parser_update_buffer(parser, 3) { + return false + } + + if !(parser.buffer[parser.buffer_pos] == '%' && + is_hex(parser.buffer, parser.buffer_pos+1) && + is_hex(parser.buffer, parser.buffer_pos+2)) { + return yaml_parser_set_scanner_tag_error(parser, directive, + start_mark, "did not find URI escaped octet") + } + + // Get the octet. + octet := byte((as_hex(parser.buffer, parser.buffer_pos+1) << 4) + as_hex(parser.buffer, parser.buffer_pos+2)) + + // If it is the leading octet, determine the length of the UTF-8 sequence. + if w == 1024 { + w = width(octet) + if w == 0 { + return yaml_parser_set_scanner_tag_error(parser, directive, + start_mark, "found an incorrect leading UTF-8 octet") + } + } else { + // Check if the trailing octet is correct. + if octet&0xC0 != 0x80 { + return yaml_parser_set_scanner_tag_error(parser, directive, + start_mark, "found an incorrect trailing UTF-8 octet") + } + } + + // Copy the octet and move the pointers. + *s = append(*s, octet) + skip(parser) + skip(parser) + skip(parser) + w-- + } + return true +} + +// Scan a block scalar. +func yaml_parser_scan_block_scalar(parser *yaml_parser_t, token *yaml_token_t, literal bool) bool { + // Eat the indicator '|' or '>'. + start_mark := parser.mark + skip(parser) + + // Scan the additional block scalar indicators. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + + // Check for a chomping indicator. + var chomping, increment int + if parser.buffer[parser.buffer_pos] == '+' || parser.buffer[parser.buffer_pos] == '-' { + // Set the chomping method and eat the indicator. + if parser.buffer[parser.buffer_pos] == '+' { + chomping = +1 + } else { + chomping = -1 + } + skip(parser) + + // Check for an indentation indicator. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + if is_digit(parser.buffer, parser.buffer_pos) { + // Check that the indentation is greater than 0. + if parser.buffer[parser.buffer_pos] == '0' { + yaml_parser_set_scanner_error(parser, "while scanning a block scalar", + start_mark, "found an indentation indicator equal to 0") + return false + } + + // Get the indentation level and eat the indicator. + increment = as_digit(parser.buffer, parser.buffer_pos) + skip(parser) + } + + } else if is_digit(parser.buffer, parser.buffer_pos) { + // Do the same as above, but in the opposite order. + + if parser.buffer[parser.buffer_pos] == '0' { + yaml_parser_set_scanner_error(parser, "while scanning a block scalar", + start_mark, "found an indentation indicator equal to 0") + return false + } + increment = as_digit(parser.buffer, parser.buffer_pos) + skip(parser) + + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + if parser.buffer[parser.buffer_pos] == '+' || parser.buffer[parser.buffer_pos] == '-' { + if parser.buffer[parser.buffer_pos] == '+' { + chomping = +1 + } else { + chomping = -1 + } + skip(parser) + } + } + + // Eat whitespaces and comments to the end of the line. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + for is_blank(parser.buffer, parser.buffer_pos) { + skip(parser) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + if parser.buffer[parser.buffer_pos] == '#' { + for !is_breakz(parser.buffer, parser.buffer_pos) { + skip(parser) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + } + + // Check if we are at the end of the line. + if !is_breakz(parser.buffer, parser.buffer_pos) { + yaml_parser_set_scanner_error(parser, "while scanning a block scalar", + start_mark, "did not find expected comment or line break") + return false + } + + // Eat a line break. + if is_break(parser.buffer, parser.buffer_pos) { + if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { + return false + } + skip_line(parser) + } + + end_mark := parser.mark + + // Set the indentation level if it was specified. + var indent int + if increment > 0 { + if parser.indent >= 0 { + indent = parser.indent + increment + } else { + indent = increment + } + } + + // Scan the leading line breaks and determine the indentation level if needed. + var s, leading_break, trailing_breaks []byte + if !yaml_parser_scan_block_scalar_breaks(parser, &indent, &trailing_breaks, start_mark, &end_mark) { + return false + } + + // Scan the block scalar content. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + var leading_blank, trailing_blank bool + for parser.mark.column == indent && !is_z(parser.buffer, parser.buffer_pos) { + // We are at the beginning of a non-empty line. + + // Is it a trailing whitespace? + trailing_blank = is_blank(parser.buffer, parser.buffer_pos) + + // Check if we need to fold the leading line break. + if !literal && !leading_blank && !trailing_blank && len(leading_break) > 0 && leading_break[0] == '\n' { + // Do we need to join the lines by space? + if len(trailing_breaks) == 0 { + s = append(s, ' ') + } + } else { + s = append(s, leading_break...) + } + leading_break = leading_break[:0] + + // Append the remaining line breaks. + s = append(s, trailing_breaks...) + trailing_breaks = trailing_breaks[:0] + + // Is it a leading whitespace? + leading_blank = is_blank(parser.buffer, parser.buffer_pos) + + // Consume the current line. + for !is_breakz(parser.buffer, parser.buffer_pos) { + s = read(parser, s) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + + // Consume the line break. + if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { + return false + } + + leading_break = read_line(parser, leading_break) + + // Eat the following indentation spaces and line breaks. + if !yaml_parser_scan_block_scalar_breaks(parser, &indent, &trailing_breaks, start_mark, &end_mark) { + return false + } + } + + // Chomp the tail. + if chomping != -1 { + s = append(s, leading_break...) + } + if chomping == 1 { + s = append(s, trailing_breaks...) + } + + // Create a token. + *token = yaml_token_t{ + typ: yaml_SCALAR_TOKEN, + start_mark: start_mark, + end_mark: end_mark, + value: s, + style: yaml_LITERAL_SCALAR_STYLE, + } + if !literal { + token.style = yaml_FOLDED_SCALAR_STYLE + } + return true +} + +// Scan indentation spaces and line breaks for a block scalar. Determine the +// indentation level if needed. +func yaml_parser_scan_block_scalar_breaks(parser *yaml_parser_t, indent *int, breaks *[]byte, start_mark yaml_mark_t, end_mark *yaml_mark_t) bool { + *end_mark = parser.mark + + // Eat the indentation spaces and line breaks. + max_indent := 0 + for { + // Eat the indentation spaces. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + for (*indent == 0 || parser.mark.column < *indent) && is_space(parser.buffer, parser.buffer_pos) { + skip(parser) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + if parser.mark.column > max_indent { + max_indent = parser.mark.column + } + + // Check for a tab character messing the indentation. + if (*indent == 0 || parser.mark.column < *indent) && is_tab(parser.buffer, parser.buffer_pos) { + return yaml_parser_set_scanner_error(parser, "while scanning a block scalar", + start_mark, "found a tab character where an indentation space is expected") + } + + // Have we found a non-empty line? + if !is_break(parser.buffer, parser.buffer_pos) { + break + } + + // Consume the line break. + if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { + return false + } + // [Go] Should really be returning breaks instead. + *breaks = read_line(parser, *breaks) + *end_mark = parser.mark + } + + // Determine the indentation level if needed. + if *indent == 0 { + *indent = max_indent + if *indent < parser.indent+1 { + *indent = parser.indent + 1 + } + if *indent < 1 { + *indent = 1 + } + } + return true +} + +// Scan a quoted scalar. +func yaml_parser_scan_flow_scalar(parser *yaml_parser_t, token *yaml_token_t, single bool) bool { + // Eat the left quote. + start_mark := parser.mark + skip(parser) + + // Consume the content of the quoted scalar. + var s, leading_break, trailing_breaks, whitespaces []byte + for { + // Check that there are no document indicators at the beginning of the line. + if parser.unread < 4 && !yaml_parser_update_buffer(parser, 4) { + return false + } + + if parser.mark.column == 0 && + ((parser.buffer[parser.buffer_pos+0] == '-' && + parser.buffer[parser.buffer_pos+1] == '-' && + parser.buffer[parser.buffer_pos+2] == '-') || + (parser.buffer[parser.buffer_pos+0] == '.' && + parser.buffer[parser.buffer_pos+1] == '.' && + parser.buffer[parser.buffer_pos+2] == '.')) && + is_blankz(parser.buffer, parser.buffer_pos+3) { + yaml_parser_set_scanner_error(parser, "while scanning a quoted scalar", + start_mark, "found unexpected document indicator") + return false + } + + // Check for EOF. + if is_z(parser.buffer, parser.buffer_pos) { + yaml_parser_set_scanner_error(parser, "while scanning a quoted scalar", + start_mark, "found unexpected end of stream") + return false + } + + // Consume non-blank characters. + leading_blanks := false + for !is_blankz(parser.buffer, parser.buffer_pos) { + if single && parser.buffer[parser.buffer_pos] == '\'' && parser.buffer[parser.buffer_pos+1] == '\'' { + // Is is an escaped single quote. + s = append(s, '\'') + skip(parser) + skip(parser) + + } else if single && parser.buffer[parser.buffer_pos] == '\'' { + // It is a right single quote. + break + } else if !single && parser.buffer[parser.buffer_pos] == '"' { + // It is a right double quote. + break + + } else if !single && parser.buffer[parser.buffer_pos] == '\\' && is_break(parser.buffer, parser.buffer_pos+1) { + // It is an escaped line break. + if parser.unread < 3 && !yaml_parser_update_buffer(parser, 3) { + return false + } + skip(parser) + skip_line(parser) + leading_blanks = true + break + + } else if !single && parser.buffer[parser.buffer_pos] == '\\' { + // It is an escape sequence. + code_length := 0 + + // Check the escape character. + switch parser.buffer[parser.buffer_pos+1] { + case '0': + s = append(s, 0) + case 'a': + s = append(s, '\x07') + case 'b': + s = append(s, '\x08') + case 't', '\t': + s = append(s, '\x09') + case 'n': + s = append(s, '\x0A') + case 'v': + s = append(s, '\x0B') + case 'f': + s = append(s, '\x0C') + case 'r': + s = append(s, '\x0D') + case 'e': + s = append(s, '\x1B') + case ' ': + s = append(s, '\x20') + case '"': + s = append(s, '"') + case '\'': + s = append(s, '\'') + case '\\': + s = append(s, '\\') + case 'N': // NEL (#x85) + s = append(s, '\xC2') + s = append(s, '\x85') + case '_': // #xA0 + s = append(s, '\xC2') + s = append(s, '\xA0') + case 'L': // LS (#x2028) + s = append(s, '\xE2') + s = append(s, '\x80') + s = append(s, '\xA8') + case 'P': // PS (#x2029) + s = append(s, '\xE2') + s = append(s, '\x80') + s = append(s, '\xA9') + case 'x': + code_length = 2 + case 'u': + code_length = 4 + case 'U': + code_length = 8 + default: + yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar", + start_mark, "found unknown escape character") + return false + } + + skip(parser) + skip(parser) + + // Consume an arbitrary escape code. + if code_length > 0 { + var value int + + // Scan the character value. + if parser.unread < code_length && !yaml_parser_update_buffer(parser, code_length) { + return false + } + for k := 0; k < code_length; k++ { + if !is_hex(parser.buffer, parser.buffer_pos+k) { + yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar", + start_mark, "did not find expected hexdecimal number") + return false + } + value = (value << 4) + as_hex(parser.buffer, parser.buffer_pos+k) + } + + // Check the value and write the character. + if (value >= 0xD800 && value <= 0xDFFF) || value > 0x10FFFF { + yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar", + start_mark, "found invalid Unicode character escape code") + return false + } + if value <= 0x7F { + s = append(s, byte(value)) + } else if value <= 0x7FF { + s = append(s, byte(0xC0+(value>>6))) + s = append(s, byte(0x80+(value&0x3F))) + } else if value <= 0xFFFF { + s = append(s, byte(0xE0+(value>>12))) + s = append(s, byte(0x80+((value>>6)&0x3F))) + s = append(s, byte(0x80+(value&0x3F))) + } else { + s = append(s, byte(0xF0+(value>>18))) + s = append(s, byte(0x80+((value>>12)&0x3F))) + s = append(s, byte(0x80+((value>>6)&0x3F))) + s = append(s, byte(0x80+(value&0x3F))) + } + + // Advance the pointer. + for k := 0; k < code_length; k++ { + skip(parser) + } + } + } else { + // It is a non-escaped non-blank character. + s = read(parser, s) + } + if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { + return false + } + } + + // Check if we are at the end of the scalar. + if single { + if parser.buffer[parser.buffer_pos] == '\'' { + break + } + } else { + if parser.buffer[parser.buffer_pos] == '"' { + break + } + } + + // Consume blank characters. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + + for is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos) { + if is_blank(parser.buffer, parser.buffer_pos) { + // Consume a space or a tab character. + if !leading_blanks { + whitespaces = read(parser, whitespaces) + } else { + skip(parser) + } + } else { + if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { + return false + } + + // Check if it is a first line break. + if !leading_blanks { + whitespaces = whitespaces[:0] + leading_break = read_line(parser, leading_break) + leading_blanks = true + } else { + trailing_breaks = read_line(parser, trailing_breaks) + } + } + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + + // Join the whitespaces or fold line breaks. + if leading_blanks { + // Do we need to fold line breaks? + if len(leading_break) > 0 && leading_break[0] == '\n' { + if len(trailing_breaks) == 0 { + s = append(s, ' ') + } else { + s = append(s, trailing_breaks...) + } + } else { + s = append(s, leading_break...) + s = append(s, trailing_breaks...) + } + trailing_breaks = trailing_breaks[:0] + leading_break = leading_break[:0] + } else { + s = append(s, whitespaces...) + whitespaces = whitespaces[:0] + } + } + + // Eat the right quote. + skip(parser) + end_mark := parser.mark + + // Create a token. + *token = yaml_token_t{ + typ: yaml_SCALAR_TOKEN, + start_mark: start_mark, + end_mark: end_mark, + value: s, + style: yaml_SINGLE_QUOTED_SCALAR_STYLE, + } + if !single { + token.style = yaml_DOUBLE_QUOTED_SCALAR_STYLE + } + return true +} + +// Scan a plain scalar. +func yaml_parser_scan_plain_scalar(parser *yaml_parser_t, token *yaml_token_t) bool { + + var s, leading_break, trailing_breaks, whitespaces []byte + var leading_blanks bool + var indent = parser.indent + 1 + + start_mark := parser.mark + end_mark := parser.mark + + // Consume the content of the plain scalar. + for { + // Check for a document indicator. + if parser.unread < 4 && !yaml_parser_update_buffer(parser, 4) { + return false + } + if parser.mark.column == 0 && + ((parser.buffer[parser.buffer_pos+0] == '-' && + parser.buffer[parser.buffer_pos+1] == '-' && + parser.buffer[parser.buffer_pos+2] == '-') || + (parser.buffer[parser.buffer_pos+0] == '.' && + parser.buffer[parser.buffer_pos+1] == '.' && + parser.buffer[parser.buffer_pos+2] == '.')) && + is_blankz(parser.buffer, parser.buffer_pos+3) { + break + } + + // Check for a comment. + if parser.buffer[parser.buffer_pos] == '#' { + break + } + + // Consume non-blank characters. + for !is_blankz(parser.buffer, parser.buffer_pos) { + + // Check for 'x:x' in the flow context. TODO: Fix the test "spec-08-13". + if parser.flow_level > 0 && + parser.buffer[parser.buffer_pos] == ':' && + !is_blankz(parser.buffer, parser.buffer_pos+1) { + yaml_parser_set_scanner_error(parser, "while scanning a plain scalar", + start_mark, "found unexpected ':'") + return false + } + + // Check for indicators that may end a plain scalar. + if (parser.buffer[parser.buffer_pos] == ':' && is_blankz(parser.buffer, parser.buffer_pos+1)) || + (parser.flow_level > 0 && + (parser.buffer[parser.buffer_pos] == ',' || parser.buffer[parser.buffer_pos] == ':' || + parser.buffer[parser.buffer_pos] == '?' || parser.buffer[parser.buffer_pos] == '[' || + parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '{' || + parser.buffer[parser.buffer_pos] == '}')) { + break + } + + // Check if we need to join whitespaces and breaks. + if leading_blanks || len(whitespaces) > 0 { + if leading_blanks { + // Do we need to fold line breaks? + if leading_break[0] == '\n' { + if len(trailing_breaks) == 0 { + s = append(s, ' ') + } else { + s = append(s, trailing_breaks...) + } + } else { + s = append(s, leading_break...) + s = append(s, trailing_breaks...) + } + trailing_breaks = trailing_breaks[:0] + leading_break = leading_break[:0] + leading_blanks = false + } else { + s = append(s, whitespaces...) + whitespaces = whitespaces[:0] + } + } + + // Copy the character. + s = read(parser, s) + + end_mark = parser.mark + if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { + return false + } + } + + // Is it the end? + if !(is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos)) { + break + } + + // Consume blank characters. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + + for is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos) { + if is_blank(parser.buffer, parser.buffer_pos) { + + // Check for tab character that abuse indentation. + if leading_blanks && parser.mark.column < indent && is_tab(parser.buffer, parser.buffer_pos) { + yaml_parser_set_scanner_error(parser, "while scanning a plain scalar", + start_mark, "found a tab character that violate indentation") + return false + } + + // Consume a space or a tab character. + if !leading_blanks { + whitespaces = read(parser, whitespaces) + } else { + skip(parser) + } + } else { + if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { + return false + } + + // Check if it is a first line break. + if !leading_blanks { + whitespaces = whitespaces[:0] + leading_break = read_line(parser, leading_break) + leading_blanks = true + } else { + trailing_breaks = read_line(parser, trailing_breaks) + } + } + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + + // Check indentation level. + if parser.flow_level == 0 && parser.mark.column < indent { + break + } + } + + // Create a token. + *token = yaml_token_t{ + typ: yaml_SCALAR_TOKEN, + start_mark: start_mark, + end_mark: end_mark, + value: s, + style: yaml_PLAIN_SCALAR_STYLE, + } + + // Note that we change the 'simple_key_allowed' flag. + if leading_blanks { + parser.simple_key_allowed = true + } + return true +} diff --git a/vendor/github.com/go-yaml/yaml/sorter.go b/vendor/github.com/go-yaml/yaml/sorter.go new file mode 100644 index 00000000..5958822f --- /dev/null +++ b/vendor/github.com/go-yaml/yaml/sorter.go @@ -0,0 +1,104 @@ +package yaml + +import ( + "reflect" + "unicode" +) + +type keyList []reflect.Value + +func (l keyList) Len() int { return len(l) } +func (l keyList) Swap(i, j int) { l[i], l[j] = l[j], l[i] } +func (l keyList) Less(i, j int) bool { + a := l[i] + b := l[j] + ak := a.Kind() + bk := b.Kind() + for (ak == reflect.Interface || ak == reflect.Ptr) && !a.IsNil() { + a = a.Elem() + ak = a.Kind() + } + for (bk == reflect.Interface || bk == reflect.Ptr) && !b.IsNil() { + b = b.Elem() + bk = b.Kind() + } + af, aok := keyFloat(a) + bf, bok := keyFloat(b) + if aok && bok { + if af != bf { + return af < bf + } + if ak != bk { + return ak < bk + } + return numLess(a, b) + } + if ak != reflect.String || bk != reflect.String { + return ak < bk + } + ar, br := []rune(a.String()), []rune(b.String()) + for i := 0; i < len(ar) && i < len(br); i++ { + if ar[i] == br[i] { + continue + } + al := unicode.IsLetter(ar[i]) + bl := unicode.IsLetter(br[i]) + if al && bl { + return ar[i] < br[i] + } + if al || bl { + return bl + } + var ai, bi int + var an, bn int64 + for ai = i; ai < len(ar) && unicode.IsDigit(ar[ai]); ai++ { + an = an*10 + int64(ar[ai]-'0') + } + for bi = i; bi < len(br) && unicode.IsDigit(br[bi]); bi++ { + bn = bn*10 + int64(br[bi]-'0') + } + if an != bn { + return an < bn + } + if ai != bi { + return ai < bi + } + return ar[i] < br[i] + } + return len(ar) < len(br) +} + +// keyFloat returns a float value for v if it is a number/bool +// and whether it is a number/bool or not. +func keyFloat(v reflect.Value) (f float64, ok bool) { + switch v.Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return float64(v.Int()), true + case reflect.Float32, reflect.Float64: + return v.Float(), true + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return float64(v.Uint()), true + case reflect.Bool: + if v.Bool() { + return 1, true + } + return 0, true + } + return 0, false +} + +// numLess returns whether a < b. +// a and b must necessarily have the same kind. +func numLess(a, b reflect.Value) bool { + switch a.Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return a.Int() < b.Int() + case reflect.Float32, reflect.Float64: + return a.Float() < b.Float() + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return a.Uint() < b.Uint() + case reflect.Bool: + return !a.Bool() && b.Bool() + } + panic("not a number") +} diff --git a/vendor/github.com/go-yaml/yaml/suite_test.go b/vendor/github.com/go-yaml/yaml/suite_test.go new file mode 100644 index 00000000..c5cf1ed4 --- /dev/null +++ b/vendor/github.com/go-yaml/yaml/suite_test.go @@ -0,0 +1,12 @@ +package yaml_test + +import ( + . "gopkg.in/check.v1" + "testing" +) + +func Test(t *testing.T) { TestingT(t) } + +type S struct{} + +var _ = Suite(&S{}) diff --git a/vendor/github.com/go-yaml/yaml/writerc.go b/vendor/github.com/go-yaml/yaml/writerc.go new file mode 100644 index 00000000..190362f2 --- /dev/null +++ b/vendor/github.com/go-yaml/yaml/writerc.go @@ -0,0 +1,89 @@ +package yaml + +// Set the writer error and return false. +func yaml_emitter_set_writer_error(emitter *yaml_emitter_t, problem string) bool { + emitter.error = yaml_WRITER_ERROR + emitter.problem = problem + return false +} + +// Flush the output buffer. +func yaml_emitter_flush(emitter *yaml_emitter_t) bool { + if emitter.write_handler == nil { + panic("write handler not set") + } + + // Check if the buffer is empty. + if emitter.buffer_pos == 0 { + return true + } + + // If the output encoding is UTF-8, we don't need to recode the buffer. + if emitter.encoding == yaml_UTF8_ENCODING { + if err := emitter.write_handler(emitter, emitter.buffer[:emitter.buffer_pos]); err != nil { + return yaml_emitter_set_writer_error(emitter, "write error: "+err.Error()) + } + emitter.buffer_pos = 0 + return true + } + + // Recode the buffer into the raw buffer. + var low, high int + if emitter.encoding == yaml_UTF16LE_ENCODING { + low, high = 0, 1 + } else { + high, low = 1, 0 + } + + pos := 0 + for pos < emitter.buffer_pos { + // See the "reader.c" code for more details on UTF-8 encoding. Note + // that we assume that the buffer contains a valid UTF-8 sequence. + + // Read the next UTF-8 character. + octet := emitter.buffer[pos] + + var w int + var value rune + switch { + case octet&0x80 == 0x00: + w, value = 1, rune(octet&0x7F) + case octet&0xE0 == 0xC0: + w, value = 2, rune(octet&0x1F) + case octet&0xF0 == 0xE0: + w, value = 3, rune(octet&0x0F) + case octet&0xF8 == 0xF0: + w, value = 4, rune(octet&0x07) + } + for k := 1; k < w; k++ { + octet = emitter.buffer[pos+k] + value = (value << 6) + (rune(octet) & 0x3F) + } + pos += w + + // Write the character. + if value < 0x10000 { + var b [2]byte + b[high] = byte(value >> 8) + b[low] = byte(value & 0xFF) + emitter.raw_buffer = append(emitter.raw_buffer, b[0], b[1]) + } else { + // Write the character using a surrogate pair (check "reader.c"). + var b [4]byte + value -= 0x10000 + b[high] = byte(0xD8 + (value >> 18)) + b[low] = byte((value >> 10) & 0xFF) + b[high+2] = byte(0xDC + ((value >> 8) & 0xFF)) + b[low+2] = byte(value & 0xFF) + emitter.raw_buffer = append(emitter.raw_buffer, b[0], b[1], b[2], b[3]) + } + } + + // Write the raw buffer. + if err := emitter.write_handler(emitter, emitter.raw_buffer); err != nil { + return yaml_emitter_set_writer_error(emitter, "write error: "+err.Error()) + } + emitter.buffer_pos = 0 + emitter.raw_buffer = emitter.raw_buffer[:0] + return true +} diff --git a/vendor/github.com/go-yaml/yaml/yaml.go b/vendor/github.com/go-yaml/yaml/yaml.go new file mode 100644 index 00000000..5e3c2dae --- /dev/null +++ b/vendor/github.com/go-yaml/yaml/yaml.go @@ -0,0 +1,357 @@ +// Package yaml implements YAML support for the Go language. +// +// Source code and other details for the project are available at GitHub: +// +// https://github.com/go-yaml/yaml +// +package yaml + +import ( + "errors" + "fmt" + "reflect" + "strings" + "sync" +) + +// MapSlice encodes and decodes as a YAML map. +// The order of keys is preserved when encoding and decoding. +type MapSlice []MapItem + +// MapItem is an item in a MapSlice. +type MapItem struct { + Key, Value interface{} +} + +// The Unmarshaler interface may be implemented by types to customize their +// behavior when being unmarshaled from a YAML document. The UnmarshalYAML +// method receives a function that may be called to unmarshal the original +// YAML value into a field or variable. It is safe to call the unmarshal +// function parameter more than once if necessary. +type Unmarshaler interface { + UnmarshalYAML(unmarshal func(interface{}) error) error +} + +// The Marshaler interface may be implemented by types to customize their +// behavior when being marshaled into a YAML document. The returned value +// is marshaled in place of the original value implementing Marshaler. +// +// If an error is returned by MarshalYAML, the marshaling procedure stops +// and returns with the provided error. +type Marshaler interface { + MarshalYAML() (interface{}, error) +} + +// Unmarshal decodes the first document found within the in byte slice +// and assigns decoded values into the out value. +// +// Maps and pointers (to a struct, string, int, etc) are accepted as out +// values. If an internal pointer within a struct is not initialized, +// the yaml package will initialize it if necessary for unmarshalling +// the provided data. The out parameter must not be nil. +// +// The type of the decoded values should be compatible with the respective +// values in out. If one or more values cannot be decoded due to a type +// mismatches, decoding continues partially until the end of the YAML +// content, and a *yaml.TypeError is returned with details for all +// missed values. +// +// Struct fields are only unmarshalled if they are exported (have an +// upper case first letter), and are unmarshalled using the field name +// lowercased as the default key. Custom keys may be defined via the +// "yaml" name in the field tag: the content preceding the first comma +// is used as the key, and the following comma-separated options are +// used to tweak the marshalling process (see Marshal). +// Conflicting names result in a runtime error. +// +// For example: +// +// type T struct { +// F int `yaml:"a,omitempty"` +// B int +// } +// var t T +// yaml.Unmarshal([]byte("a: 1\nb: 2"), &t) +// +// See the documentation of Marshal for the format of tags and a list of +// supported tag options. +// +func Unmarshal(in []byte, out interface{}) (err error) { + return unmarshal(in, out, false) +} + +// UnmarshalStrict is like Unmarshal except that any fields that are found +// in the data that do not have corresponding struct members will result in +// an error. +func UnmarshalStrict(in []byte, out interface{}) (err error) { + return unmarshal(in, out, true) +} + +func unmarshal(in []byte, out interface{}, strict bool) (err error) { + defer handleErr(&err) + d := newDecoder(strict) + p := newParser(in) + defer p.destroy() + node := p.parse() + if node != nil { + v := reflect.ValueOf(out) + if v.Kind() == reflect.Ptr && !v.IsNil() { + v = v.Elem() + } + d.unmarshal(node, v) + } + if len(d.terrors) > 0 { + return &TypeError{d.terrors} + } + return nil +} + +// Marshal serializes the value provided into a YAML document. The structure +// of the generated document will reflect the structure of the value itself. +// Maps and pointers (to struct, string, int, etc) are accepted as the in value. +// +// Struct fields are only unmarshalled if they are exported (have an upper case +// first letter), and are unmarshalled using the field name lowercased as the +// default key. Custom keys may be defined via the "yaml" name in the field +// tag: the content preceding the first comma is used as the key, and the +// following comma-separated options are used to tweak the marshalling process. +// Conflicting names result in a runtime error. +// +// The field tag format accepted is: +// +// `(...) yaml:"[][,[,]]" (...)` +// +// The following flags are currently supported: +// +// omitempty Only include the field if it's not set to the zero +// value for the type or to empty slices or maps. +// Does not apply to zero valued structs. +// +// flow Marshal using a flow style (useful for structs, +// sequences and maps). +// +// inline Inline the field, which must be a struct or a map, +// causing all of its fields or keys to be processed as if +// they were part of the outer struct. For maps, keys must +// not conflict with the yaml keys of other struct fields. +// +// In addition, if the key is "-", the field is ignored. +// +// For example: +// +// type T struct { +// F int `yaml:"a,omitempty"` +// B int +// } +// yaml.Marshal(&T{B: 2}) // Returns "b: 2\n" +// yaml.Marshal(&T{F: 1}} // Returns "a: 1\nb: 0\n" +// +func Marshal(in interface{}) (out []byte, err error) { + defer handleErr(&err) + e := newEncoder() + defer e.destroy() + e.marshal("", reflect.ValueOf(in)) + e.finish() + out = e.out + return +} + +func handleErr(err *error) { + if v := recover(); v != nil { + if e, ok := v.(yamlError); ok { + *err = e.err + } else { + panic(v) + } + } +} + +type yamlError struct { + err error +} + +func fail(err error) { + panic(yamlError{err}) +} + +func failf(format string, args ...interface{}) { + panic(yamlError{fmt.Errorf("yaml: "+format, args...)}) +} + +// A TypeError is returned by Unmarshal when one or more fields in +// the YAML document cannot be properly decoded into the requested +// types. When this error is returned, the value is still +// unmarshaled partially. +type TypeError struct { + Errors []string +} + +func (e *TypeError) Error() string { + return fmt.Sprintf("yaml: unmarshal errors:\n %s", strings.Join(e.Errors, "\n ")) +} + +// -------------------------------------------------------------------------- +// Maintain a mapping of keys to structure field indexes + +// The code in this section was copied from mgo/bson. + +// structInfo holds details for the serialization of fields of +// a given struct. +type structInfo struct { + FieldsMap map[string]fieldInfo + FieldsList []fieldInfo + + // InlineMap is the number of the field in the struct that + // contains an ,inline map, or -1 if there's none. + InlineMap int +} + +type fieldInfo struct { + Key string + Num int + OmitEmpty bool + Flow bool + + // Inline holds the field index if the field is part of an inlined struct. + Inline []int +} + +var structMap = make(map[reflect.Type]*structInfo) +var fieldMapMutex sync.RWMutex + +func getStructInfo(st reflect.Type) (*structInfo, error) { + fieldMapMutex.RLock() + sinfo, found := structMap[st] + fieldMapMutex.RUnlock() + if found { + return sinfo, nil + } + + n := st.NumField() + fieldsMap := make(map[string]fieldInfo) + fieldsList := make([]fieldInfo, 0, n) + inlineMap := -1 + for i := 0; i != n; i++ { + field := st.Field(i) + if field.PkgPath != "" && !field.Anonymous { + continue // Private field + } + + info := fieldInfo{Num: i} + + tag := field.Tag.Get("yaml") + if tag == "" && strings.Index(string(field.Tag), ":") < 0 { + tag = string(field.Tag) + } + if tag == "-" { + continue + } + + inline := false + fields := strings.Split(tag, ",") + if len(fields) > 1 { + for _, flag := range fields[1:] { + switch flag { + case "omitempty": + info.OmitEmpty = true + case "flow": + info.Flow = true + case "inline": + inline = true + default: + return nil, errors.New(fmt.Sprintf("Unsupported flag %q in tag %q of type %s", flag, tag, st)) + } + } + tag = fields[0] + } + + if inline { + switch field.Type.Kind() { + case reflect.Map: + if inlineMap >= 0 { + return nil, errors.New("Multiple ,inline maps in struct " + st.String()) + } + if field.Type.Key() != reflect.TypeOf("") { + return nil, errors.New("Option ,inline needs a map with string keys in struct " + st.String()) + } + inlineMap = info.Num + case reflect.Struct: + sinfo, err := getStructInfo(field.Type) + if err != nil { + return nil, err + } + for _, finfo := range sinfo.FieldsList { + if _, found := fieldsMap[finfo.Key]; found { + msg := "Duplicated key '" + finfo.Key + "' in struct " + st.String() + return nil, errors.New(msg) + } + if finfo.Inline == nil { + finfo.Inline = []int{i, finfo.Num} + } else { + finfo.Inline = append([]int{i}, finfo.Inline...) + } + fieldsMap[finfo.Key] = finfo + fieldsList = append(fieldsList, finfo) + } + default: + //return nil, errors.New("Option ,inline needs a struct value or map field") + return nil, errors.New("Option ,inline needs a struct value field") + } + continue + } + + if tag != "" { + info.Key = tag + } else { + info.Key = strings.ToLower(field.Name) + } + + if _, found = fieldsMap[info.Key]; found { + msg := "Duplicated key '" + info.Key + "' in struct " + st.String() + return nil, errors.New(msg) + } + + fieldsList = append(fieldsList, info) + fieldsMap[info.Key] = info + } + + sinfo = &structInfo{fieldsMap, fieldsList, inlineMap} + + fieldMapMutex.Lock() + structMap[st] = sinfo + fieldMapMutex.Unlock() + return sinfo, nil +} + +func isZero(v reflect.Value) bool { + switch v.Kind() { + case reflect.String: + return len(v.String()) == 0 + case reflect.Interface, reflect.Ptr: + return v.IsNil() + case reflect.Slice: + return v.Len() == 0 + case reflect.Map: + return v.Len() == 0 + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return v.Int() == 0 + case reflect.Float32, reflect.Float64: + return v.Float() == 0 + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return v.Uint() == 0 + case reflect.Bool: + return !v.Bool() + case reflect.Struct: + vt := v.Type() + for i := v.NumField() - 1; i >= 0; i-- { + if vt.Field(i).PkgPath != "" { + continue // Private field + } + if !isZero(v.Field(i)) { + return false + } + } + return true + } + return false +} diff --git a/vendor/github.com/go-yaml/yaml/yamlh.go b/vendor/github.com/go-yaml/yaml/yamlh.go new file mode 100644 index 00000000..3caeca04 --- /dev/null +++ b/vendor/github.com/go-yaml/yaml/yamlh.go @@ -0,0 +1,716 @@ +package yaml + +import ( + "io" +) + +// The version directive data. +type yaml_version_directive_t struct { + major int8 // The major version number. + minor int8 // The minor version number. +} + +// The tag directive data. +type yaml_tag_directive_t struct { + handle []byte // The tag handle. + prefix []byte // The tag prefix. +} + +type yaml_encoding_t int + +// The stream encoding. +const ( + // Let the parser choose the encoding. + yaml_ANY_ENCODING yaml_encoding_t = iota + + yaml_UTF8_ENCODING // The default UTF-8 encoding. + yaml_UTF16LE_ENCODING // The UTF-16-LE encoding with BOM. + yaml_UTF16BE_ENCODING // The UTF-16-BE encoding with BOM. +) + +type yaml_break_t int + +// Line break types. +const ( + // Let the parser choose the break type. + yaml_ANY_BREAK yaml_break_t = iota + + yaml_CR_BREAK // Use CR for line breaks (Mac style). + yaml_LN_BREAK // Use LN for line breaks (Unix style). + yaml_CRLN_BREAK // Use CR LN for line breaks (DOS style). +) + +type yaml_error_type_t int + +// Many bad things could happen with the parser and emitter. +const ( + // No error is produced. + yaml_NO_ERROR yaml_error_type_t = iota + + yaml_MEMORY_ERROR // Cannot allocate or reallocate a block of memory. + yaml_READER_ERROR // Cannot read or decode the input stream. + yaml_SCANNER_ERROR // Cannot scan the input stream. + yaml_PARSER_ERROR // Cannot parse the input stream. + yaml_COMPOSER_ERROR // Cannot compose a YAML document. + yaml_WRITER_ERROR // Cannot write to the output stream. + yaml_EMITTER_ERROR // Cannot emit a YAML stream. +) + +// The pointer position. +type yaml_mark_t struct { + index int // The position index. + line int // The position line. + column int // The position column. +} + +// Node Styles + +type yaml_style_t int8 + +type yaml_scalar_style_t yaml_style_t + +// Scalar styles. +const ( + // Let the emitter choose the style. + yaml_ANY_SCALAR_STYLE yaml_scalar_style_t = iota + + yaml_PLAIN_SCALAR_STYLE // The plain scalar style. + yaml_SINGLE_QUOTED_SCALAR_STYLE // The single-quoted scalar style. + yaml_DOUBLE_QUOTED_SCALAR_STYLE // The double-quoted scalar style. + yaml_LITERAL_SCALAR_STYLE // The literal scalar style. + yaml_FOLDED_SCALAR_STYLE // The folded scalar style. +) + +type yaml_sequence_style_t yaml_style_t + +// Sequence styles. +const ( + // Let the emitter choose the style. + yaml_ANY_SEQUENCE_STYLE yaml_sequence_style_t = iota + + yaml_BLOCK_SEQUENCE_STYLE // The block sequence style. + yaml_FLOW_SEQUENCE_STYLE // The flow sequence style. +) + +type yaml_mapping_style_t yaml_style_t + +// Mapping styles. +const ( + // Let the emitter choose the style. + yaml_ANY_MAPPING_STYLE yaml_mapping_style_t = iota + + yaml_BLOCK_MAPPING_STYLE // The block mapping style. + yaml_FLOW_MAPPING_STYLE // The flow mapping style. +) + +// Tokens + +type yaml_token_type_t int + +// Token types. +const ( + // An empty token. + yaml_NO_TOKEN yaml_token_type_t = iota + + yaml_STREAM_START_TOKEN // A STREAM-START token. + yaml_STREAM_END_TOKEN // A STREAM-END token. + + yaml_VERSION_DIRECTIVE_TOKEN // A VERSION-DIRECTIVE token. + yaml_TAG_DIRECTIVE_TOKEN // A TAG-DIRECTIVE token. + yaml_DOCUMENT_START_TOKEN // A DOCUMENT-START token. + yaml_DOCUMENT_END_TOKEN // A DOCUMENT-END token. + + yaml_BLOCK_SEQUENCE_START_TOKEN // A BLOCK-SEQUENCE-START token. + yaml_BLOCK_MAPPING_START_TOKEN // A BLOCK-SEQUENCE-END token. + yaml_BLOCK_END_TOKEN // A BLOCK-END token. + + yaml_FLOW_SEQUENCE_START_TOKEN // A FLOW-SEQUENCE-START token. + yaml_FLOW_SEQUENCE_END_TOKEN // A FLOW-SEQUENCE-END token. + yaml_FLOW_MAPPING_START_TOKEN // A FLOW-MAPPING-START token. + yaml_FLOW_MAPPING_END_TOKEN // A FLOW-MAPPING-END token. + + yaml_BLOCK_ENTRY_TOKEN // A BLOCK-ENTRY token. + yaml_FLOW_ENTRY_TOKEN // A FLOW-ENTRY token. + yaml_KEY_TOKEN // A KEY token. + yaml_VALUE_TOKEN // A VALUE token. + + yaml_ALIAS_TOKEN // An ALIAS token. + yaml_ANCHOR_TOKEN // An ANCHOR token. + yaml_TAG_TOKEN // A TAG token. + yaml_SCALAR_TOKEN // A SCALAR token. +) + +func (tt yaml_token_type_t) String() string { + switch tt { + case yaml_NO_TOKEN: + return "yaml_NO_TOKEN" + case yaml_STREAM_START_TOKEN: + return "yaml_STREAM_START_TOKEN" + case yaml_STREAM_END_TOKEN: + return "yaml_STREAM_END_TOKEN" + case yaml_VERSION_DIRECTIVE_TOKEN: + return "yaml_VERSION_DIRECTIVE_TOKEN" + case yaml_TAG_DIRECTIVE_TOKEN: + return "yaml_TAG_DIRECTIVE_TOKEN" + case yaml_DOCUMENT_START_TOKEN: + return "yaml_DOCUMENT_START_TOKEN" + case yaml_DOCUMENT_END_TOKEN: + return "yaml_DOCUMENT_END_TOKEN" + case yaml_BLOCK_SEQUENCE_START_TOKEN: + return "yaml_BLOCK_SEQUENCE_START_TOKEN" + case yaml_BLOCK_MAPPING_START_TOKEN: + return "yaml_BLOCK_MAPPING_START_TOKEN" + case yaml_BLOCK_END_TOKEN: + return "yaml_BLOCK_END_TOKEN" + case yaml_FLOW_SEQUENCE_START_TOKEN: + return "yaml_FLOW_SEQUENCE_START_TOKEN" + case yaml_FLOW_SEQUENCE_END_TOKEN: + return "yaml_FLOW_SEQUENCE_END_TOKEN" + case yaml_FLOW_MAPPING_START_TOKEN: + return "yaml_FLOW_MAPPING_START_TOKEN" + case yaml_FLOW_MAPPING_END_TOKEN: + return "yaml_FLOW_MAPPING_END_TOKEN" + case yaml_BLOCK_ENTRY_TOKEN: + return "yaml_BLOCK_ENTRY_TOKEN" + case yaml_FLOW_ENTRY_TOKEN: + return "yaml_FLOW_ENTRY_TOKEN" + case yaml_KEY_TOKEN: + return "yaml_KEY_TOKEN" + case yaml_VALUE_TOKEN: + return "yaml_VALUE_TOKEN" + case yaml_ALIAS_TOKEN: + return "yaml_ALIAS_TOKEN" + case yaml_ANCHOR_TOKEN: + return "yaml_ANCHOR_TOKEN" + case yaml_TAG_TOKEN: + return "yaml_TAG_TOKEN" + case yaml_SCALAR_TOKEN: + return "yaml_SCALAR_TOKEN" + } + return "" +} + +// The token structure. +type yaml_token_t struct { + // The token type. + typ yaml_token_type_t + + // The start/end of the token. + start_mark, end_mark yaml_mark_t + + // The stream encoding (for yaml_STREAM_START_TOKEN). + encoding yaml_encoding_t + + // The alias/anchor/scalar value or tag/tag directive handle + // (for yaml_ALIAS_TOKEN, yaml_ANCHOR_TOKEN, yaml_SCALAR_TOKEN, yaml_TAG_TOKEN, yaml_TAG_DIRECTIVE_TOKEN). + value []byte + + // The tag suffix (for yaml_TAG_TOKEN). + suffix []byte + + // The tag directive prefix (for yaml_TAG_DIRECTIVE_TOKEN). + prefix []byte + + // The scalar style (for yaml_SCALAR_TOKEN). + style yaml_scalar_style_t + + // The version directive major/minor (for yaml_VERSION_DIRECTIVE_TOKEN). + major, minor int8 +} + +// Events + +type yaml_event_type_t int8 + +// Event types. +const ( + // An empty event. + yaml_NO_EVENT yaml_event_type_t = iota + + yaml_STREAM_START_EVENT // A STREAM-START event. + yaml_STREAM_END_EVENT // A STREAM-END event. + yaml_DOCUMENT_START_EVENT // A DOCUMENT-START event. + yaml_DOCUMENT_END_EVENT // A DOCUMENT-END event. + yaml_ALIAS_EVENT // An ALIAS event. + yaml_SCALAR_EVENT // A SCALAR event. + yaml_SEQUENCE_START_EVENT // A SEQUENCE-START event. + yaml_SEQUENCE_END_EVENT // A SEQUENCE-END event. + yaml_MAPPING_START_EVENT // A MAPPING-START event. + yaml_MAPPING_END_EVENT // A MAPPING-END event. +) + +// The event structure. +type yaml_event_t struct { + + // The event type. + typ yaml_event_type_t + + // The start and end of the event. + start_mark, end_mark yaml_mark_t + + // The document encoding (for yaml_STREAM_START_EVENT). + encoding yaml_encoding_t + + // The version directive (for yaml_DOCUMENT_START_EVENT). + version_directive *yaml_version_directive_t + + // The list of tag directives (for yaml_DOCUMENT_START_EVENT). + tag_directives []yaml_tag_directive_t + + // The anchor (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT, yaml_ALIAS_EVENT). + anchor []byte + + // The tag (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT). + tag []byte + + // The scalar value (for yaml_SCALAR_EVENT). + value []byte + + // Is the document start/end indicator implicit, or the tag optional? + // (for yaml_DOCUMENT_START_EVENT, yaml_DOCUMENT_END_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT, yaml_SCALAR_EVENT). + implicit bool + + // Is the tag optional for any non-plain style? (for yaml_SCALAR_EVENT). + quoted_implicit bool + + // The style (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT). + style yaml_style_t +} + +func (e *yaml_event_t) scalar_style() yaml_scalar_style_t { return yaml_scalar_style_t(e.style) } +func (e *yaml_event_t) sequence_style() yaml_sequence_style_t { return yaml_sequence_style_t(e.style) } +func (e *yaml_event_t) mapping_style() yaml_mapping_style_t { return yaml_mapping_style_t(e.style) } + +// Nodes + +const ( + yaml_NULL_TAG = "tag:yaml.org,2002:null" // The tag !!null with the only possible value: null. + yaml_BOOL_TAG = "tag:yaml.org,2002:bool" // The tag !!bool with the values: true and false. + yaml_STR_TAG = "tag:yaml.org,2002:str" // The tag !!str for string values. + yaml_INT_TAG = "tag:yaml.org,2002:int" // The tag !!int for integer values. + yaml_FLOAT_TAG = "tag:yaml.org,2002:float" // The tag !!float for float values. + yaml_TIMESTAMP_TAG = "tag:yaml.org,2002:timestamp" // The tag !!timestamp for date and time values. + + yaml_SEQ_TAG = "tag:yaml.org,2002:seq" // The tag !!seq is used to denote sequences. + yaml_MAP_TAG = "tag:yaml.org,2002:map" // The tag !!map is used to denote mapping. + + // Not in original libyaml. + yaml_BINARY_TAG = "tag:yaml.org,2002:binary" + yaml_MERGE_TAG = "tag:yaml.org,2002:merge" + + yaml_DEFAULT_SCALAR_TAG = yaml_STR_TAG // The default scalar tag is !!str. + yaml_DEFAULT_SEQUENCE_TAG = yaml_SEQ_TAG // The default sequence tag is !!seq. + yaml_DEFAULT_MAPPING_TAG = yaml_MAP_TAG // The default mapping tag is !!map. +) + +type yaml_node_type_t int + +// Node types. +const ( + // An empty node. + yaml_NO_NODE yaml_node_type_t = iota + + yaml_SCALAR_NODE // A scalar node. + yaml_SEQUENCE_NODE // A sequence node. + yaml_MAPPING_NODE // A mapping node. +) + +// An element of a sequence node. +type yaml_node_item_t int + +// An element of a mapping node. +type yaml_node_pair_t struct { + key int // The key of the element. + value int // The value of the element. +} + +// The node structure. +type yaml_node_t struct { + typ yaml_node_type_t // The node type. + tag []byte // The node tag. + + // The node data. + + // The scalar parameters (for yaml_SCALAR_NODE). + scalar struct { + value []byte // The scalar value. + length int // The length of the scalar value. + style yaml_scalar_style_t // The scalar style. + } + + // The sequence parameters (for YAML_SEQUENCE_NODE). + sequence struct { + items_data []yaml_node_item_t // The stack of sequence items. + style yaml_sequence_style_t // The sequence style. + } + + // The mapping parameters (for yaml_MAPPING_NODE). + mapping struct { + pairs_data []yaml_node_pair_t // The stack of mapping pairs (key, value). + pairs_start *yaml_node_pair_t // The beginning of the stack. + pairs_end *yaml_node_pair_t // The end of the stack. + pairs_top *yaml_node_pair_t // The top of the stack. + style yaml_mapping_style_t // The mapping style. + } + + start_mark yaml_mark_t // The beginning of the node. + end_mark yaml_mark_t // The end of the node. + +} + +// The document structure. +type yaml_document_t struct { + + // The document nodes. + nodes []yaml_node_t + + // The version directive. + version_directive *yaml_version_directive_t + + // The list of tag directives. + tag_directives_data []yaml_tag_directive_t + tag_directives_start int // The beginning of the tag directives list. + tag_directives_end int // The end of the tag directives list. + + start_implicit int // Is the document start indicator implicit? + end_implicit int // Is the document end indicator implicit? + + // The start/end of the document. + start_mark, end_mark yaml_mark_t +} + +// The prototype of a read handler. +// +// The read handler is called when the parser needs to read more bytes from the +// source. The handler should write not more than size bytes to the buffer. +// The number of written bytes should be set to the size_read variable. +// +// [in,out] data A pointer to an application data specified by +// yaml_parser_set_input(). +// [out] buffer The buffer to write the data from the source. +// [in] size The size of the buffer. +// [out] size_read The actual number of bytes read from the source. +// +// On success, the handler should return 1. If the handler failed, +// the returned value should be 0. On EOF, the handler should set the +// size_read to 0 and return 1. +type yaml_read_handler_t func(parser *yaml_parser_t, buffer []byte) (n int, err error) + +// This structure holds information about a potential simple key. +type yaml_simple_key_t struct { + possible bool // Is a simple key possible? + required bool // Is a simple key required? + token_number int // The number of the token. + mark yaml_mark_t // The position mark. +} + +// The states of the parser. +type yaml_parser_state_t int + +const ( + yaml_PARSE_STREAM_START_STATE yaml_parser_state_t = iota + + yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE // Expect the beginning of an implicit document. + yaml_PARSE_DOCUMENT_START_STATE // Expect DOCUMENT-START. + yaml_PARSE_DOCUMENT_CONTENT_STATE // Expect the content of a document. + yaml_PARSE_DOCUMENT_END_STATE // Expect DOCUMENT-END. + yaml_PARSE_BLOCK_NODE_STATE // Expect a block node. + yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE // Expect a block node or indentless sequence. + yaml_PARSE_FLOW_NODE_STATE // Expect a flow node. + yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE // Expect the first entry of a block sequence. + yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE // Expect an entry of a block sequence. + yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE // Expect an entry of an indentless sequence. + yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE // Expect the first key of a block mapping. + yaml_PARSE_BLOCK_MAPPING_KEY_STATE // Expect a block mapping key. + yaml_PARSE_BLOCK_MAPPING_VALUE_STATE // Expect a block mapping value. + yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE // Expect the first entry of a flow sequence. + yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE // Expect an entry of a flow sequence. + yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE // Expect a key of an ordered mapping. + yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE // Expect a value of an ordered mapping. + yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE // Expect the and of an ordered mapping entry. + yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE // Expect the first key of a flow mapping. + yaml_PARSE_FLOW_MAPPING_KEY_STATE // Expect a key of a flow mapping. + yaml_PARSE_FLOW_MAPPING_VALUE_STATE // Expect a value of a flow mapping. + yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE // Expect an empty value of a flow mapping. + yaml_PARSE_END_STATE // Expect nothing. +) + +func (ps yaml_parser_state_t) String() string { + switch ps { + case yaml_PARSE_STREAM_START_STATE: + return "yaml_PARSE_STREAM_START_STATE" + case yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE: + return "yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE" + case yaml_PARSE_DOCUMENT_START_STATE: + return "yaml_PARSE_DOCUMENT_START_STATE" + case yaml_PARSE_DOCUMENT_CONTENT_STATE: + return "yaml_PARSE_DOCUMENT_CONTENT_STATE" + case yaml_PARSE_DOCUMENT_END_STATE: + return "yaml_PARSE_DOCUMENT_END_STATE" + case yaml_PARSE_BLOCK_NODE_STATE: + return "yaml_PARSE_BLOCK_NODE_STATE" + case yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE: + return "yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE" + case yaml_PARSE_FLOW_NODE_STATE: + return "yaml_PARSE_FLOW_NODE_STATE" + case yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE: + return "yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE" + case yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE: + return "yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE" + case yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE: + return "yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE" + case yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE: + return "yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE" + case yaml_PARSE_BLOCK_MAPPING_KEY_STATE: + return "yaml_PARSE_BLOCK_MAPPING_KEY_STATE" + case yaml_PARSE_BLOCK_MAPPING_VALUE_STATE: + return "yaml_PARSE_BLOCK_MAPPING_VALUE_STATE" + case yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE: + return "yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE" + case yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE: + return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE" + case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE: + return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE" + case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE: + return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE" + case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE: + return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE" + case yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE: + return "yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE" + case yaml_PARSE_FLOW_MAPPING_KEY_STATE: + return "yaml_PARSE_FLOW_MAPPING_KEY_STATE" + case yaml_PARSE_FLOW_MAPPING_VALUE_STATE: + return "yaml_PARSE_FLOW_MAPPING_VALUE_STATE" + case yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE: + return "yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE" + case yaml_PARSE_END_STATE: + return "yaml_PARSE_END_STATE" + } + return "" +} + +// This structure holds aliases data. +type yaml_alias_data_t struct { + anchor []byte // The anchor. + index int // The node id. + mark yaml_mark_t // The anchor mark. +} + +// The parser structure. +// +// All members are internal. Manage the structure using the +// yaml_parser_ family of functions. +type yaml_parser_t struct { + + // Error handling + + error yaml_error_type_t // Error type. + + problem string // Error description. + + // The byte about which the problem occurred. + problem_offset int + problem_value int + problem_mark yaml_mark_t + + // The error context. + context string + context_mark yaml_mark_t + + // Reader stuff + + read_handler yaml_read_handler_t // Read handler. + + input_file io.Reader // File input data. + input []byte // String input data. + input_pos int + + eof bool // EOF flag + + buffer []byte // The working buffer. + buffer_pos int // The current position of the buffer. + + unread int // The number of unread characters in the buffer. + + raw_buffer []byte // The raw buffer. + raw_buffer_pos int // The current position of the buffer. + + encoding yaml_encoding_t // The input encoding. + + offset int // The offset of the current position (in bytes). + mark yaml_mark_t // The mark of the current position. + + // Scanner stuff + + stream_start_produced bool // Have we started to scan the input stream? + stream_end_produced bool // Have we reached the end of the input stream? + + flow_level int // The number of unclosed '[' and '{' indicators. + + tokens []yaml_token_t // The tokens queue. + tokens_head int // The head of the tokens queue. + tokens_parsed int // The number of tokens fetched from the queue. + token_available bool // Does the tokens queue contain a token ready for dequeueing. + + indent int // The current indentation level. + indents []int // The indentation levels stack. + + simple_key_allowed bool // May a simple key occur at the current position? + simple_keys []yaml_simple_key_t // The stack of simple keys. + + // Parser stuff + + state yaml_parser_state_t // The current parser state. + states []yaml_parser_state_t // The parser states stack. + marks []yaml_mark_t // The stack of marks. + tag_directives []yaml_tag_directive_t // The list of TAG directives. + + // Dumper stuff + + aliases []yaml_alias_data_t // The alias data. + + document *yaml_document_t // The currently parsed document. +} + +// Emitter Definitions + +// The prototype of a write handler. +// +// The write handler is called when the emitter needs to flush the accumulated +// characters to the output. The handler should write @a size bytes of the +// @a buffer to the output. +// +// @param[in,out] data A pointer to an application data specified by +// yaml_emitter_set_output(). +// @param[in] buffer The buffer with bytes to be written. +// @param[in] size The size of the buffer. +// +// @returns On success, the handler should return @c 1. If the handler failed, +// the returned value should be @c 0. +// +type yaml_write_handler_t func(emitter *yaml_emitter_t, buffer []byte) error + +type yaml_emitter_state_t int + +// The emitter states. +const ( + // Expect STREAM-START. + yaml_EMIT_STREAM_START_STATE yaml_emitter_state_t = iota + + yaml_EMIT_FIRST_DOCUMENT_START_STATE // Expect the first DOCUMENT-START or STREAM-END. + yaml_EMIT_DOCUMENT_START_STATE // Expect DOCUMENT-START or STREAM-END. + yaml_EMIT_DOCUMENT_CONTENT_STATE // Expect the content of a document. + yaml_EMIT_DOCUMENT_END_STATE // Expect DOCUMENT-END. + yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE // Expect the first item of a flow sequence. + yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE // Expect an item of a flow sequence. + yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE // Expect the first key of a flow mapping. + yaml_EMIT_FLOW_MAPPING_KEY_STATE // Expect a key of a flow mapping. + yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE // Expect a value for a simple key of a flow mapping. + yaml_EMIT_FLOW_MAPPING_VALUE_STATE // Expect a value of a flow mapping. + yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE // Expect the first item of a block sequence. + yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE // Expect an item of a block sequence. + yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE // Expect the first key of a block mapping. + yaml_EMIT_BLOCK_MAPPING_KEY_STATE // Expect the key of a block mapping. + yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE // Expect a value for a simple key of a block mapping. + yaml_EMIT_BLOCK_MAPPING_VALUE_STATE // Expect a value of a block mapping. + yaml_EMIT_END_STATE // Expect nothing. +) + +// The emitter structure. +// +// All members are internal. Manage the structure using the @c yaml_emitter_ +// family of functions. +type yaml_emitter_t struct { + + // Error handling + + error yaml_error_type_t // Error type. + problem string // Error description. + + // Writer stuff + + write_handler yaml_write_handler_t // Write handler. + + output_buffer *[]byte // String output data. + output_file io.Writer // File output data. + + buffer []byte // The working buffer. + buffer_pos int // The current position of the buffer. + + raw_buffer []byte // The raw buffer. + raw_buffer_pos int // The current position of the buffer. + + encoding yaml_encoding_t // The stream encoding. + + // Emitter stuff + + canonical bool // If the output is in the canonical style? + best_indent int // The number of indentation spaces. + best_width int // The preferred width of the output lines. + unicode bool // Allow unescaped non-ASCII characters? + line_break yaml_break_t // The preferred line break. + + state yaml_emitter_state_t // The current emitter state. + states []yaml_emitter_state_t // The stack of states. + + events []yaml_event_t // The event queue. + events_head int // The head of the event queue. + + indents []int // The stack of indentation levels. + + tag_directives []yaml_tag_directive_t // The list of tag directives. + + indent int // The current indentation level. + + flow_level int // The current flow level. + + root_context bool // Is it the document root context? + sequence_context bool // Is it a sequence context? + mapping_context bool // Is it a mapping context? + simple_key_context bool // Is it a simple mapping key context? + + line int // The current line. + column int // The current column. + whitespace bool // If the last character was a whitespace? + indention bool // If the last character was an indentation character (' ', '-', '?', ':')? + open_ended bool // If an explicit document end is required? + + // Anchor analysis. + anchor_data struct { + anchor []byte // The anchor value. + alias bool // Is it an alias? + } + + // Tag analysis. + tag_data struct { + handle []byte // The tag handle. + suffix []byte // The tag suffix. + } + + // Scalar analysis. + scalar_data struct { + value []byte // The scalar value. + multiline bool // Does the scalar contain line breaks? + flow_plain_allowed bool // Can the scalar be expessed in the flow plain style? + block_plain_allowed bool // Can the scalar be expressed in the block plain style? + single_quoted_allowed bool // Can the scalar be expressed in the single quoted style? + block_allowed bool // Can the scalar be expressed in the literal or folded styles? + style yaml_scalar_style_t // The output style. + } + + // Dumper stuff + + opened bool // If the stream was already opened? + closed bool // If the stream was already closed? + + // The information associated with the document nodes. + anchors *struct { + references int // The number of references. + anchor int // The anchor id. + serialized bool // If the node has been emitted? + } + + last_anchor_id int // The last assigned anchor id. + + document *yaml_document_t // The currently emitted document. +} diff --git a/vendor/github.com/go-yaml/yaml/yamlprivateh.go b/vendor/github.com/go-yaml/yaml/yamlprivateh.go new file mode 100644 index 00000000..8110ce3c --- /dev/null +++ b/vendor/github.com/go-yaml/yaml/yamlprivateh.go @@ -0,0 +1,173 @@ +package yaml + +const ( + // The size of the input raw buffer. + input_raw_buffer_size = 512 + + // The size of the input buffer. + // It should be possible to decode the whole raw buffer. + input_buffer_size = input_raw_buffer_size * 3 + + // The size of the output buffer. + output_buffer_size = 128 + + // The size of the output raw buffer. + // It should be possible to encode the whole output buffer. + output_raw_buffer_size = (output_buffer_size*2 + 2) + + // The size of other stacks and queues. + initial_stack_size = 16 + initial_queue_size = 16 + initial_string_size = 16 +) + +// Check if the character at the specified position is an alphabetical +// character, a digit, '_', or '-'. +func is_alpha(b []byte, i int) bool { + return b[i] >= '0' && b[i] <= '9' || b[i] >= 'A' && b[i] <= 'Z' || b[i] >= 'a' && b[i] <= 'z' || b[i] == '_' || b[i] == '-' +} + +// Check if the character at the specified position is a digit. +func is_digit(b []byte, i int) bool { + return b[i] >= '0' && b[i] <= '9' +} + +// Get the value of a digit. +func as_digit(b []byte, i int) int { + return int(b[i]) - '0' +} + +// Check if the character at the specified position is a hex-digit. +func is_hex(b []byte, i int) bool { + return b[i] >= '0' && b[i] <= '9' || b[i] >= 'A' && b[i] <= 'F' || b[i] >= 'a' && b[i] <= 'f' +} + +// Get the value of a hex-digit. +func as_hex(b []byte, i int) int { + bi := b[i] + if bi >= 'A' && bi <= 'F' { + return int(bi) - 'A' + 10 + } + if bi >= 'a' && bi <= 'f' { + return int(bi) - 'a' + 10 + } + return int(bi) - '0' +} + +// Check if the character is ASCII. +func is_ascii(b []byte, i int) bool { + return b[i] <= 0x7F +} + +// Check if the character at the start of the buffer can be printed unescaped. +func is_printable(b []byte, i int) bool { + return ((b[i] == 0x0A) || // . == #x0A + (b[i] >= 0x20 && b[i] <= 0x7E) || // #x20 <= . <= #x7E + (b[i] == 0xC2 && b[i+1] >= 0xA0) || // #0xA0 <= . <= #xD7FF + (b[i] > 0xC2 && b[i] < 0xED) || + (b[i] == 0xED && b[i+1] < 0xA0) || + (b[i] == 0xEE) || + (b[i] == 0xEF && // #xE000 <= . <= #xFFFD + !(b[i+1] == 0xBB && b[i+2] == 0xBF) && // && . != #xFEFF + !(b[i+1] == 0xBF && (b[i+2] == 0xBE || b[i+2] == 0xBF)))) +} + +// Check if the character at the specified position is NUL. +func is_z(b []byte, i int) bool { + return b[i] == 0x00 +} + +// Check if the beginning of the buffer is a BOM. +func is_bom(b []byte, i int) bool { + return b[0] == 0xEF && b[1] == 0xBB && b[2] == 0xBF +} + +// Check if the character at the specified position is space. +func is_space(b []byte, i int) bool { + return b[i] == ' ' +} + +// Check if the character at the specified position is tab. +func is_tab(b []byte, i int) bool { + return b[i] == '\t' +} + +// Check if the character at the specified position is blank (space or tab). +func is_blank(b []byte, i int) bool { + //return is_space(b, i) || is_tab(b, i) + return b[i] == ' ' || b[i] == '\t' +} + +// Check if the character at the specified position is a line break. +func is_break(b []byte, i int) bool { + return (b[i] == '\r' || // CR (#xD) + b[i] == '\n' || // LF (#xA) + b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) + b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) + b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9) // PS (#x2029) +} + +func is_crlf(b []byte, i int) bool { + return b[i] == '\r' && b[i+1] == '\n' +} + +// Check if the character is a line break or NUL. +func is_breakz(b []byte, i int) bool { + //return is_break(b, i) || is_z(b, i) + return ( // is_break: + b[i] == '\r' || // CR (#xD) + b[i] == '\n' || // LF (#xA) + b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) + b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) + b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029) + // is_z: + b[i] == 0) +} + +// Check if the character is a line break, space, or NUL. +func is_spacez(b []byte, i int) bool { + //return is_space(b, i) || is_breakz(b, i) + return ( // is_space: + b[i] == ' ' || + // is_breakz: + b[i] == '\r' || // CR (#xD) + b[i] == '\n' || // LF (#xA) + b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) + b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) + b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029) + b[i] == 0) +} + +// Check if the character is a line break, space, tab, or NUL. +func is_blankz(b []byte, i int) bool { + //return is_blank(b, i) || is_breakz(b, i) + return ( // is_blank: + b[i] == ' ' || b[i] == '\t' || + // is_breakz: + b[i] == '\r' || // CR (#xD) + b[i] == '\n' || // LF (#xA) + b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) + b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) + b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029) + b[i] == 0) +} + +// Determine the width of the character. +func width(b byte) int { + // Don't replace these by a switch without first + // confirming that it is being inlined. + if b&0x80 == 0x00 { + return 1 + } + if b&0xE0 == 0xC0 { + return 2 + } + if b&0xF0 == 0xE0 { + return 3 + } + if b&0xF8 == 0xF0 { + return 4 + } + return 0 + +} diff --git a/vendor/github.com/golang/dep/.codeclimate.yml b/vendor/github.com/golang/dep/.codeclimate.yml new file mode 100644 index 00000000..a1c11c89 --- /dev/null +++ b/vendor/github.com/golang/dep/.codeclimate.yml @@ -0,0 +1,35 @@ +version: "2" +checks: + argument-count: + enabled: false + complex-logic: + enabled: false + file-lines: + enabled: false + method-complexity: + enabled: false + method-count: + enabled: false + method-lines: + enabled: false + nested-control-flow: + enabled: false + return-statements: + enabled: false + similar-code: + enabled: false + identical-code: + enabled: false +plugins: + gofmt: + enabled: true + govet: + enabled: true + golint: + enabled: true +exclude_paths: + - vendor/ + - gps/_testdata + - cmd/dep/testdata + - testdata + - gps/internal/pb diff --git a/vendor/github.com/golang/dep/.gitattributes b/vendor/github.com/golang/dep/.gitattributes new file mode 100644 index 00000000..d8df4ca6 --- /dev/null +++ b/vendor/github.com/golang/dep/.gitattributes @@ -0,0 +1,2 @@ +# Prevent problems comparing golden files on Windows +**/testdata/** text eol=lf diff --git a/vendor/github.com/golang/dep/.github/CODEOWNERS b/vendor/github.com/golang/dep/.github/CODEOWNERS new file mode 100644 index 00000000..6bc15ea9 --- /dev/null +++ b/vendor/github.com/golang/dep/.github/CODEOWNERS @@ -0,0 +1,25 @@ +# general +* @sdboyer + +# init +/cmd/dep/init* @carolynvs +/cmd/dep/gopath_scanner* @carolynvs +/cmd/dep/root_analyzer* @carolynvs +/cmd/dep/testdata/init @carolynvs +/cmd/dep/testdata/harness_tests/init @carolynvs +/internal/importers @carolynvs +/analyzer* @carolynvs +/testdata/analyzer @carolynvs +/internal/feedback @carolynvs + +# ensure +/cmd/dep/ensure* @ibrasho +/cmd/dep/testdata/harness_tests/ensure** @ibrasho + +# status +/cmd/dep/status* @darkowlzz +/cmd/dep/testdata/harness_tests/status** @darkowlzz +/cmd/dep/graphviz* @darkowlzz + +# gps caching +/gps/source_cache* @jmank88 diff --git a/vendor/github.com/golang/dep/.github/ISSUE_TEMPLATE.md b/vendor/github.com/golang/dep/.github/ISSUE_TEMPLATE.md new file mode 100644 index 00000000..3e612d9b --- /dev/null +++ b/vendor/github.com/golang/dep/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,26 @@ + + +### What version of `dep` are you using (`dep version`)? + + +### What `dep` command did you run? + + + +### What did you expect to see? + +### What did you see instead? diff --git a/vendor/github.com/golang/dep/.github/PULL_REQUEST_TEMPLATE.md b/vendor/github.com/golang/dep/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 00000000..c0668911 --- /dev/null +++ b/vendor/github.com/golang/dep/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,23 @@ + + +### What does this do / why do we need it? + +### What should your reviewer look out for in this PR? + +### Do you need help or clarification on anything? + +### Which issue(s) does this PR fix? + + diff --git a/vendor/github.com/golang/dep/.gitignore b/vendor/github.com/golang/dep/.gitignore new file mode 100644 index 00000000..a7c3f411 --- /dev/null +++ b/vendor/github.com/golang/dep/.gitignore @@ -0,0 +1,10 @@ +# dep project generated files to ignore +# if you want to ignore files created by your editor/tools, +# please consider a global .gitignore https://help.github.com/articles/ignoring-files +# please do not open a pull request to add something created by your editor or tools +/dep +/testdep +/dep.exe +/licenseok +/profile.out +/coverage.txt diff --git a/vendor/github.com/golang/dep/.travis.yml b/vendor/github.com/golang/dep/.travis.yml new file mode 100644 index 00000000..88d434b8 --- /dev/null +++ b/vendor/github.com/golang/dep/.travis.yml @@ -0,0 +1,87 @@ +language: go +sudo: false +notifications: + email: false +jobs: + include: + - stage: test + go_import_path: github.com/golang/dep + install: + - go get -u github.com/golang/lint/golint honnef.co/go/tools/cmd/megacheck + - npm install -g codeclimate-test-reporter + env: + - DEPTESTBYPASS501=1 + os: linux + go: 1.9.x + script: + - go test -i ./... + - ./hack/lint.bash + - ./hack/validate-vendor.bash + - ./hack/validate-licence.bash + - ./hack/coverage.bash + after_success: + - codeclimate-test-reporter < coverage.txt + # YAML alias, for settings shared across the simpler builds + - &simple-test + go: 1.8.x + stage: test + go_import_path: github.com/golang/dep + install: skip + env: + - DEPTESTBYPASS501=1 + script: go test -race $(go list ./... | grep -v vendor) + - <<: *simple-test + go: tip + - <<: *simple-test + os: osx + go: 1.9.x + install: + # brew takes horribly long to update itself despite the above caching + # attempt; only bzr install if it's not on the $PATH + - test $(which bzr) || brew install bzr + env: + - HOMEBREW_NO_AUTO_UPDATE=1 + - DEPTESTBYPASS501=1 + script: + # OSX as of El Capitan sets an exit trap that interacts poorly with how + # travis seems to spawn these shells; if set -e is set, then it can cause + # build failures. We're not doing that here, but retain the trap statement + # for future safety. + # Related: https://superuser.com/questions/1044130/why-am-i-having-how-can-i-fix-this-error-shell-session-update-command-not-f + - trap EXIT + - go test -race ./... + - go: 1.9.x + stage: deploy + go_import_path: github.com/golang/dep + install: skip + script: skip + before_deploy: + - ./hack/build-all.bash + deploy: + - provider: releases + api_key: + secure: fL9GX11J3JLizEBTPZHN32wuAT91eAJsGl0kjlAdIc6Lb/9UCe1XZGgFnpQFN4qo/S+omhHBDbM6Ty1xhNy7xmjDecpQGDU8Rmap9Oll0TuxqMigG+njOuPp5VUYPofPP0PGKdxAcYg+KaFM7x0o2rK+qA046NHwo2gH1BbE+bn55TZglEajEfc8j9iX4jt96KC7zlu+WiKArLmfUtlrI8m8ZYgbYcvFmlYjeCiEqlNhvNL59ejug9Rl0PLtPbamqVXkGLafYtekgPCb4WSxBiCt8pq5Rb5svk9YcdXpiaWQhZjMPAuKN6BrmN2lw1PiXzADUG5fjvNc8eo2HY70GD2utU9cAsY8VIafhoH5n6uM1WI8MHwDfd7P1PiQA3ZGQ8CPwk4q/8HSfQU9ap7vZgSF63pTIbtlviyIG67orOJE9PWWncl9olYM946UylZu6m3hWI/rmJxOeJ1UJjym/3GNPMRfKubaGhV/TyRdM0bKX4M0cXHU6k/ESVFupGXdKRt4RpvkD4/1Km6b2OShW6PNI+ifFspnJr7obkI7dm7ubySdnNz4lMv9WWymxRpMVc8hUAhuoDvXeZJq7pSnkjBEWDxIRoTkA93CU3/Rf7MFYCJMnGSqjcxWUpIfCAk2/r4BqL9NQnqBvvVt+MYi64QaD5n7ZF3dVbr6HZ2zjSU= + file: + - release/dep-linux-amd64 + - release/dep-linux-amd64.sha256 + - release/dep-darwin-amd64 + - release/dep-darwin-amd64.sha256 + - release/dep-freebsd-amd64 + - release/dep-freebsd-amd64.sha256 + - release/dep-windows-amd64.exe + - release/dep-windows-amd64.exe.sha256 + - release/dep-linux-386 + - release/dep-linux-386.sha256 + - release/dep-darwin-386 + - release/dep-darwin-386.sha256 + - release/dep-freebsd-386 + - release/dep-freebsd-386.sha256 + - release/dep-windows-386.exe + - release/dep-windows-386.exe.sha256 + skip_cleanup: true + on: + repo: golang/dep + branch: master + tags: true +addons: + ssh_known_hosts: github.com diff --git a/vendor/github.com/golang/dep/AUTHORS b/vendor/github.com/golang/dep/AUTHORS new file mode 100644 index 00000000..15167cd7 --- /dev/null +++ b/vendor/github.com/golang/dep/AUTHORS @@ -0,0 +1,3 @@ +# This source code refers to The Go Authors for copyright purposes. +# The master list of authors is in the main Go distribution, +# visible at http://tip.golang.org/AUTHORS. diff --git a/vendor/github.com/golang/dep/CHANGELOG.md b/vendor/github.com/golang/dep/CHANGELOG.md new file mode 100644 index 00000000..f1693910 --- /dev/null +++ b/vendor/github.com/golang/dep/CHANGELOG.md @@ -0,0 +1,122 @@ +# (next version) + +NEW FEATURES: + +BUG FIXES: + +IMPROVEMENTS: + +# v0.4.1 + +BUG FIXES: + +* Fix per-project prune option handling ([#1570](https://github.com/golang/dep/pull/1570)) + +# v0.4.0 + +NEW FEATURES: +* Add support for importing from [glock](https://github.com/robfig/glock) based projects. ([#1422](https://github.com/golang/dep/pull/1422) +* Add support for importing from [govendor](https://github.com/kardianos/govendor) based projects. ([#815](https://github.com/golang/dep/pull/815) +* Allow override of cache directory location using environment variable `DEPCACHEDIR`. ([#1234](https://github.com/golang/dep/pull/1234)) +* Add support for template output in `dep status`. ([#1389](https://github.com/golang/dep/pull/1389) +* Each element in a multi-item TOML array is output on its own line. ([#1461](https://github.com/golang/dep/pull/1461) + +BUG FIXES: + +* Releases targeting Windows now have a `.exe` suffix. ([#1291](https://github.com/golang/dep/pull/1291) +* Adaptively recover from dirty and corrupted git repositories in cache. ([#1279](https://github.com/golang/dep/pull/1279) +* Suppress git password prompts in more places. ([#1357](https://github.com/golang/dep/pull/1357) +* Fix `-no-vendor` flag for `ensure -update`. ([#1361](https://github.com/golang/dep/pull/1361) +* Validate `git ls-remote` output and ignore all malformed lines. ([#1379](https://github.com/golang/dep/pull/1379) +* Support [gopkg.in version zero](http://labix.org/gopkg.in#VersionZero). ([#1243](https://github.com/golang/dep/pull/1243) +* Fix how dep status print revision constraints. ([#1421](https://github.com/golang/dep/pull/1421) +* Add optional `-v` flag to ensure sub command's syntax. ([#1458](https://github.com/golang/dep/pull/1458) +* Allow URLs containing ports in `Gopkg.toml` `source` fields. ([#1509](https://github.com/golang/dep/pull/1509) + +IMPROVEMENTS: + +* Log as dependencies are pre-fetched during dep init. ([#1176](https://github.com/golang/dep/pull/1176)) +* Make the gps package importable. ([#1349](https://github.com/golang/dep/pull/1349)) +* Improve file copy performance by not forcing a file sync. ([#1408](https://github.com/golang/dep/pull/1408) +* Skip empty constraints during import. ([#1414](https://github.com/golang/dep/pull/1349)) +* Handle errors when writing status output. ([#1420](https://github.com/golang/dep/pull/1420)) +* Add constraint for locked projects in `dep status`. ([#962](https://github.com/golang/dep/pull/962) +* Make external config importers error tolerant. ([#1315](https://github.com/golang/dep/pull/1315)) +* Show LATEST and VERSION as the same type in status. ([#1515](https://github.com/golang/dep/pull/1515) +* Warn when [[constraint]] rules that will have no effect. ([#1534](https://github.com/golang/dep/pull/1534)) + +# v0.3.2 + +NEW FEATURES: + +* Add support for importing from [gvt](https://github.com/FiloSottile/gvt) +and [gb](https://godoc.org/github.com/constabulary/gb/cmd/gb-vendor). +(#1149) +* Wildcard ignore support. (#1156) +* Disable SourceManager lock by setting `DEPNOLOCK` environment variable. +(#1206) +* `dep ensure -no-vendor -dry-run` now exits with an error when changes would +have to be made to `Gopkg.lock`. This is useful for CI. (#1256) + +BUG FIXES: + +* gps: Fix case mismatch error with multiple dependers. (#1233) +* Skip broken `vendor` symlink rather than returning an error. (#1191) +* Fix `status` shows incorrect reason for lock mismatch when ignoring packages. +(#1216) + +IMPROVEMENTS: + +* Allow `dep ensure -add` and `-update` when lock is out-of-sync. (#1225) +* gps: vcs: Dedupe git version list (#1212) +* gps: Add prune functions to gps. (#1020) +* gps: Skip broken vendor symlinks. (#1191) +* `dep ensure -add` now concurrently fetches the source and adds the projects. +(#1218) +* File name case check is now performed on `Gopkg.toml` and `Gopkg.lock`. +(#1114) +* gps: gps now supports pruning. (#1020) +* `dep ensure -update` now concurrently validates the passed project arguments. +Improving performance when updating dependencies with `-update`. (#1175) +* `dep status` now concurrently fetches repo info. Improving status performance. +(#1135) +* gps: Add SourceURLsForPath() to SourceManager. (#1166) +* gps: Include output in error. (#1180) + +WIP: + +* gps: Process canonical import paths. (#1017) +* gps: Persistent cache. (#1127, #1215) + + +# v0.3.1 + +* gps: Add satisfiability check for case variants (#1079) +* Validate Project Roots in manifest (#1116) +* gps: Properly separate sources for different gopkg.in versions & github +(#1132) +* gps: Add persistent BoltDB cache (#1098) +* gps: Increase default subcommand timeout to 30s (#1087) +* Fix importer [issue](https://github.com/golang/dep/issues/939) where the +importer would drop the imported version of a project (#1100) +* Import analyzer now always uses the same name, fixing the lock mismatch +immediately after dep init issue (#1099) +* Add support for importing from [govend](https://github.com/govend/govend) +(#1040) and [LK4D4/vndr](https://github.com/LK4D4/vndr) (#978) based projects +* gps: gps no longer assumes that every git repo has a HEAD (#1053) +* `os.Chmod` failures on Windows due to long path length has been fixed (#925) +* Add `version` command (#996) +* Drop support for building with go1.7 (#714) +* gps: Parse abbreviated git revisions (#1027) +* gps: Parallelize writing dep tree (#1021) +* `status` now shows the progress in verbose mode (#1009, #1037) +* Fix empty `Constraint` and `Version` in `status` json output (#976) +* `status` table output now shows override constraints (#918) +* gps: Display warning message every 15 seconds when lockfile is busy (#958) +* gps: Hashing directory tree and tree verification (#959) +* `ensure` now has `-vendor-only` mode to populate vendor/ without updating +Gopkg.lock (#954) +* Use fork of Masterminds/semver until +Masterminds/semver [issue#59](https://github.com/Masterminds/semver/issues/59) +is fixed upstream (#938) +* gps: Ensure packages are deducible before attempting to solve (#697) diff --git a/vendor/github.com/golang/dep/CODE_OF_CONDUCT.md b/vendor/github.com/golang/dep/CODE_OF_CONDUCT.md new file mode 100644 index 00000000..660ee848 --- /dev/null +++ b/vendor/github.com/golang/dep/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, 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 the project team at sam (at) samboyer.org. 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 [http://contributor-covenant.org/version/1/4][version] + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/ diff --git a/vendor/github.com/golang/dep/CONTRIBUTING.md b/vendor/github.com/golang/dep/CONTRIBUTING.md new file mode 100644 index 00000000..2a0e7b28 --- /dev/null +++ b/vendor/github.com/golang/dep/CONTRIBUTING.md @@ -0,0 +1,109 @@ +# Contributing to `dep` + +`dep` is an open source project. + +It is the work of hundreds of contributors. We appreciate your help! + +Keep an eye on the [Roadmap](https://github.com/golang/dep/wiki/Roadmap) for a summary of where the project is, and where we're headed. + +## Filing issues + +Please check the existing issues and [FAQ](docs/FAQ.md) to see if your feedback has already been reported. + +When [filing an issue](https://github.com/golang/dep/issues/new), make sure to answer these five questions: + +1. What version of Go (`go version`) and `dep` (`git describe --tags`) are you using?? +3. What `dep` command did you run? +4. What did you expect to see? +5. What did you see instead? + +General questions should go to the [golang-nuts mailing list](https://groups.google.com/group/golang-nuts) instead of the issue tracker. +The gophers there will answer or ask you to file an issue if you've tripped over a bug. + +## Contributing code + +Let us know if you are interested in working on an issue by leaving a comment +on the issue in GitHub. This helps avoid multiple people unknowingly +working on the same issue. + +Please read the [Contribution Guidelines](https://golang.org/doc/contribute.html) +before sending patches. + +The +[help wanted](https://github.com/golang/dep/issues?q=is%3Aissue+is%3Aopen+label%3A%22help%20wanted%22) +label highlights issues that are well-suited for folks to jump in on. The +[good first issue](https://github.com/golang/dep/issues?q=is%3Aissue+is%3Aopen+label%3A%22good%20first%20issue%22) +label further identifies issues that are particularly well-sized for newcomers. + +Unless otherwise noted, the `dep` source files are distributed under +the BSD-style license found in the LICENSE file. + +All submissions, including submissions by project members, require review. We +use GitHub pull requests for this purpose. Consult [GitHub Help] for more +information on using pull requests. + +We check `dep`'s own `vendor` directory into git. For any PR to `dep` where you're +updating `Gopkg.toml`, make sure to run `dep ensure` and +([for now](https://github.com/golang/dep/issues/944)) `dep prune` and commit all +changes to `vendor`. + +[GitHub Help]: https://help.github.com/articles/about-pull-requests/ + +## Contributor License Agreement + +Contributions to this project must be accompanied by a Contributor License +Agreement. You (or your employer) retain the copyright to your contribution, +this simply gives us permission to use and redistribute your contributions as +part of the project. Head over to to see +your current agreements on file or to sign a new one. + +You generally only need to submit a CLA once, so if you've already submitted one +(even if it was for a different project), you probably don't need to do it +again. + +## Maintainer's Guide + +`dep` has subsystem maintainers; this guide is intended for them in performing their work as a maintainer. + +### General guidelines + +* _Be kind, respectful, and inclusive_. Really live [that CoC](https://github.com/golang/dep/blob/master/CODE_OF_CONDUCT.md). We've developed a reputation as one of the most welcoming and supportive project environments in the Go community, and we want to keep that up! +* The lines of responsibility between maintainership areas can be fuzzy. Get to know your fellow maintainers - it's important to work _with_ them when an issue falls in this grey area. +* Remember, the long-term goal of `dep` is to disappear into the `go` toolchain. That's going to be a challenging process, no matter what. Minimizing that eventual difficulty should be a guiding light for all your decisions today. + * Try to match the toolchain's assumptions as closely as possible ([example](https://github.com/golang/dep/issues/564#issuecomment-300994599)), and avoid introducing new rules the toolchain would later have to incorporate. + * Every new flag or option in the metadata files is more exposed surface area that demands conversion later. Only add these with a clear design plan. + * `dep` is experimental, but increasingly only on a larger scale. Experiments need clear hypotheses and parameters for testing - nothing off-the-cuff. +* Being a maintainer doesn't mean you're always right. Admitting when you've made a mistake keeps the code flowing, the environment health, and the respect level up. +* It's fine if you need to step back from maintainership responsibilities - just, please, don't fade away! Let other maintainers know what's going on. + +### Issue management + +* We use [Zenhub](https://www.zenhub.com) to manage the queue, in addition to what we do with labels. + * You will need to install [ZenHub extension](https://www.zenhub.com/extension) to your browser to show the board. + * Pipelines, and [the board](https://github.com/golang/dep#boards) are one thing we try to utilize: + * **New Issues Pipeline**: When someone creates a new issue, it goes here first. Keep an eye out for issues that fall into your area. Add labels to them, and if it's something we should do, put it in the `Backlog` pipeline. If you aren't sure, throw it in the `Icebox`. It helps to sort this pipeline by date. + * **Icebox Pipeline**: Issues that we aren't immediately closing but aren't really ready to be prioritized and started on. It's not a wontfix bucket, but a "not sure if we should/can fix right now" bucket. + * **Backlog Pipeline**: Issues that we know we want to tackle. You can drag/drop up and down to prioritize issues. + * Marking dependencies/blockers is also quite useful where appropriate; please do that. + * We use epics and milestones in roughly the same way (because OSS projects don't have real sprints). Epics should be duplicated as milestones; if there's a main epic issue, it should contain a checklist of the relevant issues to complete it. +* The `area:` labels correspond to maintainership areas. Apply yours to any issues or PRs that fall under your purview. It's to be expected that multiple `area:` labels may be applied to a single issue. +* The [`help wanted`](https://github.com/golang/dep/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22) and [`good first issue`](https://github.com/golang/dep/labels/good%20first%20issue) labels are two of our most important tools for making the project accessible to newcomers - a key goal for our community. Here's how to use them well. + * `good-first-pr` should be applied when there's a very straightforward, self-contained task that is very unlikely to have any hidden complexity. The real purpose of these is to provide a "chink in the armor", providing newcomers a lens through which to start understanding the project. + * `help-wanted` should be applied to issues where there's a clear, stated goal, there is at most one significant question that needs answering, and it looks like the implementation won't be inordinately difficult, or disruptive to other parts of the system. + * `help-wanted` should also be applied to all `good-first-pr` issues - it's duplicative, but not doing so seems unfriendly. + + +### Pull Requests + +* Try to make, and encourage, smaller pull requests. +* [No is temporary. Yes is forever.](https://blog.jessfraz.com/post/the-art-of-closing/) +* Long-running feature branches should generally be avoided. Discuss it with other maintainers first. +* Unless it's trivial, don't merge your own PRs - ask another maintainer. +* Commit messages should follow [Tim Pope's rules](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html). +* Checklist for merging PRs: + * Does the PR pass [the code review comments](https://github.com/golang/go/wiki/CodeReviewComments)? (internalize these rules!) + * Are there tests to cover new or changed behavior? Prefer reliable tests > no tests > flaky tests. + * Does the first post in the PR contain "Fixes #..." text for any issues it resolves? + * Are any necessary follow-up issues _already_ posted, prior to merging? + * Does this change entail the updating of any docs? + * For docs kept in the repo, e.g. FAQ.md, docs changes _must_ be submitted as part of the same PR. diff --git a/vendor/github.com/golang/dep/CONTRIBUTORS b/vendor/github.com/golang/dep/CONTRIBUTORS new file mode 100644 index 00000000..1c4577e9 --- /dev/null +++ b/vendor/github.com/golang/dep/CONTRIBUTORS @@ -0,0 +1,3 @@ +# This source code was written by the Go contributors. +# The master list of contributors is in the main Go distribution, +# visible at http://tip.golang.org/CONTRIBUTORS. diff --git a/vendor/github.com/golang/dep/Gopkg.lock b/vendor/github.com/golang/dep/Gopkg.lock new file mode 100644 index 00000000..1779ee42 --- /dev/null +++ b/vendor/github.com/golang/dep/Gopkg.lock @@ -0,0 +1,94 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + branch = "parse-constraints-with-dash-in-pre" + name = "github.com/Masterminds/semver" + packages = ["."] + revision = "a93e51b5a57ef416dac8bb02d11407b6f55d8929" + source = "https://github.com/carolynvs/semver.git" + +[[projects]] + name = "github.com/Masterminds/vcs" + packages = ["."] + revision = "3084677c2c188840777bff30054f2b553729d329" + version = "v1.11.1" + +[[projects]] + branch = "master" + name = "github.com/armon/go-radix" + packages = ["."] + revision = "4239b77079c7b5d1243b7b4736304ce8ddb6f0f2" + +[[projects]] + name = "github.com/boltdb/bolt" + packages = ["."] + revision = "2f1ce7a837dcb8da3ec595b1dac9d0632f0f99e8" + version = "v1.3.1" + +[[projects]] + branch = "v2" + name = "github.com/go-yaml/yaml" + packages = ["."] + revision = "cd8b52f8269e0feb286dfeef29f8fe4d5b397e0b" + +[[projects]] + branch = "master" + name = "github.com/golang/protobuf" + packages = ["proto"] + revision = "5afd06f9d81a86d6e3bb7dc702d6bd148ea3ff23" + +[[projects]] + name = "github.com/jmank88/nuts" + packages = ["."] + revision = "8b28145dffc87104e66d074f62ea8080edfad7c8" + version = "v0.3.0" + +[[projects]] + branch = "master" + name = "github.com/nightlyone/lockfile" + packages = ["."] + revision = "e83dc5e7bba095e8d32fb2124714bf41f2a30cb5" + +[[projects]] + branch = "master" + name = "github.com/pelletier/go-toml" + packages = ["."] + revision = "b8b5e7696574464b2f9bf303a7b37781bb52889f" + +[[projects]] + name = "github.com/pkg/errors" + packages = ["."] + revision = "645ef00459ed84a119197bfb8d8205042c6df63d" + version = "v0.8.0" + +[[projects]] + branch = "master" + name = "github.com/sdboyer/constext" + packages = ["."] + revision = "836a144573533ea4da4e6929c235fd348aed1c80" + +[[projects]] + branch = "master" + name = "golang.org/x/net" + packages = ["context"] + revision = "66aacef3dd8a676686c7ae3716979581e8b03c47" + +[[projects]] + branch = "master" + name = "golang.org/x/sync" + packages = ["errgroup"] + revision = "f52d1811a62927559de87708c8913c1650ce4f26" + +[[projects]] + branch = "master" + name = "golang.org/x/sys" + packages = ["unix"] + revision = "bb24a47a89eac6c1227fbcb2ae37a8b9ed323366" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "e70d26b359aed7af66f3393fc9d4985bbcf499c0b5ed3b5661a5912b4c71a32e" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/Gopkg.toml b/vendor/github.com/golang/dep/Gopkg.toml new file mode 100644 index 00000000..1bec06d0 --- /dev/null +++ b/vendor/github.com/golang/dep/Gopkg.toml @@ -0,0 +1,37 @@ +[[constraint]] + branch = "parse-constraints-with-dash-in-pre" + name = "github.com/Masterminds/semver" + source = "https://github.com/carolynvs/semver.git" + +[[constraint]] + name = "github.com/Masterminds/vcs" + version = "1.11.0" + +[[constraint]] + branch = "v2" + name = "github.com/go-yaml/yaml" + +[[constraint]] + branch = "master" + name = "github.com/pelletier/go-toml" + +[[constraint]] + name = "github.com/pkg/errors" + version = "0.8.0" + +[[constraint]] + name = "github.com/boltdb/bolt" + version = "1.0.0" + +[[constraint]] + name = "github.com/jmank88/nuts" + version = "0.3.0" + +[[constraint]] + name = "github.com/golang/protobuf" + branch = "master" + +[prune] + non-go = true + go-tests = true + unused-packages = true diff --git a/vendor/github.com/golang/dep/LICENSE b/vendor/github.com/golang/dep/LICENSE new file mode 100644 index 00000000..a2dd15fa --- /dev/null +++ b/vendor/github.com/golang/dep/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2014 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * 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. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +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 +OWNER 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/golang/dep/MAINTAINERS.md b/vendor/github.com/golang/dep/MAINTAINERS.md new file mode 100644 index 00000000..9b985c38 --- /dev/null +++ b/vendor/github.com/golang/dep/MAINTAINERS.md @@ -0,0 +1,17 @@ + +General maintainers: + sam boyer (@sdboyer) + +* dep + * `init` command: Carolyn Van Slyck (@carolynvs) + * `ensure` command: Ibrahim AshShohail (@ibrasho) + * `status` command: Sunny (@darkowlzz) + * testing harness: (vacant) +* gps + * solver: (vacant) + * source manager: (vacant) + * root deduction: (vacant) + * source/vcs interaction: (vacant) + * caching: Jordan Krage (@jmank88) + * pkgtree: (vacant) + * versions and constraints: (vacant) diff --git a/vendor/github.com/golang/dep/PATENTS b/vendor/github.com/golang/dep/PATENTS new file mode 100644 index 00000000..73309904 --- /dev/null +++ b/vendor/github.com/golang/dep/PATENTS @@ -0,0 +1,22 @@ +Additional IP Rights Grant (Patents) + +"This implementation" means the copyrightable works distributed by +Google as part of the Go project. + +Google hereby grants to You a perpetual, worldwide, non-exclusive, +no-charge, royalty-free, irrevocable (except as stated in this section) +patent license to make, have made, use, offer to sell, sell, import, +transfer and otherwise run, modify and propagate the contents of this +implementation of Go, where such license applies only to those patent +claims, both currently owned or controlled by Google and acquired in +the future, licensable by Google that are necessarily infringed by this +implementation of Go. This grant does not include claims that would be +infringed only as a consequence of further modification of this +implementation. If you or your agent or exclusive licensee institute or +order or agree to the institution of patent litigation against any +entity (including a cross-claim or counterclaim in a lawsuit) alleging +that this implementation of Go or any code incorporated within this +implementation of Go constitutes direct or contributory patent +infringement, or inducement of patent infringement, then any patent +rights granted to you under this License for this implementation of Go +shall terminate as of the date such litigation is filed. diff --git a/vendor/github.com/golang/dep/README.md b/vendor/github.com/golang/dep/README.md new file mode 100644 index 00000000..49e407df --- /dev/null +++ b/vendor/github.com/golang/dep/README.md @@ -0,0 +1,47 @@ +

+

+ Build Status + Windows Build Status + +

+ +## Dep + +`dep` is a prototype dependency management tool for Go. It requires Go 1.8 or newer to compile. **`dep` is safe for production use.** + +`dep` is the official _experiment_, but not yet the official tool. Check out the [Roadmap](https://github.com/golang/dep/wiki/Roadmap) for more on what this means! + +For guides and reference materials about `dep`, see [the documentation](https://golang.github.io/dep). + +## Installation + +It is strongly recommended that you use a released version. Release binaries are available on the [releases](https://github.com/golang/dep/releases) page. + +On MacOS you can install or upgrade to the latest released version with Homebrew: + +```sh +$ brew install dep +$ brew upgrade dep +``` + +If you're interested in hacking on `dep`, you can install via `go get`: + +```sh +go get -u github.com/golang/dep/cmd/dep +``` + +## Feedback + +Feedback is greatly appreciated. +At this stage, the maintainers are most interested in feedback centered on the user experience (UX) of the tool. +Do you have workflows that the tool supports well, or doesn't support at all? +Do any of the commands have surprising effects, output, or results? +If not, please file an issue, describing what you did or wanted to do, what you expected to happen, and what actually happened. + +## Contributing + +Contributions are greatly appreciated. +The maintainers actively manage the issues list, and try to highlight issues suitable for newcomers. +The project follows the typical GitHub pull request model. +See [CONTRIBUTING.md](CONTRIBUTING.md) for more details. +Before starting any work, please either comment on an existing issue, or file a new one. diff --git a/vendor/github.com/golang/dep/analyzer.go b/vendor/github.com/golang/dep/analyzer.go new file mode 100644 index 00000000..1d0b920e --- /dev/null +++ b/vendor/github.com/golang/dep/analyzer.go @@ -0,0 +1,53 @@ +// Copyright 2016 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 dep + +import ( + "os" + "path/filepath" + + "github.com/golang/dep/gps" + "github.com/golang/dep/internal/fs" +) + +// Analyzer implements gps.ProjectAnalyzer. +type Analyzer struct{} + +// HasDepMetadata determines if a dep manifest exists at the specified path. +func (a Analyzer) HasDepMetadata(path string) bool { + mf := filepath.Join(path, ManifestName) + fileOK, err := fs.IsRegular(mf) + return err == nil && fileOK +} + +// DeriveManifestAndLock reads and returns the manifest at path/ManifestName or nil if one is not found. +// The Lock is always nil for now. +func (a Analyzer) DeriveManifestAndLock(path string, n gps.ProjectRoot) (gps.Manifest, gps.Lock, error) { + if !a.HasDepMetadata(path) { + return nil, nil, nil + } + + f, err := os.Open(filepath.Join(path, ManifestName)) + if err != nil { + return nil, nil, err + } + defer f.Close() + + // Ignore warnings irrelevant to user. + m, _, err := readManifest(f) + if err != nil { + return nil, nil, err + } + + return m, nil, nil +} + +// Info returns Analyzer's name and version info. +func (a Analyzer) Info() gps.ProjectAnalyzerInfo { + return gps.ProjectAnalyzerInfo{ + Name: "dep", + Version: 1, + } +} diff --git a/vendor/github.com/golang/dep/analyzer_notwindows_test.go b/vendor/github.com/golang/dep/analyzer_notwindows_test.go new file mode 100644 index 00000000..6b9dedb8 --- /dev/null +++ b/vendor/github.com/golang/dep/analyzer_notwindows_test.go @@ -0,0 +1,24 @@ +// Copyright 2017 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. + +// +build !windows + +package dep + +import ( + "io" + "os" +) + +func makeUnreadable(path string) (io.Closer, error) { + err := os.Chmod(path, 0222) + if err != nil { + return nil, err + } + return closer{}, nil +} + +type closer struct{} + +func (closer) Close() error { return nil } diff --git a/vendor/github.com/golang/dep/analyzer_test.go b/vendor/github.com/golang/dep/analyzer_test.go new file mode 100644 index 00000000..40b73074 --- /dev/null +++ b/vendor/github.com/golang/dep/analyzer_test.go @@ -0,0 +1,113 @@ +// Copyright 2016 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 dep + +import ( + "path/filepath" + "testing" + + "github.com/golang/dep/internal/test" +) + +func TestAnalyzerDeriveManifestAndLock(t *testing.T) { + h := test.NewHelper(t) + defer h.Cleanup() + + h.TempDir("dep") + golden := filepath.Join("analyzer", ManifestName) + want := h.GetTestFileString(golden) + h.TempCopy(filepath.Join("dep", ManifestName), golden) + + a := Analyzer{} + + m, l, err := a.DeriveManifestAndLock(h.Path("dep"), "my/fake/project") + if err != nil { + t.Fatal(err) + } + + got, err := m.(*Manifest).MarshalTOML() + if err != nil { + t.Fatal(err) + } + + if want != string(got) { + if *test.UpdateGolden { + if err := h.WriteTestFile(golden, string(got)); err != nil { + t.Fatal(err) + } + } else { + t.Fatalf("(WNT):\n%s\n(GOT):\n%s", want, string(got)) + } + } + + if l != nil { + t.Fatalf("expected lock to be nil, got: %#v", l) + } +} + +func TestAnalyzerDeriveManifestAndLockDoesNotExist(t *testing.T) { + h := test.NewHelper(t) + defer h.Cleanup() + + h.TempDir("dep") + + a := Analyzer{} + + m, l, err := a.DeriveManifestAndLock(h.Path("dep"), "my/fake/project") + if m != nil || l != nil || err != nil { + t.Fatalf("expected manifest & lock & err to be nil: m -> %#v l -> %#v err-> %#v", m, l, err) + } +} + +func TestAnalyzerDeriveManifestAndLockCannotOpen(t *testing.T) { + h := test.NewHelper(t) + defer h.Cleanup() + + h.TempDir("dep") + + // Simulate an inaccessible manifest file. + h.TempFile(filepath.Join("dep", ManifestName), "") + closer, err := makeUnreadable(filepath.Join(h.Path("dep"), ManifestName)) + if err != nil { + t.Fatal(err) + } + defer closer.Close() + + a := Analyzer{} + + // Verify that the solver rejects the manifest, rather than treating it as + // offering no constraints. + m, l, err := a.DeriveManifestAndLock(h.Path("dep"), "my/fake/project") + if m != nil || l != nil || err == nil { + t.Fatalf("expected manifest & lock to be nil, err to be not nil: m -> %#v l -> %#v err -> %#v", m, l, err) + } +} + +func TestAnalyzerDeriveManifestAndLockInvalidManifest(t *testing.T) { + h := test.NewHelper(t) + defer h.Cleanup() + + h.TempDir("dep") + + // Create a manifest with invalid contents + h.TempFile(filepath.Join("dep", ManifestName), "invalid manifest") + + a := Analyzer{} + + m, l, err := a.DeriveManifestAndLock(h.Path("dep"), "my/fake/project") + if m != nil || l != nil || err == nil { + t.Fatalf("expected manifest & lock & err to be nil: m -> %#v l -> %#v err-> %#v", m, l, err) + } +} + +func TestAnalyzerInfo(t *testing.T) { + a := Analyzer{} + + info := a.Info() + + if info.Name != "dep" || info.Version != 1 { + t.Fatalf("expected name to be 'dep' and version to be 1: name -> %q vers -> %d", info.Name, info.Version) + } +} diff --git a/vendor/github.com/golang/dep/analyzer_windows_test.go b/vendor/github.com/golang/dep/analyzer_windows_test.go new file mode 100644 index 00000000..96eb02a4 --- /dev/null +++ b/vendor/github.com/golang/dep/analyzer_windows_test.go @@ -0,0 +1,33 @@ +// Copyright 2017 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 dep + +import ( + "io" + "os" + "syscall" +) + +// makeUnreadable opens the file at path in exclusive mode. A file opened in +// exclusive mode cannot be opened again until the exclusive mode file handle +// is closed. +func makeUnreadable(path string) (io.Closer, error) { + if len(path) == 0 { + return nil, syscall.ERROR_FILE_NOT_FOUND + } + pathp, err := syscall.UTF16PtrFromString(path) + if err != nil { + return nil, err + } + access := uint32(syscall.GENERIC_READ | syscall.GENERIC_WRITE) + sharemode := uint32(0) // no sharing == exclusive mode + sa := (*syscall.SecurityAttributes)(nil) + createmode := uint32(syscall.OPEN_EXISTING) + h, err := syscall.CreateFile(pathp, access, sharemode, sa, createmode, syscall.FILE_ATTRIBUTE_NORMAL, 0) + if err != nil { + return nil, err + } + return os.NewFile(uintptr(h), path), nil +} diff --git a/vendor/github.com/golang/dep/appveyor.yml b/vendor/github.com/golang/dep/appveyor.yml new file mode 100644 index 00000000..fb07653a --- /dev/null +++ b/vendor/github.com/golang/dep/appveyor.yml @@ -0,0 +1,34 @@ +version: "{build}" + +# Source Config + +clone_folder: c:\gopath\src\github.com\golang\dep + +# Build host + +environment: + GOPATH: c:\gopath + DEPTESTBYPASS501: 1 + GOVERSION: 1.8 + +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 + - choco install bzr + - set Path=c:\go\bin;c:\gopath\bin;C:\Program Files (x86)\Bazaar\;C:\Program Files\Mercurial\%Path% + - go version + - go env + +build: false +deploy: false + +test_script: + - go build github.com/golang/dep/cmd/dep + - for /f "" %%G in ('go list github.com/golang/dep/... ^| find /i /v "/vendor/"') do ( go test %%G & IF ERRORLEVEL == 1 EXIT 1) diff --git a/vendor/github.com/golang/dep/cmd/dep/dep_test.go b/vendor/github.com/golang/dep/cmd/dep/dep_test.go new file mode 100644 index 00000000..be53f4cc --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/dep_test.go @@ -0,0 +1,47 @@ +// Copyright 2016 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 main + +import ( + "fmt" + "os" + "os/exec" + "path/filepath" + "testing" + + "github.com/golang/dep/internal/test" +) + +// The TestMain function creates a dep command for testing purposes and +// deletes it after the tests have been run. +// Most of this is taken from https://github.com/golang/go/blob/master/src/cmd/go/go_test.go and reused here. +func TestMain(m *testing.M) { + args := []string{"build", "-o", "testdep" + test.ExeSuffix} + out, err := exec.Command("go", args...).CombinedOutput() + if err != nil { + fmt.Fprintf(os.Stderr, "building testdep failed: %v\n%s", err, out) + os.Exit(2) + } + + // Don't let these environment variables confuse the test. + os.Unsetenv("GOPATH") + os.Unsetenv("GIT_ALLOW_PROTOCOL") + if home, ccacheDir := os.Getenv("HOME"), os.Getenv("CCACHE_DIR"); home != "" && ccacheDir == "" { + // On some systems the default C compiler is ccache. + // Setting HOME to a non-existent directory will break + // those systems. Set CCACHE_DIR to cope. Issue 17668. + os.Setenv("CCACHE_DIR", filepath.Join(home, ".ccache")) + } + os.Setenv("HOME", "/test-dep-home-does-not-exist") + if os.Getenv("GOCACHE") == "" { + os.Setenv("GOCACHE", "off") // because $HOME is gone + } + + r := m.Run() + + os.Remove("testdep" + test.ExeSuffix) + + os.Exit(r) +} diff --git a/vendor/github.com/golang/dep/cmd/dep/doc.go b/vendor/github.com/golang/dep/cmd/dep/doc.go new file mode 100644 index 00000000..7d5afdce --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/doc.go @@ -0,0 +1,143 @@ +// Copyright 2017 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. + +// DO NOT EDIT THIS FILE. GENERATED BY mkdoc.sh. +// Edit the documentation in other files and rerun mkdoc.sh to generate this one. + +// Dep is a tool for managing dependencies for Go projects +// +// Usage: "dep [command]" +// +// Commands: +// +// init Initialize a new project with manifest and lock files +// status Report the status of the project's dependencies +// ensure Ensure a dependency is safely vendored in the project +// prune Prune the vendor tree of unused packages +// version Show the dep version information +// +// Examples: +// dep init set up a new project +// dep ensure install the project's dependencies +// dep ensure -update update the locked versions of all dependencies +// dep ensure -add github.com/pkg/errors add a dependency to the project +// +// Use "dep help [command]" for more information about a command. +// +// Initialize a new project with manifest and lock files +// +// Usage: +// +// init [root] +// +// Initialize the project at filepath root by parsing its dependencies, writing +// manifest and lock files, and vendoring the dependencies. If root isn't +// specified, use the current directory. +// +// When configuration for another dependency management tool is detected, it is +// imported into the initial manifest and lock. Use the -skip-tools flag to +// disable this behavior. The following external tools are supported: +// glide, godep, vndr, govend, gb, gvt, glock. +// +// Any dependencies that are not constrained by external configuration use the +// GOPATH analysis below. +// +// By default, the dependencies are resolved over the network. A version will be +// selected from the versions available from the upstream source per the following +// algorithm: +// +// - Tags conforming to semver (sorted by semver rules) +// - Default branch(es) (sorted lexicographically) +// - Non-semver tags (sorted lexicographically) +// +// An alternate mode can be activated by passing -gopath. In this mode, the version +// of each dependency will reflect the current state of the GOPATH. If a dependency +// doesn't exist in the GOPATH, a version will be selected based on the above +// network version selection algorithm. +// +// A Gopkg.toml file will be written with inferred version constraints for all +// direct dependencies. Gopkg.lock will be written with precise versions, and +// vendor/ will be populated with the precise versions written to Gopkg.lock. +// +// +// Report the status of the project's dependencies +// +// Usage: +// +// status [package...] +// +// With no arguments, print the status of each dependency of the project. +// +// PROJECT Import path +// CONSTRAINT Version constraint, from the manifest +// VERSION Version chosen, from the lock +// REVISION VCS revision of the chosen version +// LATEST Latest VCS revision available +// PKGS USED Number of packages from this project that are actually used +// +// With one or more explicitly specified packages, or with the -detailed flag, +// print an extended status output for each dependency of the project. +// +// TODO Another column description +// FOOBAR Another column description +// +// Status returns exit code zero if all dependencies are in a "good state". +// +// +// Ensure a dependency is safely vendored in the project +// +// Usage: +// +// ensure [-update | -add] [-no-vendor | -vendor-only] [-dry-run] [...] +// +// Project spec: +// +// [:alt source URL][@] +// +// +// Ensure gets a project into a complete, reproducible, and likely compilable state: +// +// * All non-stdlib imports are fulfilled +// * All rules in Gopkg.toml are respected +// * Gopkg.lock records precise versions for all dependencies +// * vendor/ is populated according to Gopkg.lock +// +// Ensure has fast techniques to determine that some of these steps may be +// unnecessary. If that determination is made, ensure may skip some steps. Flags +// may be passed to bypass these checks; -vendor-only will allow an out-of-date +// Gopkg.lock to populate vendor/, and -no-vendor will update Gopkg.lock (if +// needed), but never touch vendor/. +// +// The effect of passing project spec arguments varies slightly depending on the +// combination of flags that are passed. +// +// +// Examples: +// +// dep ensure Populate vendor from existing Gopkg.toml and Gopkg.lock +// dep ensure -add github.com/pkg/foo Introduce a named dependency at its newest version +// dep ensure -add github.com/pkg/foo@^1.0.1 Introduce a named dependency with a particular constraint +// +// For more detailed usage examples, see dep ensure -examples. +// +// +// Prune the vendor tree of unused packages +// +// Usage: +// +// prune +// +// Prune is used to remove unused packages from your vendor tree. +// +// STABILITY NOTICE: this command creates problems for vendor/ verification. As +// such, it may be removed and/or moved out into a separate project later on. +// +// +// Show the dep version information +// +// Usage: +// +// version +// +package main diff --git a/vendor/github.com/golang/dep/cmd/dep/ensure.go b/vendor/github.com/golang/dep/cmd/dep/ensure.go new file mode 100644 index 00000000..f2cd7081 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/ensure.go @@ -0,0 +1,917 @@ +// Copyright 2016 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 main + +import ( + "bytes" + "context" + "flag" + "fmt" + "go/build" + "io/ioutil" + "log" + "os" + "path/filepath" + "sort" + "strings" + "sync" + + "github.com/golang/dep" + "github.com/golang/dep/gps" + "github.com/golang/dep/gps/paths" + "github.com/golang/dep/gps/pkgtree" + "github.com/pkg/errors" +) + +const ensureShortHelp = `Ensure a dependency is safely vendored in the project` +const ensureLongHelp = ` +Project spec: + + [:alt source URL][@] + + +Ensure gets a project into a complete, reproducible, and likely compilable state: + + * All non-stdlib imports are fulfilled + * All rules in Gopkg.toml are respected + * Gopkg.lock records precise versions for all dependencies + * vendor/ is populated according to Gopkg.lock + +Ensure has fast techniques to determine that some of these steps may be +unnecessary. If that determination is made, ensure may skip some steps. Flags +may be passed to bypass these checks; -vendor-only will allow an out-of-date +Gopkg.lock to populate vendor/, and -no-vendor will update Gopkg.lock (if +needed), but never touch vendor/. + +The effect of passing project spec arguments varies slightly depending on the +combination of flags that are passed. + + +Examples: + + dep ensure Populate vendor from existing Gopkg.toml and Gopkg.lock + dep ensure -add github.com/pkg/foo Introduce a named dependency at its newest version + dep ensure -add github.com/pkg/foo@^1.0.1 Introduce a named dependency with a particular constraint + +For more detailed usage examples, see dep ensure -examples. +` +const ensureExamples = ` +dep ensure + + Solve the project's dependency graph, and place all dependencies in the + vendor folder. If a dependency is in the lock file, use the version + specified there. Otherwise, use the most recent version that can satisfy the + constraints in the manifest file. + +dep ensure -vendor-only + + Write vendor/ from an existing Gopkg.lock file, without first verifying that + the lock is in sync with imports and Gopkg.toml. (This may be useful for + e.g. strategically layering a Docker images) + +dep ensure -add github.com/pkg/foo github.com/pkg/foo/bar + + Introduce one or more dependencies, at their newest version, ensuring that + specific packages are present in Gopkg.lock and vendor/. Also, append a + corresponding constraint to Gopkg.toml. + + Note: packages introduced in this way will disappear on the next "dep + ensure" if an import statement is not added first. + +dep ensure -add github.com/pkg/foo/subpkg@1.0.0 bitbucket.org/pkg/bar/baz@master + + Append version constraints to Gopkg.toml for one or more packages, if no + such rules already exist. + + If the named packages are not already imported, also ensure they are present + in Gopkg.lock and vendor/. As in the preceding example, packages introduced + in this way will disappear on the next "dep ensure" if an import statement + is not added first. + +dep ensure -add github.com/pkg/foo:git.internal.com/alt/foo + + Specify an alternate location to treat as the upstream source for a dependency. + +dep ensure -update github.com/pkg/foo github.com/pkg/bar + + Update a list of dependencies to the latest versions allowed by Gopkg.toml, + ignoring any versions recorded in Gopkg.lock. Write the results to + Gopkg.lock and vendor/. + +dep ensure -update + + Update all dependencies to the latest versions allowed by Gopkg.toml, + ignoring any versions recorded in Gopkg.lock. Update the lock file with any + changes. (NOTE: Not recommended. Updating one/some dependencies at a time is + preferred.) + +dep ensure -update -no-vendor + + As above, but only modify Gopkg.lock; leave vendor/ unchanged. + +dep ensure -no-vendor -dry-run + + This fails with a non zero exit code if Gopkg.lock is not up to date with + the Gopkg.toml or the project imports. It can be useful to run this during + CI to check if Gopkg.lock is up to date. + +` + +var ( + errUpdateArgsValidation = errors.New("update arguments validation failed") + errAddDepsFailed = errors.New("adding dependencies failed") +) + +func (cmd *ensureCommand) Name() string { return "ensure" } +func (cmd *ensureCommand) Args() string { + return "[-update | -add] [-no-vendor | -vendor-only] [-dry-run] [-v] [...]" +} +func (cmd *ensureCommand) ShortHelp() string { return ensureShortHelp } +func (cmd *ensureCommand) LongHelp() string { return ensureLongHelp } +func (cmd *ensureCommand) Hidden() bool { return false } + +func (cmd *ensureCommand) Register(fs *flag.FlagSet) { + fs.BoolVar(&cmd.examples, "examples", false, "print detailed usage examples") + fs.BoolVar(&cmd.update, "update", false, "update the named dependencies (or all, if none are named) in Gopkg.lock to the latest allowed by Gopkg.toml") + fs.BoolVar(&cmd.add, "add", false, "add new dependencies, or populate Gopkg.toml with constraints for existing dependencies") + fs.BoolVar(&cmd.vendorOnly, "vendor-only", false, "populate vendor/ from Gopkg.lock without updating it first") + fs.BoolVar(&cmd.noVendor, "no-vendor", false, "update Gopkg.lock (if needed), but do not update vendor/") + fs.BoolVar(&cmd.dryRun, "dry-run", false, "only report the changes that would be made") +} + +type ensureCommand struct { + examples bool + update bool + add bool + noVendor bool + vendorOnly bool + dryRun bool +} + +func (cmd *ensureCommand) Run(ctx *dep.Ctx, args []string) error { + if cmd.examples { + ctx.Err.Println(strings.TrimSpace(ensureExamples)) + return nil + } + + if err := cmd.validateFlags(); err != nil { + return err + } + + p, err := ctx.LoadProject() + if err != nil { + return err + } + + sm, err := ctx.SourceManager() + if err != nil { + return err + } + sm.UseDefaultSignalHandling() + defer sm.Release() + + if err := dep.ValidateProjectRoots(ctx, p.Manifest, sm); err != nil { + return err + } + + params := p.MakeParams() + if ctx.Verbose { + params.TraceLogger = ctx.Err + } + + if cmd.vendorOnly { + return cmd.runVendorOnly(ctx, args, p, sm, params) + } + + params.RootPackageTree, err = p.ParseRootPackageTree() + if err != nil { + return err + } + + if fatal, err := checkErrors(params.RootPackageTree.Packages, p.Manifest.IgnoredPackages()); err != nil { + if fatal { + return err + } else if ctx.Verbose { + ctx.Out.Println(err) + } + } + if ineffs := p.FindIneffectualConstraints(sm); len(ineffs) > 0 { + ctx.Err.Printf("Warning: the following project(s) have [[constraint]] stanzas in %s:\n\n", dep.ManifestName) + for _, ineff := range ineffs { + ctx.Err.Println(" ✗ ", ineff) + } + // TODO(sdboyer) lazy wording, it does not mention ignores at all + ctx.Err.Printf("\nHowever, these projects are not direct dependencies of the current project:\n") + ctx.Err.Printf("they are not imported in any .go files, nor are they in the 'required' list in\n") + ctx.Err.Printf("%s. Dep only applies [[constraint]] rules to direct dependencies, so\n", dep.ManifestName) + ctx.Err.Printf("these rules will have no effect.\n\n") + ctx.Err.Printf("Either import/require packages from these projects so that they become direct\n") + ctx.Err.Printf("dependencies, or convert each [[constraint]] to an [[override]] to enforce rules\n") + ctx.Err.Printf("on these projects, if they happen to be transitive dependencies,\n\n") + } + + if cmd.add { + return cmd.runAdd(ctx, args, p, sm, params) + } else if cmd.update { + return cmd.runUpdate(ctx, args, p, sm, params) + } + return cmd.runDefault(ctx, args, p, sm, params) +} + +func (cmd *ensureCommand) validateFlags() error { + if cmd.add && cmd.update { + return errors.New("cannot pass both -add and -update") + } + + if cmd.vendorOnly { + if cmd.update { + return errors.New("-vendor-only makes -update a no-op; cannot pass them together") + } + if cmd.add { + return errors.New("-vendor-only makes -add a no-op; cannot pass them together") + } + if cmd.noVendor { + // TODO(sdboyer) can't think of anything not snarky right now + return errors.New("really?") + } + } + return nil +} + +func (cmd *ensureCommand) vendorBehavior() dep.VendorBehavior { + if cmd.noVendor { + return dep.VendorNever + } + return dep.VendorOnChanged +} + +func (cmd *ensureCommand) runDefault(ctx *dep.Ctx, args []string, p *dep.Project, sm gps.SourceManager, params gps.SolveParameters) error { + // Bare ensure doesn't take any args. + if len(args) != 0 { + return errors.New("dep ensure only takes spec arguments with -add or -update") + } + + if err := ctx.ValidateParams(sm, params); err != nil { + return err + } + + solver, err := gps.Prepare(params, sm) + if err != nil { + return errors.Wrap(err, "prepare solver") + } + + if p.Lock != nil && bytes.Equal(p.Lock.InputsDigest(), solver.HashInputs()) { + // Memo matches, so there's probably nothing to do. + if ctx.Verbose { + ctx.Out.Printf("%s was already in sync with imports and %s\n", dep.LockName, dep.ManifestName) + } + + if cmd.noVendor { + // The user said not to touch vendor/, so definitely nothing to do. + return nil + } + + // TODO(sdboyer) The desired behavior at this point is to determine + // whether it's necessary to write out vendor, or if it's already + // consistent with the lock. However, we haven't yet determined what + // that "verification" is supposed to look like (#121); in the meantime, + // we unconditionally write out vendor/ so that `dep ensure`'s behavior + // is maximally compatible with what it will eventually become. + sw, err := dep.NewSafeWriter(nil, p.Lock, p.Lock, dep.VendorAlways, p.Manifest.PruneOptions) + if err != nil { + return err + } + + if cmd.dryRun { + return sw.PrintPreparedActions(ctx.Out, ctx.Verbose) + } + + logger := ctx.Err + if !ctx.Verbose { + logger = log.New(ioutil.Discard, "", 0) + } + return errors.WithMessage(sw.Write(p.AbsRoot, sm, true, logger), "grouped write of manifest, lock and vendor") + } + + if cmd.noVendor && cmd.dryRun { + return errors.New("Gopkg.lock was not up to date") + } + + solution, err := solver.Solve(context.TODO()) + if err != nil { + return handleAllTheFailuresOfTheWorld(err) + } + + sw, err := dep.NewSafeWriter(nil, p.Lock, dep.LockFromSolution(solution), cmd.vendorBehavior(), p.Manifest.PruneOptions) + if err != nil { + return err + } + if cmd.dryRun { + return sw.PrintPreparedActions(ctx.Out, ctx.Verbose) + } + + logger := ctx.Err + if !ctx.Verbose { + logger = log.New(ioutil.Discard, "", 0) + } + return errors.Wrap(sw.Write(p.AbsRoot, sm, false, logger), "grouped write of manifest, lock and vendor") +} + +func (cmd *ensureCommand) runVendorOnly(ctx *dep.Ctx, args []string, p *dep.Project, sm gps.SourceManager, params gps.SolveParameters) error { + if len(args) != 0 { + return errors.Errorf("dep ensure -vendor-only only populates vendor/ from %s; it takes no spec arguments", dep.LockName) + } + + if p.Lock == nil { + return errors.Errorf("no %s exists from which to populate vendor/", dep.LockName) + } + // Pass the same lock as old and new so that the writer will observe no + // difference and choose not to write it out. + sw, err := dep.NewSafeWriter(nil, p.Lock, p.Lock, dep.VendorAlways, p.Manifest.PruneOptions) + if err != nil { + return err + } + + if cmd.dryRun { + return sw.PrintPreparedActions(ctx.Out, ctx.Verbose) + } + + logger := ctx.Err + if !ctx.Verbose { + logger = log.New(ioutil.Discard, "", 0) + } + return errors.WithMessage(sw.Write(p.AbsRoot, sm, true, logger), "grouped write of manifest, lock and vendor") +} + +func (cmd *ensureCommand) runUpdate(ctx *dep.Ctx, args []string, p *dep.Project, sm gps.SourceManager, params gps.SolveParameters) error { + if p.Lock == nil { + return errors.Errorf("-update works by updating the versions recorded in %s, but %s does not exist", dep.LockName, dep.LockName) + } + + if err := ctx.ValidateParams(sm, params); err != nil { + return err + } + + // We'll need to discard this prepared solver as later work changes params, + // but solver preparation is cheap and worth doing up front in order to + // perform the fastpath check of hash comparison. + solver, err := gps.Prepare(params, sm) + if err != nil { + return errors.Wrap(err, "fastpath solver prepare") + } + + // Compare the hashes. If they're not equal, bail out and ask the user to + // run a straight `dep ensure` before updating. This is handholding the + // user a bit, but the extra effort required is minimal, and it ensures the + // user is isolating variables in the event of solve problems (was it the + // "pending" changes, or the -update that caused the problem?). + if !bytes.Equal(p.Lock.InputsDigest(), solver.HashInputs()) { + ctx.Out.Printf("Warning: %s is out of sync with %s or the project's imports.", dep.LockName, dep.ManifestName) + } + + // When -update is specified without args, allow every dependency to change + // versions, regardless of the lock file. + if len(args) == 0 { + params.ChangeAll = true + } + + if err := validateUpdateArgs(ctx, args, p, sm, ¶ms); err != nil { + return err + } + + // Re-prepare a solver now that our params are complete. + solver, err = gps.Prepare(params, sm) + if err != nil { + return errors.Wrap(err, "fastpath solver prepare") + } + solution, err := solver.Solve(context.TODO()) + if err != nil { + // TODO(sdboyer) special handling for warning cases as described in spec + // - e.g., named projects did not upgrade even though newer versions + // were available. + return handleAllTheFailuresOfTheWorld(err) + } + + sw, err := dep.NewSafeWriter(nil, p.Lock, dep.LockFromSolution(solution), cmd.vendorBehavior(), p.Manifest.PruneOptions) + if err != nil { + return err + } + if cmd.dryRun { + return sw.PrintPreparedActions(ctx.Out, ctx.Verbose) + } + + logger := ctx.Err + if !ctx.Verbose { + logger = log.New(ioutil.Discard, "", 0) + } + return errors.Wrap(sw.Write(p.AbsRoot, sm, false, logger), "grouped write of manifest, lock and vendor") +} + +func (cmd *ensureCommand) runAdd(ctx *dep.Ctx, args []string, p *dep.Project, sm gps.SourceManager, params gps.SolveParameters) error { + if len(args) == 0 { + return errors.New("must specify at least one project or package to -add") + } + + if err := ctx.ValidateParams(sm, params); err != nil { + return err + } + + // We'll need to discard this prepared solver as later work changes params, + // but solver preparation is cheap and worth doing up front in order to + // perform the fastpath check of hash comparison. + solver, err := gps.Prepare(params, sm) + if err != nil { + return errors.Wrap(err, "fastpath solver prepare") + } + + // Compare the hashes. If they're not equal, bail out and ask the user to + // run a straight `dep ensure` before updating. This is handholding the + // user a bit, but the extra effort required is minimal, and it ensures the + // user is isolating variables in the event of solve problems (was it the + // "pending" changes, or the -add that caused the problem?). + if p.Lock != nil && !bytes.Equal(p.Lock.InputsDigest(), solver.HashInputs()) { + ctx.Out.Printf("Warning: %s is out of sync with %s or the project's imports.", dep.LockName, dep.ManifestName) + } + + rm, _ := params.RootPackageTree.ToReachMap(true, true, false, p.Manifest.IgnoredPackages()) + + // TODO(sdboyer) re-enable this once we ToReachMap() intelligently filters out normally-excluded (_*, .*), dirs from errmap + //rm, errmap := params.RootPackageTree.ToReachMap(true, true, false, p.Manifest.IgnoredPackages()) + // Having some problematic internal packages isn't cause for termination, + // but the user needs to be warned. + //for fail, err := range errmap { + //if _, is := err.Err.(*build.NoGoError); !is { + //ctx.Err.Printf("Warning: %s, %s", fail, err) + //} + //} + + // Compile unique sets of 1) all external packages imported or required, and + // 2) the project roots under which they fall. + exmap := make(map[string]bool) + exrmap := make(map[gps.ProjectRoot]bool) + + for _, ex := range append(rm.FlattenFn(paths.IsStandardImportPath), p.Manifest.Required...) { + exmap[ex] = true + root, err := sm.DeduceProjectRoot(ex) + if err != nil { + // This should be very uncommon to hit, as it entails that we + // couldn't deduce the root for an import, but that some previous + // solve run WAS able to deduce the root. It's most likely to occur + // if the user has e.g. not connected to their organization's VPN, + // and thus cannot access an internal go-get metadata service. + return errors.Wrapf(err, "could not deduce project root for %s", ex) + } + exrmap[root] = true + } + + // Note: these flags are only partially used by the latter parts of the + // algorithm; rather, it relies on inference. However, they remain in their + // entirety as future needs may make further use of them, being a handy, + // terse way of expressing the original context of the arg inputs. + type addType uint8 + const ( + // Straightforward case - this induces a temporary require, and thus + // a warning message about it being ephemeral. + isInManifest addType = 1 << iota + // If solving works, we'll pull this constraint from the in-memory + // manifest (where we recorded it earlier) and then append it to the + // manifest on disk. + isInImportsWithConstraint + // If solving works, we'll extract a constraint from the lock and + // append it into the manifest on disk, similar to init's behavior. + isInImportsNoConstraint + // This gets a message AND a hoist from the solution up into the + // manifest on disk. + isInNeither + ) + + type addInstruction struct { + id gps.ProjectIdentifier + ephReq map[string]bool + constraint gps.Constraint + typ addType + } + addInstructions := make(map[gps.ProjectRoot]addInstruction) + + // A mutex for limited access to addInstructions by goroutines. + var mutex sync.Mutex + + // Channel for receiving all the errors. + errCh := make(chan error, len(args)) + + var wg sync.WaitGroup + + ctx.Out.Println("Fetching sources...") + + for i, arg := range args { + wg.Add(1) + + if ctx.Verbose { + ctx.Err.Printf("(%d/%d) %s\n", i+1, len(args), arg) + } + + go func(arg string) { + defer wg.Done() + + pc, path, err := getProjectConstraint(arg, sm) + if err != nil { + // TODO(sdboyer) ensure these errors are contextualized in a sensible way for -add + errCh <- err + return + } + + // check if the the parsed path is the current root path + if strings.EqualFold(string(p.ImportRoot), string(pc.Ident.ProjectRoot)) { + errCh <- errors.New("cannot add current project to itself") + return + } + + inManifest := p.Manifest.HasConstraintsOn(pc.Ident.ProjectRoot) + inImports := exmap[string(pc.Ident.ProjectRoot)] + if inManifest && inImports { + errCh <- errors.Errorf("nothing to -add, %s is already in %s and the project's direct imports or required list", pc.Ident.ProjectRoot, dep.ManifestName) + return + } + + err = sm.SyncSourceFor(pc.Ident) + if err != nil { + errCh <- errors.Wrapf(err, "failed to fetch source for %s", pc.Ident.ProjectRoot) + return + } + + someConstraint := !gps.IsAny(pc.Constraint) || pc.Ident.Source != "" + + // Obtain a lock for addInstructions + mutex.Lock() + defer mutex.Unlock() + instr, has := addInstructions[pc.Ident.ProjectRoot] + if has { + // Multiple packages from the same project were specified as + // arguments; make sure they agree on declared constraints. + // TODO(sdboyer) until we have a general method for checking constraint equality, only allow one to declare + if someConstraint { + if !gps.IsAny(instr.constraint) || instr.id.Source != "" { + errCh <- errors.Errorf("can only specify rules once per project being added; rules were given at least twice for %s", pc.Ident.ProjectRoot) + return + } + instr.constraint = pc.Constraint + instr.id = pc.Ident + } + } else { + instr.ephReq = make(map[string]bool) + instr.constraint = pc.Constraint + instr.id = pc.Ident + } + + if inManifest { + if someConstraint { + errCh <- errors.Errorf("%s already contains rules for %s, cannot specify a version constraint or alternate source", dep.ManifestName, path) + return + } + + instr.ephReq[path] = true + instr.typ |= isInManifest + } else if inImports { + if !someConstraint { + if exmap[path] { + errCh <- errors.Errorf("%s is already imported or required, so -add is only valid with a constraint", path) + return + } + + // No constraints, but the package isn't imported; require it. + // TODO(sdboyer) this case seems like it's getting overly specific and risks muddying the water more than it helps + instr.ephReq[path] = true + instr.typ |= isInImportsNoConstraint + } else { + // Don't require on this branch if the path was a ProjectRoot; + // most common here will be the user adding constraints to + // something they already imported, and if they specify the + // root, there's a good chance they don't actually want to + // require the project's root package, but are just trying to + // indicate which project should receive the constraints. + if !exmap[path] && string(pc.Ident.ProjectRoot) != path { + instr.ephReq[path] = true + } + instr.typ |= isInImportsWithConstraint + } + } else { + instr.typ |= isInNeither + instr.ephReq[path] = true + } + + addInstructions[pc.Ident.ProjectRoot] = instr + }(arg) + } + + wg.Wait() + close(errCh) + + // Newline after printing the fetching source output. + ctx.Err.Println() + + // Log all the errors. + if len(errCh) > 0 { + ctx.Err.Printf("Failed to add the dependencies:\n\n") + for err := range errCh { + ctx.Err.Println(" ✗", err.Error()) + } + ctx.Err.Println() + return errAddDepsFailed + } + + // We're now sure all of our add instructions are individually and mutually + // valid, so it's safe to begin modifying the input parameters. + for pr, instr := range addInstructions { + // The arg processing logic above only adds to the ephReq list if + // that package definitely needs to be on that list, so we don't + // need to check instr.typ here - if it's in instr.ephReq, it + // definitely needs to be added to the manifest's required list. + for path := range instr.ephReq { + p.Manifest.Required = append(p.Manifest.Required, path) + } + + // Only two branches can possibly be adding rules, though the + // isInNeither case may or may not have an empty constraint. + if instr.typ&(isInNeither|isInImportsWithConstraint) != 0 { + p.Manifest.Constraints[pr] = gps.ProjectProperties{ + Source: instr.id.Source, + Constraint: instr.constraint, + } + } + } + + // Re-prepare a solver now that our params are complete. + solver, err = gps.Prepare(params, sm) + if err != nil { + return errors.Wrap(err, "fastpath solver prepare") + } + solution, err := solver.Solve(context.TODO()) + if err != nil { + // TODO(sdboyer) detect if the failure was specifically about some of the -add arguments + return handleAllTheFailuresOfTheWorld(err) + } + + // Prep post-actions and feedback from adds. + var reqlist []string + appender := dep.NewManifest() + + for pr, instr := range addInstructions { + for path := range instr.ephReq { + reqlist = append(reqlist, path) + } + + if instr.typ&isInManifest == 0 { + var pp gps.ProjectProperties + var found bool + for _, proj := range solution.Projects() { + // We compare just ProjectRoot instead of the whole + // ProjectIdentifier here because an empty source on the input side + // could have been converted into a source by the solver. + if proj.Ident().ProjectRoot == pr { + found = true + pp = getProjectPropertiesFromVersion(proj.Version()) + break + } + } + if !found { + panic(fmt.Sprintf("unreachable: solution did not contain -add argument %s, but solver did not fail", pr)) + } + pp.Source = instr.id.Source + + if !gps.IsAny(instr.constraint) { + pp.Constraint = instr.constraint + } + appender.Constraints[pr] = pp + } + } + + extra, err := appender.MarshalTOML() + if err != nil { + return errors.Wrap(err, "could not marshal manifest into TOML") + } + sort.Strings(reqlist) + + sw, err := dep.NewSafeWriter(nil, p.Lock, dep.LockFromSolution(solution), dep.VendorOnChanged, p.Manifest.PruneOptions) + if err != nil { + return err + } + + if cmd.dryRun { + return sw.PrintPreparedActions(ctx.Out, ctx.Verbose) + } + + logger := ctx.Err + if !ctx.Verbose { + logger = log.New(ioutil.Discard, "", 0) + } + if err := errors.Wrap(sw.Write(p.AbsRoot, sm, true, logger), "grouped write of manifest, lock and vendor"); err != nil { + return err + } + + // FIXME(sdboyer) manifest writes ABSOLUTELY need verification - follow up! + f, err := os.OpenFile(filepath.Join(p.AbsRoot, dep.ManifestName), os.O_APPEND|os.O_WRONLY, 0666) + if err != nil { + return errors.Wrapf(err, "opening %s failed", dep.ManifestName) + } + + if _, err := f.Write(extra); err != nil { + f.Close() + return errors.Wrapf(err, "writing to %s failed", dep.ManifestName) + } + + switch len(reqlist) { + case 0: + // nothing to tell the user + case 1: + if cmd.noVendor { + ctx.Out.Printf("%q is not imported by your project, and has been temporarily added to %s.\n", reqlist[0], dep.LockName) + ctx.Out.Printf("If you run \"dep ensure\" again before actually importing it, it will disappear from %s. Running \"dep ensure -vendor-only\" is safe, and will guarantee it is present in vendor/.", dep.LockName) + } else { + ctx.Out.Printf("%q is not imported by your project, and has been temporarily added to %s and vendor/.\n", reqlist[0], dep.LockName) + ctx.Out.Printf("If you run \"dep ensure\" again before actually importing it, it will disappear from %s and vendor/.", dep.LockName) + } + default: + if cmd.noVendor { + ctx.Out.Printf("The following packages are not imported by your project, and have been temporarily added to %s:\n", dep.LockName) + ctx.Out.Printf("\t%s\n", strings.Join(reqlist, "\n\t")) + ctx.Out.Printf("If you run \"dep ensure\" again before actually importing them, they will disappear from %s. Running \"dep ensure -vendor-only\" is safe, and will guarantee they are present in vendor/.", dep.LockName) + } else { + ctx.Out.Printf("The following packages are not imported by your project, and have been temporarily added to %s and vendor/:\n", dep.LockName) + ctx.Out.Printf("\t%s\n", strings.Join(reqlist, "\n\t")) + ctx.Out.Printf("If you run \"dep ensure\" again before actually importing them, they will disappear from %s and vendor/.", dep.LockName) + } + } + + return errors.Wrapf(f.Close(), "closing %s", dep.ManifestName) +} + +func getProjectConstraint(arg string, sm gps.SourceManager) (gps.ProjectConstraint, string, error) { + emptyPC := gps.ProjectConstraint{ + Constraint: gps.Any(), // default to any; avoids panics later + } + + // try to split on '@' + // When there is no `@`, use any version + var versionStr string + atIndex := strings.Index(arg, "@") + if atIndex > 0 { + parts := strings.SplitN(arg, "@", 2) + arg = parts[0] + versionStr = parts[1] + } + + // TODO: if we decide to keep equals..... + + // split on colon if there is a network location + var source string + colonIndex := strings.Index(arg, ":") + if colonIndex > 0 { + parts := strings.SplitN(arg, ":", 2) + arg = parts[0] + source = parts[1] + } + + pr, err := sm.DeduceProjectRoot(arg) + if err != nil { + return emptyPC, "", errors.Wrapf(err, "could not infer project root from dependency path: %s", arg) // this should go through to the user + } + + pi := gps.ProjectIdentifier{ProjectRoot: pr, Source: source} + c, err := sm.InferConstraint(versionStr, pi) + if err != nil { + return emptyPC, "", err + } + return gps.ProjectConstraint{Ident: pi, Constraint: c}, arg, nil +} + +func checkErrors(m map[string]pkgtree.PackageOrErr, ignore *pkgtree.IgnoredRuleset) (fatal bool, err error) { + var ( + noGoErrors int + pkgtreeErrors = make(pkgtreeErrs, 0, len(m)) + ) + + for ip, poe := range m { + if ignore.IsIgnored(ip) { + continue + } + + if poe.Err != nil { + switch poe.Err.(type) { + case *build.NoGoError: + noGoErrors++ + default: + pkgtreeErrors = append(pkgtreeErrors, poe.Err) + } + } + } + + // If pkgtree was empty or all dirs lacked any Go code, return an error. + if len(m) == 0 || len(m) == noGoErrors { + return true, errors.New("no dirs contained any Go code") + } + + // If all dirs contained build errors, return an error. + if len(m) == len(pkgtreeErrors) { + return true, errors.New("all dirs contained build errors") + } + + // If all directories either had no Go files or caused a build error, return an error. + if len(m) == len(pkgtreeErrors)+noGoErrors { + return true, pkgtreeErrors + } + + // If m contained some errors, return a warning with those errors. + if len(pkgtreeErrors) > 0 { + return false, pkgtreeErrors + } + + return false, nil +} + +type pkgtreeErrs []error + +func (e pkgtreeErrs) Error() string { + errs := make([]string, 0, len(e)) + + for _, err := range e { + errs = append(errs, err.Error()) + } + + return fmt.Sprintf("found %d errors in the package tree:\n%s", len(e), strings.Join(errs, "\n")) +} + +func validateUpdateArgs(ctx *dep.Ctx, args []string, p *dep.Project, sm gps.SourceManager, params *gps.SolveParameters) error { + // Channel for receiving all the valid arguments. + argsCh := make(chan string, len(args)) + + // Channel for receiving all the validation errors. + errCh := make(chan error, len(args)) + + var wg sync.WaitGroup + + // Allow any of specified project versions to change, regardless of the lock + // file. + for _, arg := range args { + wg.Add(1) + + go func(arg string) { + defer wg.Done() + + // Ensure the provided path has a deducible project root. + pc, path, err := getProjectConstraint(arg, sm) + if err != nil { + // TODO(sdboyer) ensure these errors are contextualized in a sensible way for -update + errCh <- err + return + } + if path != string(pc.Ident.ProjectRoot) { + // TODO(sdboyer): does this really merit an abortive error? + errCh <- errors.Errorf("%s is not a project root, try %s instead", path, pc.Ident.ProjectRoot) + return + } + + if !p.Lock.HasProjectWithRoot(pc.Ident.ProjectRoot) { + errCh <- errors.Errorf("%s is not present in %s, cannot -update it", pc.Ident.ProjectRoot, dep.LockName) + return + } + + if pc.Ident.Source != "" { + errCh <- errors.Errorf("cannot specify alternate sources on -update (%s)", pc.Ident.Source) + return + } + + if !gps.IsAny(pc.Constraint) { + // TODO(sdboyer) constraints should be allowed to allow solves that + // target particular versions while remaining within declared constraints. + errCh <- errors.Errorf("version constraint %s passed for %s, but -update follows constraints declared in %s, not CLI arguments", pc.Constraint, pc.Ident.ProjectRoot, dep.ManifestName) + return + } + + // Valid argument. + argsCh <- arg + }(arg) + } + + wg.Wait() + close(errCh) + close(argsCh) + + // Log all the errors. + if len(errCh) > 0 { + ctx.Err.Printf("Invalid arguments passed to ensure -update:\n\n") + for err := range errCh { + ctx.Err.Println(" ✗", err.Error()) + } + ctx.Err.Println() + return errUpdateArgsValidation + } + + // Add all the valid arguments to solve params. + for arg := range argsCh { + params.ToChange = append(params.ToChange, gps.ProjectRoot(arg)) + } + + return nil +} diff --git a/vendor/github.com/golang/dep/cmd/dep/ensure_test.go b/vendor/github.com/golang/dep/cmd/dep/ensure_test.go new file mode 100644 index 00000000..15d16fd9 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/ensure_test.go @@ -0,0 +1,256 @@ +// Copyright 2017 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 main + +import ( + "bytes" + "errors" + "go/build" + "io/ioutil" + "log" + "strings" + "testing" + + "github.com/golang/dep" + "github.com/golang/dep/gps" + "github.com/golang/dep/gps/pkgtree" + "github.com/golang/dep/internal/test" +) + +func TestInvalidEnsureFlagCombinations(t *testing.T) { + ec := &ensureCommand{ + update: true, + add: true, + } + + if err := ec.validateFlags(); err == nil { + t.Error("-add and -update together should fail validation") + } + + ec.vendorOnly, ec.add = true, false + if err := ec.validateFlags(); err == nil { + t.Error("-vendor-only with -update should fail validation") + } + + ec.add, ec.update = true, false + if err := ec.validateFlags(); err == nil { + t.Error("-vendor-only with -add should fail validation") + } + + ec.noVendor, ec.add = true, false + if err := ec.validateFlags(); err == nil { + t.Error("-vendor-only with -no-vendor should fail validation") + } + ec.noVendor = false + + // Also verify that the plain ensure path takes no args. This is a shady + // test, as lots of other things COULD return errors, and we don't check + // anything other than the error being non-nil. For now, it works well + // because a panic will quickly result if the initial arg length validation + // checks are incorrectly handled. + if err := ec.runDefault(nil, []string{"foo"}, nil, nil, gps.SolveParameters{}); err == nil { + t.Errorf("no args to plain ensure with -vendor-only") + } + ec.vendorOnly = false + if err := ec.runDefault(nil, []string{"foo"}, nil, nil, gps.SolveParameters{}); err == nil { + t.Errorf("no args to plain ensure") + } +} + +func TestCheckErrors(t *testing.T) { + tt := []struct { + name string + fatal bool + pkgOrErrMap map[string]pkgtree.PackageOrErr + }{ + { + name: "noErrors", + fatal: false, + pkgOrErrMap: map[string]pkgtree.PackageOrErr{ + "mypkg": { + P: pkgtree.Package{}, + }, + }, + }, + { + name: "hasErrors", + fatal: true, + pkgOrErrMap: map[string]pkgtree.PackageOrErr{ + "github.com/me/pkg": { + Err: &build.NoGoError{}, + }, + "github.com/someone/pkg": { + Err: errors.New("code is busted"), + }, + }, + }, + { + name: "onlyGoErrors", + fatal: false, + pkgOrErrMap: map[string]pkgtree.PackageOrErr{ + "github.com/me/pkg": { + Err: &build.NoGoError{}, + }, + "github.com/someone/pkg": { + P: pkgtree.Package{}, + }, + }, + }, + { + name: "onlyBuildErrors", + fatal: false, + pkgOrErrMap: map[string]pkgtree.PackageOrErr{ + "github.com/me/pkg": { + Err: &build.NoGoError{}, + }, + "github.com/someone/pkg": { + P: pkgtree.Package{}, + }, + }, + }, + { + name: "allGoErrors", + fatal: true, + pkgOrErrMap: map[string]pkgtree.PackageOrErr{ + "github.com/me/pkg": { + Err: &build.NoGoError{}, + }, + }, + }, + { + name: "allMixedErrors", + fatal: true, + pkgOrErrMap: map[string]pkgtree.PackageOrErr{ + "github.com/me/pkg": { + Err: &build.NoGoError{}, + }, + "github.com/someone/pkg": { + Err: errors.New("code is busted"), + }, + }, + }, + } + + for _, tc := range tt { + t.Run(tc.name, func(t *testing.T) { + fatal, err := checkErrors(tc.pkgOrErrMap, nil) + if tc.fatal != fatal { + t.Fatalf("expected fatal flag to be %T, got %T", tc.fatal, fatal) + } + if err == nil && fatal { + t.Fatal("unexpected fatal flag value while err is nil") + } + }) + } +} + +func TestValidateUpdateArgs(t *testing.T) { + cases := []struct { + name string + args []string + wantError error + wantWarn []string + lockedProjects []string + }{ + { + name: "empty args", + args: []string{}, + wantError: nil, + }, + { + name: "not project root", + args: []string{"github.com/golang/dep/cmd"}, + wantError: errUpdateArgsValidation, + wantWarn: []string{ + "github.com/golang/dep/cmd is not a project root, try github.com/golang/dep instead", + }, + }, + { + name: "not present in lock", + args: []string{"github.com/golang/dep"}, + wantError: errUpdateArgsValidation, + wantWarn: []string{ + "github.com/golang/dep is not present in Gopkg.lock, cannot -update it", + }, + }, + { + name: "cannot specify alternate sources", + args: []string{"github.com/golang/dep:github.com/example/dep"}, + wantError: errUpdateArgsValidation, + wantWarn: []string{ + "cannot specify alternate sources on -update (github.com/example/dep)", + }, + lockedProjects: []string{"github.com/golang/dep"}, + }, + { + name: "version constraint passed", + args: []string{"github.com/golang/dep@master"}, + wantError: errUpdateArgsValidation, + wantWarn: []string{ + "version constraint master passed for github.com/golang/dep, but -update follows constraints declared in Gopkg.toml, not CLI arguments", + }, + lockedProjects: []string{"github.com/golang/dep"}, + }, + { + name: "flags after spec", + args: []string{"github.com/golang/dep@master", "-v"}, + wantError: errUpdateArgsValidation, + wantWarn: []string{ + "could not infer project root from dependency path", + }, + lockedProjects: []string{"github.com/golang/dep"}, + }, + } + + h := test.NewHelper(t) + defer h.Cleanup() + + h.TempDir("src") + pwd := h.Path(".") + + stderrOutput := &bytes.Buffer{} + errLogger := log.New(stderrOutput, "", 0) + ctx := &dep.Ctx{ + GOPATH: pwd, + Out: log.New(ioutil.Discard, "", 0), + Err: errLogger, + } + + sm, err := ctx.SourceManager() + h.Must(err) + defer sm.Release() + + p := new(dep.Project) + params := p.MakeParams() + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + // Empty the buffer for every case + stderrOutput.Reset() + + // Fill up the locked projects + lockedProjects := []gps.LockedProject{} + for _, lp := range c.lockedProjects { + pi := gps.ProjectIdentifier{ProjectRoot: gps.ProjectRoot(lp)} + lockedProjects = append(lockedProjects, gps.NewLockedProject(pi, gps.NewVersion("v1.0.0"), []string{})) + } + + // Add lock to project + p.Lock = &dep.Lock{P: lockedProjects} + + err := validateUpdateArgs(ctx, c.args, p, sm, ¶ms) + if err != c.wantError { + t.Fatalf("Unexpected error while validating update args:\n\t(GOT): %v\n\t(WNT): %v", err, c.wantError) + } + + warnings := stderrOutput.String() + for _, warn := range c.wantWarn { + if !strings.Contains(warnings, warn) { + t.Fatalf("Expected validateUpdateArgs errors to contain: %q", warn) + } + } + }) + } +} diff --git a/vendor/github.com/golang/dep/cmd/dep/failures.go b/vendor/github.com/golang/dep/cmd/dep/failures.go new file mode 100644 index 00000000..c40ac8c7 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/failures.go @@ -0,0 +1,23 @@ +// Copyright 2018 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 main + +import ( + "context" + + "github.com/golang/dep/gps" + "github.com/pkg/errors" +) + +// TODO solve failures can be really creative - we need to be similarly creative +// in handling them and informing the user appropriately +func handleAllTheFailuresOfTheWorld(err error) error { + switch errors.Cause(err) { + case context.Canceled, context.DeadlineExceeded, gps.ErrSourceManagerIsReleased: + return nil + } + + return errors.Wrap(err, "Solving failure") +} diff --git a/vendor/github.com/golang/dep/cmd/dep/gopath_scanner.go b/vendor/github.com/golang/dep/cmd/dep/gopath_scanner.go new file mode 100644 index 00000000..ed94d8d4 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/gopath_scanner.go @@ -0,0 +1,408 @@ +// Copyright 2016 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 main + +import ( + "fmt" + "os" + "path/filepath" + "strings" + "sync" + + "github.com/golang/dep" + "github.com/golang/dep/gps" + "github.com/golang/dep/gps/paths" + "github.com/golang/dep/gps/pkgtree" + fb "github.com/golang/dep/internal/feedback" + "github.com/golang/dep/internal/fs" + "github.com/pkg/errors" +) + +// gopathScanner supplies manifest/lock data by scanning the contents of GOPATH +// It uses its results to fill-in any missing details left by the rootAnalyzer. +type gopathScanner struct { + ctx *dep.Ctx + directDeps map[gps.ProjectRoot]bool + sm gps.SourceManager + + pd projectData + origM *dep.Manifest + origL *dep.Lock +} + +func newGopathScanner(ctx *dep.Ctx, directDeps map[gps.ProjectRoot]bool, sm gps.SourceManager) *gopathScanner { + return &gopathScanner{ + ctx: ctx, + directDeps: directDeps, + sm: sm, + } +} + +// InitializeRootManifestAndLock performs analysis of the filesystem tree rooted +// at path, with the root import path importRoot, to determine the project's +// constraints. Respect any initial constraints defined in the root manifest and +// lock. +func (g *gopathScanner) InitializeRootManifestAndLock(rootM *dep.Manifest, rootL *dep.Lock) error { + var err error + + g.ctx.Err.Println("Searching GOPATH for projects...") + g.pd, err = g.scanGopathForDependencies() + if err != nil { + return err + } + + g.origM = dep.NewManifest() + g.origM.Constraints = g.pd.constraints + + g.origL = &dep.Lock{ + P: make([]gps.LockedProject, 0, len(g.pd.ondisk)), + } + + for pr, v := range g.pd.ondisk { + // That we have to chop off these path prefixes is a symptom of + // a problem in gps itself + pkgs := make([]string, 0, len(g.pd.dependencies[pr])) + prslash := string(pr) + "/" + for _, pkg := range g.pd.dependencies[pr] { + if pkg == string(pr) { + pkgs = append(pkgs, ".") + } else { + pkgs = append(pkgs, trimPathPrefix(pkg, prslash)) + } + } + + g.origL.P = append(g.origL.P, gps.NewLockedProject( + gps.ProjectIdentifier{ProjectRoot: pr}, v, pkgs), + ) + } + + g.overlay(rootM, rootL) + + return nil +} + +// Fill in gaps in the root manifest/lock with data found from the GOPATH. +func (g *gopathScanner) overlay(rootM *dep.Manifest, rootL *dep.Lock) { + for pkg, prj := range g.origM.Constraints { + if _, has := rootM.Constraints[pkg]; has { + continue + } + rootM.Constraints[pkg] = prj + v := g.pd.ondisk[pkg] + + pi := gps.ProjectIdentifier{ProjectRoot: pkg, Source: prj.Source} + f := fb.NewConstraintFeedback(gps.ProjectConstraint{Ident: pi, Constraint: v}, fb.DepTypeDirect) + f.LogFeedback(g.ctx.Err) + f = fb.NewLockedProjectFeedback(gps.NewLockedProject(pi, v, nil), fb.DepTypeDirect) + f.LogFeedback(g.ctx.Err) + } + + // Keep track of which projects have been locked + lockedProjects := map[gps.ProjectRoot]bool{} + for _, lp := range rootL.P { + lockedProjects[lp.Ident().ProjectRoot] = true + } + + for _, lp := range g.origL.P { + pkg := lp.Ident().ProjectRoot + if _, isLocked := lockedProjects[pkg]; isLocked { + continue + } + rootL.P = append(rootL.P, lp) + lockedProjects[pkg] = true + + if _, isDirect := g.directDeps[pkg]; !isDirect { + f := fb.NewLockedProjectFeedback(lp, fb.DepTypeTransitive) + f.LogFeedback(g.ctx.Err) + } + } + + // Identify projects whose version is unknown and will have to be solved for + var missing []string // all project roots missing from GOPATH + var missingVCS []string // all project roots missing VCS information + for pr := range g.pd.notondisk { + if _, isLocked := lockedProjects[pr]; isLocked { + continue + } + if g.pd.invalidSVC[pr] { + missingVCS = append(missingVCS, string(pr)) + } else { + missing = append(missing, string(pr)) + } + } + + missingStr := "" + missingVCSStr := "" + if len(missing) > 0 { + missingStr = fmt.Sprintf("The following dependencies were not found in GOPATH:\n %s\n\n", + strings.Join(missing, "\n ")) + } + if len(missingVCS) > 0 { + missingVCSStr = fmt.Sprintf("The following dependencies found in GOPATH were missing VCS information (a remote source is required):\n %s\n\n", + strings.Join(missingVCS, "\n ")) + } + if len(missingVCS)+len(missing) > 0 { + g.ctx.Err.Printf("\n%s%sThe most recent version of these projects will be used.\n\n", missingStr, missingVCSStr) + } +} + +func trimPathPrefix(p1, p2 string) string { + if isPrefix, _ := fs.HasFilepathPrefix(p1, p2); isPrefix { + return p1[len(p2):] + } + return p1 +} + +// contains checks if a array of strings contains a value +func contains(a []string, b string) bool { + for _, v := range a { + if b == v { + return true + } + } + return false +} + +// getProjectPropertiesFromVersion takes a Version and returns a proper +// ProjectProperties with Constraint value based on the provided version. +func getProjectPropertiesFromVersion(v gps.Version) gps.ProjectProperties { + pp := gps.ProjectProperties{} + + // extract version and ignore if it's revision only + switch tv := v.(type) { + case gps.PairedVersion: + v = tv.Unpair() + case gps.Revision: + return pp + } + + switch v.Type() { + case gps.IsBranch, gps.IsVersion: + pp.Constraint = v + case gps.IsSemver: + c, err := gps.NewSemverConstraintIC(v.String()) + if err != nil { + panic(err) + } + pp.Constraint = c + } + + return pp +} + +type projectData struct { + constraints gps.ProjectConstraints // constraints that could be found + dependencies map[gps.ProjectRoot][]string // all dependencies (imports) found by project root + notondisk map[gps.ProjectRoot]bool // projects that were not found on disk + invalidSVC map[gps.ProjectRoot]bool // projects that were found on disk but SVC data could not be read + ondisk map[gps.ProjectRoot]gps.Version // projects that were found on disk +} + +func (g *gopathScanner) scanGopathForDependencies() (projectData, error) { + constraints := make(gps.ProjectConstraints) + dependencies := make(map[gps.ProjectRoot][]string) + packages := make(map[string]bool) + notondisk := make(map[gps.ProjectRoot]bool) + invalidSVC := make(map[gps.ProjectRoot]bool) + ondisk := make(map[gps.ProjectRoot]gps.Version) + + var syncDepGroup sync.WaitGroup + syncDep := func(pr gps.ProjectRoot, sm gps.SourceManager) { + if err := sm.SyncSourceFor(gps.ProjectIdentifier{ProjectRoot: pr}); err != nil { + g.ctx.Err.Printf("%+v", errors.Wrapf(err, "Unable to cache %s", pr)) + } + syncDepGroup.Done() + } + + if len(g.directDeps) == 0 { + return projectData{}, nil + } + + for ippr := range g.directDeps { + // TODO(sdboyer) these are not import paths by this point, they've + // already been worked down to project roots. + ip := string(ippr) + pr, err := g.sm.DeduceProjectRoot(ip) + if err != nil { + return projectData{}, errors.Wrap(err, "sm.DeduceProjectRoot") + } + + packages[ip] = true + if _, has := dependencies[pr]; has { + dependencies[pr] = append(dependencies[pr], ip) + continue + } + syncDepGroup.Add(1) + go syncDep(pr, g.sm) + + dependencies[pr] = []string{ip} + abs, err := g.ctx.AbsForImport(string(pr)) + if err != nil { + notondisk[pr] = true + continue + } + v, err := gps.VCSVersion(abs) + if err != nil { + invalidSVC[pr] = true + notondisk[pr] = true + continue + } + + ondisk[pr] = v + pp := getProjectPropertiesFromVersion(v) + if pp.Constraint != nil || pp.Source != "" { + constraints[pr] = pp + } + } + + // Explore the packages we've found for transitive deps, either + // completing the lock or identifying (more) missing projects that we'll + // need to ask gps to solve for us. + colors := make(map[string]uint8) + const ( + white uint8 = iota + grey + black + ) + + // cache of PackageTrees, so we don't parse projects more than once + ptrees := make(map[gps.ProjectRoot]pkgtree.PackageTree) + + // depth-first traverser + var dft func(string) error + dft = func(pkg string) error { + switch colors[pkg] { + case white: + colors[pkg] = grey + + pr, err := g.sm.DeduceProjectRoot(pkg) + if err != nil { + return errors.Wrap(err, "could not deduce project root for "+pkg) + } + + // We already visited this project root earlier via some other + // pkg within it, and made the decision that it's not on disk. + // Respect that decision, and pop the stack. + if notondisk[pr] { + colors[pkg] = black + return nil + } + + ptree, has := ptrees[pr] + if !has { + // It's fine if the root does not exist - it indicates that this + // project is not present in the workspace, and so we need to + // solve to deal with this dep. + r := filepath.Join(g.ctx.GOPATH, "src", string(pr)) + fi, err := os.Stat(r) + if os.IsNotExist(err) || !fi.IsDir() { + colors[pkg] = black + notondisk[pr] = true + return nil + } + + // We know the project is on disk; the question is whether we're + // first seeing it here, in the transitive exploration, or if it + // was found in the initial pass on direct imports. We know it's + // the former if there's no entry for it in the ondisk map. + if _, in := ondisk[pr]; !in { + abs, err := g.ctx.AbsForImport(string(pr)) + if err != nil { + colors[pkg] = black + notondisk[pr] = true + return nil + } + v, err := gps.VCSVersion(abs) + if err != nil { + // Even if we know it's on disk, errors are still + // possible when trying to deduce version. If we + // encounter such an error, just treat the project as + // not being on disk; the solver will work it out. + colors[pkg] = black + notondisk[pr] = true + return nil + } + ondisk[pr] = v + } + + ptree, err = pkgtree.ListPackages(r, string(pr)) + if err != nil { + // Any error here other than an a nonexistent dir (which + // can't happen because we covered that case above) is + // probably critical, so bail out. + return errors.Wrap(err, "gps.ListPackages") + } + ptrees[pr] = ptree + } + + // Get a reachmap that includes main pkgs (even though importing + // them is an error, what we're checking right now is simply whether + // there's a package with go code present on disk), and does not + // backpropagate errors (again, because our only concern right now + // is package existence). + rm, errmap := ptree.ToReachMap(true, false, false, nil) + reached, ok := rm[pkg] + if !ok { + colors[pkg] = black + // not on disk... + notondisk[pr] = true + return nil + } + if _, ok := errmap[pkg]; ok { + // The package is on disk, but contains some errors. + colors[pkg] = black + return nil + } + + if deps, has := dependencies[pr]; has { + if !contains(deps, pkg) { + dependencies[pr] = append(deps, pkg) + } + } else { + dependencies[pr] = []string{pkg} + syncDepGroup.Add(1) + go syncDep(pr, g.sm) + } + + // recurse + for _, rpkg := range reached.External { + if paths.IsStandardImportPath(rpkg) { + continue + } + + err := dft(rpkg) + if err != nil { + // Bubble up any errors we encounter + return err + } + } + + colors[pkg] = black + case grey: + return errors.Errorf("Import cycle detected on %s", pkg) + } + return nil + } + + // run the depth-first traversal from the set of immediate external + // package imports we found in the current project + for pkg := range packages { + err := dft(pkg) + if err != nil { + return projectData{}, err // already errors.Wrap()'d internally + } + } + + syncDepGroup.Wait() + + pd := projectData{ + constraints: constraints, + dependencies: dependencies, + invalidSVC: invalidSVC, + notondisk: notondisk, + ondisk: ondisk, + } + return pd, nil +} diff --git a/vendor/github.com/golang/dep/cmd/dep/gopath_scanner_test.go b/vendor/github.com/golang/dep/cmd/dep/gopath_scanner_test.go new file mode 100644 index 00000000..bfab02e8 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/gopath_scanner_test.go @@ -0,0 +1,189 @@ +// Copyright 2016 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 main + +import ( + "io/ioutil" + "log" + "reflect" + "testing" + + "github.com/golang/dep" + "github.com/golang/dep/gps" + "github.com/golang/dep/internal/test" +) + +const testProject1 string = "github.com/sdboyer/deptest" +const testProject2 string = "github.com/sdboyer/deptestdos" + +// NewTestContext creates a unique context with its own GOPATH for a single test. +func NewTestContext(h *test.Helper) *dep.Ctx { + h.TempDir("src") + pwd := h.Path(".") + discardLogger := log.New(ioutil.Discard, "", 0) + + return &dep.Ctx{ + GOPATH: pwd, + Out: discardLogger, + Err: discardLogger, + } +} + +func TestGopathScanner_OverlayManifestConstraints(t *testing.T) { + h := test.NewHelper(t) + h.Parallel() + defer h.Cleanup() + + ctx := NewTestContext(h) + + pi1 := gps.ProjectIdentifier{ProjectRoot: gps.ProjectRoot(testProject1)} + pi2 := gps.ProjectIdentifier{ProjectRoot: gps.ProjectRoot(testProject2)} + v1 := gps.NewVersion("v1.0.0") + v2 := gps.NewVersion("v2.0.0") + v3 := gps.NewVersion("v3.0.0") + rootM := dep.NewManifest() + rootM.Constraints[pi1.ProjectRoot] = gps.ProjectProperties{Constraint: v1} + rootL := &dep.Lock{} + origM := dep.NewManifest() + origM.Constraints[pi1.ProjectRoot] = gps.ProjectProperties{Constraint: v2} + origM.Constraints[pi2.ProjectRoot] = gps.ProjectProperties{Constraint: v3} + gs := gopathScanner{ + origM: origM, + origL: &dep.Lock{}, + ctx: ctx, + pd: projectData{ + ondisk: map[gps.ProjectRoot]gps.Version{ + pi1.ProjectRoot: v2, + pi2.ProjectRoot: v3, + }, + }, + } + + gs.overlay(rootM, rootL) + + dep, has := rootM.Constraints[pi1.ProjectRoot] + if !has { + t.Fatalf("Expected the root manifest to contain %s", pi1.ProjectRoot) + } + wantC := v1.String() + gotC := dep.Constraint.String() + if wantC != gotC { + t.Fatalf("Expected %s to be constrained to '%s', got '%s'", pi1.ProjectRoot, wantC, gotC) + } + + dep, has = rootM.Constraints[pi2.ProjectRoot] + if !has { + t.Fatalf("Expected the root manifest to contain %s", pi2.ProjectRoot) + } + wantC = v3.String() + gotC = dep.Constraint.String() + if wantC != gotC { + t.Fatalf("Expected %s to be constrained to '%s', got '%s'", pi2.ProjectRoot, wantC, gotC) + } +} + +func TestGopathScanner_OverlayLockProjects(t *testing.T) { + h := test.NewHelper(t) + h.Parallel() + defer h.Cleanup() + + ctx := NewTestContext(h) + + rootM := dep.NewManifest() + pi1 := gps.ProjectIdentifier{ProjectRoot: gps.ProjectRoot(testProject1)} + pi2 := gps.ProjectIdentifier{ProjectRoot: gps.ProjectRoot(testProject2)} + v1 := gps.NewVersion("v1.0.0") + v2 := gps.NewVersion("v2.0.0") + v3 := gps.NewVersion("v3.0.0") + rootL := &dep.Lock{ + P: []gps.LockedProject{gps.NewLockedProject(pi1, v1, []string{})}, + } + gs := gopathScanner{ + origM: dep.NewManifest(), + origL: &dep.Lock{ + P: []gps.LockedProject{ + gps.NewLockedProject(pi1, v2, []string{}), // ignored, already exists in lock + gps.NewLockedProject(pi2, v3, []string{}), // should be added to the lock + }, + }, + ctx: ctx, + pd: projectData{ + ondisk: map[gps.ProjectRoot]gps.Version{ + pi1.ProjectRoot: v2, + pi2.ProjectRoot: v3, + }, + }, + } + + gs.overlay(rootM, rootL) + + if len(rootL.P) != 2 { + t.Fatalf("Expected the root manifest to contain 2 packages, got %d", len(rootL.P)) + } + + if rootL.P[0].Version() != v1 { + t.Fatalf("Expected %s to be locked to '%s', got '%s'", rootL.P[0].Ident().ProjectRoot, v1, rootL.P[0].Version()) + } + + if rootL.P[1].Version() != v3 { + t.Fatalf("Expected %s to be locked to '%s', got '%s'", rootL.P[1].Ident().ProjectRoot, v3, rootL.P[1].Version()) + } +} + +func TestContains(t *testing.T) { + t.Parallel() + a := []string{"a", "b", "abcd"} + + if !contains(a, "a") { + t.Fatal("expected array to contain 'a'") + } + if contains(a, "d") { + t.Fatal("expected array to not contain 'd'") + } +} + +func TestGetProjectPropertiesFromVersion(t *testing.T) { + t.Parallel() + wantSemver, _ := gps.NewSemverConstraintIC("v1.0.0") + cases := []struct { + version, want gps.Constraint + }{ + { + version: gps.NewBranch("foo-branch"), + want: gps.NewBranch("foo-branch"), + }, + { + version: gps.NewVersion("foo-version"), + want: gps.NewVersion("foo-version"), + }, + { + version: gps.NewVersion("v1.0.0"), + want: wantSemver, + }, + { + version: gps.NewBranch("foo-branch").Pair("some-revision"), + want: gps.NewBranch("foo-branch"), + }, + { + version: gps.NewVersion("foo-version").Pair("some-revision"), + want: gps.NewVersion("foo-version"), + }, + { + version: gps.Revision("some-revision"), + want: nil, + }, + { + version: gps.NewVersion("v1.0.0").Pair("some-revision"), + want: wantSemver, + }, + } + + for _, c := range cases { + actualProp := getProjectPropertiesFromVersion(c.version.(gps.Version)) + if !reflect.DeepEqual(c.want, actualProp.Constraint) { + t.Fatalf("Constraints are not as expected: \n\t(GOT) %v\n\t(WNT) %v", actualProp.Constraint, c.want) + } + } +} diff --git a/vendor/github.com/golang/dep/cmd/dep/graphviz.go b/vendor/github.com/golang/dep/cmd/dep/graphviz.go new file mode 100644 index 00000000..b422ddde --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/graphviz.go @@ -0,0 +1,110 @@ +// Copyright 2016 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 main + +import ( + "bytes" + "fmt" + "hash/fnv" + "strings" +) + +type graphviz struct { + ps []*gvnode + b bytes.Buffer + h map[string]uint32 +} + +type gvnode struct { + project string + version string + children []string +} + +func (g graphviz) New() *graphviz { + ga := &graphviz{ + ps: []*gvnode{}, + h: make(map[string]uint32), + } + return ga +} + +func (g graphviz) output() bytes.Buffer { + g.b.WriteString("digraph {\n\tnode [shape=box];") + + for _, gvp := range g.ps { + // Create node string + g.b.WriteString(fmt.Sprintf("\n\t%d [label=\"%s\"];", gvp.hash(), gvp.label())) + } + + // Store relations to avoid duplication + rels := make(map[string]bool) + + // Create relations + for _, dp := range g.ps { + for _, bsc := range dp.children { + for pr, hsh := range g.h { + if isPathPrefix(bsc, pr) { + r := fmt.Sprintf("\n\t%d -> %d", g.h[dp.project], hsh) + + if _, ex := rels[r]; !ex { + g.b.WriteString(r + ";") + rels[r] = true + } + + } + } + } + } + + g.b.WriteString("\n}") + return g.b +} + +func (g *graphviz) createNode(project, version string, children []string) { + pr := &gvnode{ + project: project, + version: version, + children: children, + } + + g.h[pr.project] = pr.hash() + g.ps = append(g.ps, pr) +} + +func (dp gvnode) hash() uint32 { + h := fnv.New32a() + h.Write([]byte(dp.project)) + return h.Sum32() +} + +func (dp gvnode) label() string { + label := []string{dp.project} + + if dp.version != "" { + label = append(label, dp.version) + } + + return strings.Join(label, "\\n") +} + +// isPathPrefix ensures that the literal string prefix is a path tree match and +// guards against possibilities like this: +// +// github.com/sdboyer/foo +// github.com/sdboyer/foobar/baz +// +// Verify that prefix is path match and either the input is the same length as +// the match (in which case we know they're equal), or that the next character +// is a "/". (Import paths are defined to always use "/", not the OS-specific +// path separator.) +func isPathPrefix(path, pre string) bool { + pathlen, prflen := len(path), len(pre) + if pathlen < prflen || path[0:prflen] != pre { + return false + } + + return prflen == pathlen || strings.Index(path[prflen:], "/") == 0 +} diff --git a/vendor/github.com/golang/dep/cmd/dep/graphviz_test.go b/vendor/github.com/golang/dep/cmd/dep/graphviz_test.go new file mode 100644 index 00000000..a7537f00 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/graphviz_test.go @@ -0,0 +1,83 @@ +// Copyright 2016 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 main + +import ( + "testing" + + "github.com/golang/dep/internal/test" +) + +func TestEmptyProject(t *testing.T) { + h := test.NewHelper(t) + h.Parallel() + defer h.Cleanup() + + g := new(graphviz).New() + + b := g.output() + want := h.GetTestFileString("graphviz/empty.dot") + + if b.String() != want { + t.Fatalf("expected '%v', got '%v'", want, b.String()) + } +} + +func TestSimpleProject(t *testing.T) { + h := test.NewHelper(t) + h.Parallel() + defer h.Cleanup() + + g := new(graphviz).New() + + g.createNode("project", "", []string{"foo", "bar"}) + g.createNode("foo", "master", []string{"bar"}) + g.createNode("bar", "dev", []string{}) + + b := g.output() + want := h.GetTestFileString("graphviz/case1.dot") + if b.String() != want { + t.Fatalf("expected '%v', got '%v'", want, b.String()) + } +} + +func TestNoLinks(t *testing.T) { + h := test.NewHelper(t) + h.Parallel() + defer h.Cleanup() + + g := new(graphviz).New() + + g.createNode("project", "", []string{}) + + b := g.output() + want := h.GetTestFileString("graphviz/case2.dot") + if b.String() != want { + t.Fatalf("expected '%v', got '%v'", want, b.String()) + } +} + +func TestIsPathPrefix(t *testing.T) { + t.Parallel() + + tcs := []struct { + path string + pre string + want bool + }{ + {"github.com/sdboyer/foo/bar", "github.com/sdboyer/foo", true}, + {"github.com/sdboyer/foobar", "github.com/sdboyer/foo", false}, + {"github.com/sdboyer/bar/foo", "github.com/sdboyer/foo", false}, + {"golang.org/sdboyer/bar/foo", "github.com/sdboyer/foo", false}, + {"golang.org/sdboyer/FOO", "github.com/sdboyer/foo", false}, + } + + for _, tc := range tcs { + r := isPathPrefix(tc.path, tc.pre) + if tc.want != r { + t.Fatalf("expected '%v', got '%v'", tc.want, r) + } + } +} diff --git a/vendor/github.com/golang/dep/cmd/dep/hash_in.go b/vendor/github.com/golang/dep/cmd/dep/hash_in.go new file mode 100644 index 00000000..ed7f3569 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/hash_in.go @@ -0,0 +1,51 @@ +// Copyright 2017 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 main + +import ( + "flag" + + "github.com/golang/dep" + "github.com/golang/dep/gps" + "github.com/golang/dep/gps/pkgtree" + "github.com/pkg/errors" +) + +func (cmd *hashinCommand) Name() string { return "hash-inputs" } +func (cmd *hashinCommand) Args() string { return "" } +func (cmd *hashinCommand) ShortHelp() string { return "" } +func (cmd *hashinCommand) LongHelp() string { return "" } +func (cmd *hashinCommand) Hidden() bool { return true } + +func (cmd *hashinCommand) Register(fs *flag.FlagSet) {} + +type hashinCommand struct{} + +func (hashinCommand) Run(ctx *dep.Ctx, args []string) error { + p, err := ctx.LoadProject() + if err != nil { + return err + } + + sm, err := ctx.SourceManager() + if err != nil { + return err + } + sm.UseDefaultSignalHandling() + defer sm.Release() + + params := p.MakeParams() + params.RootPackageTree, err = pkgtree.ListPackages(p.ResolvedAbsRoot, string(p.ImportRoot)) + if err != nil { + return errors.Wrap(err, "gps.ListPackages") + } + + s, err := gps.Prepare(params, sm) + if err != nil { + return errors.Wrap(err, "prepare solver") + } + ctx.Out.Println(gps.HashingInputsAsString(s)) + return nil +} diff --git a/vendor/github.com/golang/dep/cmd/dep/init.go b/vendor/github.com/golang/dep/cmd/dep/init.go new file mode 100644 index 00000000..fe90b867 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/init.go @@ -0,0 +1,245 @@ +// Copyright 2016 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 main + +import ( + "context" + "flag" + "io/ioutil" + "log" + "os" + "path/filepath" + "time" + + "github.com/golang/dep" + "github.com/golang/dep/gps" + "github.com/golang/dep/internal/fs" + "github.com/pkg/errors" +) + +const initShortHelp = `Set up a new Go project, or migrate an existing one` +const initLongHelp = ` +Initialize the project at filepath root by parsing its dependencies, writing +manifest and lock files, and vendoring the dependencies. If root isn't +specified, use the current directory. + +When configuration for another dependency management tool is detected, it is +imported into the initial manifest and lock. Use the -skip-tools flag to +disable this behavior. The following external tools are supported: +glide, godep, vndr, govend, gb, gvt, govendor, glock. + +Any dependencies that are not constrained by external configuration use the +GOPATH analysis below. + +By default, the dependencies are resolved over the network. A version will be +selected from the versions available from the upstream source per the following +algorithm: + + - Tags conforming to semver (sorted by semver rules) + - Default branch(es) (sorted lexicographically) + - Non-semver tags (sorted lexicographically) + +An alternate mode can be activated by passing -gopath. In this mode, the version +of each dependency will reflect the current state of the GOPATH. If a dependency +doesn't exist in the GOPATH, a version will be selected based on the above +network version selection algorithm. + +A Gopkg.toml file will be written with inferred version constraints for all +direct dependencies. Gopkg.lock will be written with precise versions, and +vendor/ will be populated with the precise versions written to Gopkg.lock. +` + +func (cmd *initCommand) Name() string { return "init" } +func (cmd *initCommand) Args() string { return "[root]" } +func (cmd *initCommand) ShortHelp() string { return initShortHelp } +func (cmd *initCommand) LongHelp() string { return initLongHelp } +func (cmd *initCommand) Hidden() bool { return false } + +func (cmd *initCommand) Register(fs *flag.FlagSet) { + fs.BoolVar(&cmd.noExamples, "no-examples", false, "don't include example in Gopkg.toml") + fs.BoolVar(&cmd.skipTools, "skip-tools", false, "skip importing configuration from other dependency managers") + fs.BoolVar(&cmd.gopath, "gopath", false, "search in GOPATH for dependencies") +} + +type initCommand struct { + noExamples bool + skipTools bool + gopath bool +} + +func (cmd *initCommand) Run(ctx *dep.Ctx, args []string) error { + if len(args) > 1 { + return errors.Errorf("too many args (%d)", len(args)) + } + + var root string + if len(args) <= 0 { + root = ctx.WorkingDir + } else { + root = args[0] + if !filepath.IsAbs(args[0]) { + root = filepath.Join(ctx.WorkingDir, args[0]) + } + if err := os.MkdirAll(root, os.FileMode(0777)); err != nil { + return errors.Wrapf(err, "init failed: unable to create a directory at %s", root) + } + } + + p, err := cmd.establishProjectAt(root, ctx) + if err != nil { + return err + } + + sm, err := ctx.SourceManager() + if err != nil { + return errors.Wrap(err, "init failed: unable to create a source manager") + } + sm.UseDefaultSignalHandling() + defer sm.Release() + + if ctx.Verbose { + ctx.Out.Println("Getting direct dependencies...") + } + + ptree, directDeps, err := p.GetDirectDependencyNames(sm) + if err != nil { + return errors.Wrap(err, "init failed: unable to determine direct dependencies") + } + if ctx.Verbose { + ctx.Out.Printf("Checked %d directories for packages.\nFound %d direct dependencies.\n", len(ptree.Packages), len(directDeps)) + } + + // Initialize with imported data, then fill in the gaps using the GOPATH + rootAnalyzer := newRootAnalyzer(cmd.skipTools, ctx, directDeps, sm) + p.Manifest, p.Lock, err = rootAnalyzer.InitializeRootManifestAndLock(root, p.ImportRoot) + if err != nil { + return errors.Wrap(err, "init failed: unable to prepare an initial manifest and lock for the solver") + } + + // Set default prune options for go-tests and unused-packages + p.Manifest.PruneOptions.DefaultOptions = gps.PruneNestedVendorDirs | gps.PruneGoTestFiles | gps.PruneUnusedPackages + + if cmd.gopath { + gs := newGopathScanner(ctx, directDeps, sm) + err = gs.InitializeRootManifestAndLock(p.Manifest, p.Lock) + if err != nil { + return errors.Wrap(err, "init failed: unable to scan the GOPATH for dependencies") + } + } + + rootAnalyzer.skipTools = true // Don't import external config during solve for now + copyLock := *p.Lock // Copy lock before solving. Use this to separate new lock projects from solved lock + + params := gps.SolveParameters{ + RootDir: root, + RootPackageTree: ptree, + Manifest: p.Manifest, + Lock: p.Lock, + ProjectAnalyzer: rootAnalyzer, + } + + if ctx.Verbose { + params.TraceLogger = ctx.Err + } + + if err := ctx.ValidateParams(sm, params); err != nil { + return errors.Wrapf(err, "init failed: validation of solve parameters failed") + } + + s, err := gps.Prepare(params, sm) + if err != nil { + return errors.Wrap(err, "init failed: unable to prepare the solver") + } + + soln, err := s.Solve(context.TODO()) + if err != nil { + err = handleAllTheFailuresOfTheWorld(err) + return errors.Wrap(err, "init failed: unable to solve the dependency graph") + } + p.Lock = dep.LockFromSolution(soln) + + rootAnalyzer.FinalizeRootManifestAndLock(p.Manifest, p.Lock, copyLock) + + // Run gps.Prepare with appropriate constraint solutions from solve run + // to generate the final lock memo. + s, err = gps.Prepare(params, sm) + if err != nil { + return errors.Wrap(err, "init failed: unable to recalculate the lock digest") + } + + p.Lock.SolveMeta.InputsDigest = s.HashInputs() + + // Pass timestamp (yyyyMMddHHmmss format) as suffix to backup name. + vendorbak, err := dep.BackupVendor(filepath.Join(root, "vendor"), time.Now().Format("20060102150405")) + if err != nil { + return errors.Wrap(err, "init failed: first backup vendor/, delete it, and then retry the previous command: failed to backup existing vendor directory") + } + if vendorbak != "" { + ctx.Err.Printf("Old vendor backed up to %v", vendorbak) + } + + sw, err := dep.NewSafeWriter(p.Manifest, nil, p.Lock, dep.VendorAlways, p.Manifest.PruneOptions) + if err != nil { + return errors.Wrap(err, "init failed: unable to create a SafeWriter") + } + + logger := ctx.Err + if !ctx.Verbose { + logger = log.New(ioutil.Discard, "", 0) + } + if err := sw.Write(root, sm, !cmd.noExamples, logger); err != nil { + return errors.Wrap(err, "init failed: unable to write the manifest, lock and vendor directory to disk") + } + + return nil +} + +// establishProjectAt attempts to set up the provided path as the root for the +// project to be created. +// +// It checks for being within a GOPATH, that there is no pre-existing manifest +// and lock, and that we can successfully infer the root import path from +// GOPATH. +// +// If successful, it returns a dep.Project, ready for further use. +func (cmd *initCommand) establishProjectAt(root string, ctx *dep.Ctx) (*dep.Project, error) { + var err error + p := new(dep.Project) + if err = p.SetRoot(root); err != nil { + return nil, errors.Wrapf(err, "init failed: unable to set the root project to %s", root) + } + + ctx.GOPATH, err = ctx.DetectProjectGOPATH(p) + if err != nil { + return nil, errors.Wrapf(err, "init failed: unable to detect the containing GOPATH") + } + + mf := filepath.Join(root, dep.ManifestName) + lf := filepath.Join(root, dep.LockName) + + mok, err := fs.IsRegular(mf) + if err != nil { + return nil, errors.Wrapf(err, "init failed: unable to check for an existing manifest at %s", mf) + } + if mok { + return nil, errors.Errorf("init aborted: manifest already exists at %s", mf) + } + + lok, err := fs.IsRegular(lf) + if err != nil { + return nil, errors.Wrapf(err, "init failed: unable to check for an existing lock at %s", lf) + } + if lok { + return nil, errors.Errorf("invalid aborted: lock already exists at %s", lf) + } + + ip, err := ctx.ImportForAbs(root) + if err != nil { + return nil, errors.Wrapf(err, "init failed: unable to determine the import path for the root project %s", root) + } + p.ImportRoot = gps.ProjectRoot(ip) + + return p, nil +} diff --git a/vendor/github.com/golang/dep/cmd/dep/integration_test.go b/vendor/github.com/golang/dep/cmd/dep/integration_test.go new file mode 100644 index 00000000..b332b0cf --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/integration_test.go @@ -0,0 +1,237 @@ +// Copyright 2017 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 main + +import ( + "fmt" + "io" + "io/ioutil" + "os" + "os/exec" + "path/filepath" + "runtime" + "strings" + "testing" + + "github.com/golang/dep" + "github.com/golang/dep/internal/test" + "github.com/golang/dep/internal/test/integration" +) + +func TestIntegration(t *testing.T) { + t.Parallel() + + test.NeedsExternalNetwork(t) + test.NeedsGit(t) + + wd, err := os.Getwd() + if err != nil { + t.Fatal(err) + } + + relPath := filepath.Join("testdata", "harness_tests") + filepath.Walk(relPath, func(path string, info os.FileInfo, err error) error { + if err != nil { + t.Fatal("error walking filepath") + } + + if filepath.Base(path) != "testcase.json" { + return nil + } + + parse := strings.Split(path, string(filepath.Separator)) + testName := strings.Join(parse[2:len(parse)-1], "/") + t.Run(testName, func(t *testing.T) { + t.Parallel() + + t.Run("external", testIntegration(testName, relPath, wd, execCmd)) + t.Run("internal", testIntegration(testName, relPath, wd, runMain)) + }) + + return nil + }) +} + +func TestDepCachedir(t *testing.T) { + if runtime.GOOS == "windows" { + // This test is unreliable on Windows and fails at random which makes it very + // difficult to debug. It might have something to do with parallel execution. + // Since the test doesn't test any specific behavior of Windows, it should be okay + // to skip. + t.Skip("skipping on windows") + } + t.Parallel() + + test.NeedsExternalNetwork(t) + test.NeedsGit(t) + + wd, err := os.Getwd() + if err != nil { + t.Fatal(err) + } + + initPath := filepath.Join("testdata", "cachedir") + + t.Run("env-cachedir", func(t *testing.T) { + t.Parallel() + testProj := integration.NewTestProject(t, initPath, wd, runMain) + defer testProj.Cleanup() + + testProj.TempDir("cachedir") + cachedir := testProj.Path("cachedir") + testProj.Setenv("DEPCACHEDIR", cachedir) + + // Running `dep ensure` will pull in the dependency into cachedir. + err = testProj.DoRun([]string{"ensure"}) + if err != nil { + // Log the error output from running `dep ensure`, could be useful. + t.Logf("`dep ensure` error output: \n%s", testProj.GetStderr()) + t.Errorf("got an unexpected error: %s", err) + } + + // Check that the cache was created in the cachedir. Our fixture has the dependency + // `github.com/sdboyer/deptest` + _, err = os.Stat(testProj.Path("cachedir", "sources", "https---github.com-sdboyer-deptest")) + if err != nil { + if os.IsNotExist(err) { + t.Error("expected cachedir to have been populated but none was found") + } else { + t.Errorf("got an unexpected error: %s", err) + } + } + }) + t.Run("env-invalid-cachedir", func(t *testing.T) { + t.Parallel() + testProj := integration.NewTestProject(t, initPath, wd, runMain) + defer testProj.Cleanup() + + var d []byte + tmpFp := testProj.Path("tmp-file") + ioutil.WriteFile(tmpFp, d, 0644) + cases := []string{ + // invalid path + "\000", + // parent directory does not exist + testProj.Path("non-existent-fldr", "cachedir"), + // path is a regular file + tmpFp, + // invalid path, tmp-file is a regular file + testProj.Path("tmp-file", "cachedir"), + } + + wantErr := "dep: $DEPCACHEDIR set to an invalid or inaccessible path" + for _, c := range cases { + testProj.Setenv("DEPCACHEDIR", c) + + err = testProj.DoRun([]string{"ensure"}) + + if err == nil { + // Log the output from running `dep ensure`, could be useful. + t.Logf("test run output: \n%s\n%s", testProj.GetStdout(), testProj.GetStderr()) + t.Error("unexpected result: \n\t(GOT) nil\n\t(WNT) exit status 1") + } else if stderr := testProj.GetStderr(); !strings.Contains(stderr, wantErr) { + t.Errorf( + "unexpected error output: \n\t(GOT) %s\n\t(WNT) %s", + strings.TrimSpace(stderr), wantErr, + ) + } + } + }) + +} + +// execCmd is a test.RunFunc which runs the program in another process. +func execCmd(prog string, args []string, stdout, stderr io.Writer, dir string, env []string) error { + cmd := exec.Command(prog, args...) + cmd.Stdout = stdout + cmd.Stderr = stderr + cmd.Env = env + cmd.Dir = dir + return cmd.Run() +} + +// runMain is a test.RunFunc which runs the program in-process. +func runMain(prog string, args []string, stdout, stderr io.Writer, dir string, env []string) (err error) { + defer func() { + if r := recover(); r != nil { + switch r := r.(type) { + case error: + err = r + default: + err = fmt.Errorf("%v", r) + } + } + }() + m := &Config{ + Args: append([]string{prog}, args...), + Stdout: stdout, + Stderr: stderr, + WorkingDir: dir, + Env: env, + } + if exitCode := m.Run(); exitCode != 0 { + err = fmt.Errorf("exit status %d", exitCode) + } + return +} + +// testIntegration runs the test specified by ///testcase.json +func testIntegration(name, relPath, wd string, run integration.RunFunc) func(t *testing.T) { + return func(t *testing.T) { + t.Parallel() + + // Set up environment + testCase := integration.NewTestCase(t, filepath.Join(wd, relPath), name) + testProj := integration.NewTestProject(t, testCase.InitialPath(), wd, run) + defer testProj.Cleanup() + + // Create and checkout the vendor revisions + for ip, rev := range testCase.VendorInitial { + testProj.GetVendorGit(ip) + testProj.RunGit(testProj.VendorPath(ip), "checkout", rev) + } + + // Create and checkout the import revisions + for ip, rev := range testCase.GopathInitial { + testProj.RunGo("get", ip) + testProj.RunGit(testProj.Path("src", ip), "checkout", rev) + } + + // Run commands + testProj.RecordImportPaths() + + var err error + for i, args := range testCase.Commands { + err = testProj.DoRun(args) + if err != nil && i < len(testCase.Commands)-1 { + t.Fatalf("cmd %s raised an unexpected error: %s", args[0], err.Error()) + } + } + + // Check error raised in final command + testCase.CompareError(err, testProj.GetStderr()) + + if *test.UpdateGolden { + testCase.UpdateOutput(testProj.GetStdout()) + } else { + // Check output + testCase.CompareOutput(testProj.GetStdout()) + } + + // Check vendor paths + testProj.CompareImportPaths() + testCase.CompareVendorPaths(testProj.GetVendorPaths()) + + if *test.UpdateGolden { + // Update manifest and lock + testCase.UpdateFile(dep.ManifestName, testProj.ProjPath(dep.ManifestName)) + testCase.UpdateFile(dep.LockName, testProj.ProjPath(dep.LockName)) + } else { + // Check final manifest and lock + testCase.CompareFile(dep.ManifestName, testProj.ProjPath(dep.ManifestName)) + testCase.CompareFile(dep.LockName, testProj.ProjPath(dep.LockName)) + } + } +} diff --git a/vendor/github.com/golang/dep/cmd/dep/main.go b/vendor/github.com/golang/dep/cmd/dep/main.go new file mode 100644 index 00000000..969d8b8d --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/main.go @@ -0,0 +1,329 @@ +// Copyright 2016 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. + +//go:generate ./mkdoc.sh + +package main + +import ( + "bytes" + "flag" + "fmt" + "io" + "log" + "os" + "path/filepath" + "strings" + "text/tabwriter" + + "github.com/golang/dep" + "github.com/golang/dep/internal/fs" +) + +var ( + successExitCode = 0 + errorExitCode = 1 +) + +type command interface { + Name() string // "foobar" + Args() string // " [quux...]" + ShortHelp() string // "Foo the first bar" + LongHelp() string // "Foo the first bar meeting the following conditions..." + Register(*flag.FlagSet) // command-specific flags + Hidden() bool // indicates whether the command should be hidden from help output + Run(*dep.Ctx, []string) error +} + +func main() { + wd, err := os.Getwd() + if err != nil { + fmt.Fprintln(os.Stderr, "failed to get working directory", err) + os.Exit(1) + } + c := &Config{ + Args: os.Args, + Stdout: os.Stdout, + Stderr: os.Stderr, + WorkingDir: wd, + Env: os.Environ(), + } + os.Exit(c.Run()) +} + +// A Config specifies a full configuration for a dep execution. +type Config struct { + WorkingDir string // Where to execute + Args []string // Command-line arguments, starting with the program name. + Env []string // Environment variables + Stdout, Stderr io.Writer // Log output +} + +// Run executes a configuration and returns an exit code. +func (c *Config) Run() int { + // Build the list of available commands. + commands := [...]command{ + &initCommand{}, + &statusCommand{}, + &ensureCommand{}, + &pruneCommand{}, + &hashinCommand{}, + &versionCommand{}, + } + + examples := [...][2]string{ + { + "dep init", + "set up a new project", + }, + { + "dep ensure", + "install the project's dependencies", + }, + { + "dep ensure -update", + "update the locked versions of all dependencies", + }, + { + "dep ensure -add github.com/pkg/errors", + "add a dependency to the project", + }, + } + + usage := func(w io.Writer) { + fmt.Fprintln(w, "Dep is a tool for managing dependencies for Go projects") + fmt.Fprintln(w) + fmt.Fprintln(w, "Usage: \"dep [command]\"") + fmt.Fprintln(w) + fmt.Fprintln(w, "Commands:") + fmt.Fprintln(w) + tw := tabwriter.NewWriter(w, 0, 0, 2, ' ', 0) + for _, cmd := range commands { + if !cmd.Hidden() { + fmt.Fprintf(tw, "\t%s\t%s\n", cmd.Name(), cmd.ShortHelp()) + } + } + tw.Flush() + fmt.Fprintln(w) + fmt.Fprintln(w, "Examples:") + for _, example := range examples { + fmt.Fprintf(tw, "\t%s\t%s\n", example[0], example[1]) + } + tw.Flush() + fmt.Fprintln(w) + fmt.Fprintln(w, "Use \"dep help [command]\" for more information about a command.") + } + + cmdName, printCommandHelp, exit := parseArgs(c.Args) + if exit { + usage(c.Stderr) + return errorExitCode + } + + // 'dep help documentation' generates doc.go. + if printCommandHelp && cmdName == "documentation" { + fmt.Println("// Copyright 2017 The Go Authors. All rights reserved.") + fmt.Println("// Use of this source code is governed by a BSD-style") + fmt.Println("// license that can be found in the LICENSE file.") + fmt.Println() + fmt.Println("// DO NOT EDIT THIS FILE. GENERATED BY mkdoc.sh.") + fmt.Println("// Edit the documentation in other files and rerun mkdoc.sh to generate this one.") + fmt.Println() + + var cw io.Writer = &commentWriter{W: c.Stdout} + usage(cw) + for _, cmd := range commands { + if !cmd.Hidden() { + fmt.Fprintln(cw) + short := cmd.ShortHelp() + fmt.Fprintln(cw, short) + fmt.Fprintln(cw) + fmt.Fprintln(cw, "Usage:") + fmt.Fprintln(cw) + fmt.Fprintln(cw, "", cmd.Name(), cmd.Args()) + if long := cmd.LongHelp(); long != short { + fmt.Fprintln(cw, long) + } + } + } + + fmt.Println("//") + fmt.Println("package main") + return successExitCode + } + + outLogger := log.New(c.Stdout, "", 0) + errLogger := log.New(c.Stderr, "", 0) + + for _, cmd := range commands { + if cmd.Name() == cmdName { + // Build flag set with global flags in there. + flags := flag.NewFlagSet(cmdName, flag.ContinueOnError) + flags.SetOutput(c.Stderr) + verbose := flags.Bool("v", false, "enable verbose logging") + + // Register the subcommand flags in there, too. + cmd.Register(flags) + + // Override the usage text to something nicer. + resetUsage(errLogger, flags, cmdName, cmd.Args(), cmd.LongHelp()) + + if printCommandHelp { + flags.Usage() + return errorExitCode + } + + // Parse the flags the user gave us. + // flag package automatically prints usage and error message in err != nil + // or if '-h' flag provided + if err := flags.Parse(c.Args[2:]); err != nil { + return errorExitCode + } + + // Cachedir is loaded from env if present. `$GOPATH/pkg/dep` is used as the + // default cache location. + cachedir := getEnv(c.Env, "DEPCACHEDIR") + if cachedir != "" { + if err := fs.EnsureDir(cachedir, 0777); err != nil { + errLogger.Printf( + "dep: $DEPCACHEDIR set to an invalid or inaccessible path: %q\n", cachedir, + ) + errLogger.Printf("dep: failed to ensure cache directory: %v\n", err) + return errorExitCode + } + } + + // Set up dep context. + ctx := &dep.Ctx{ + Out: outLogger, + Err: errLogger, + Verbose: *verbose, + DisableLocking: getEnv(c.Env, "DEPNOLOCK") != "", + Cachedir: cachedir, + } + + GOPATHS := filepath.SplitList(getEnv(c.Env, "GOPATH")) + ctx.SetPaths(c.WorkingDir, GOPATHS...) + + // Run the command with the post-flag-processing args. + if err := cmd.Run(ctx, flags.Args()); err != nil { + errLogger.Printf("%v\n", err) + return errorExitCode + } + + // Easy peasy livin' breezy. + return successExitCode + } + } + + errLogger.Printf("dep: %s: no such command\n", cmdName) + usage(c.Stderr) + return errorExitCode +} + +func resetUsage(logger *log.Logger, fs *flag.FlagSet, name, args, longHelp string) { + var ( + hasFlags bool + flagBlock bytes.Buffer + flagWriter = tabwriter.NewWriter(&flagBlock, 0, 4, 2, ' ', 0) + ) + fs.VisitAll(func(f *flag.Flag) { + hasFlags = true + // Default-empty string vars should read "(default: )" + // rather than the comparatively ugly "(default: )". + defValue := f.DefValue + if defValue == "" { + defValue = "" + } + fmt.Fprintf(flagWriter, "\t-%s\t%s (default: %s)\n", f.Name, f.Usage, defValue) + }) + flagWriter.Flush() + fs.Usage = func() { + logger.Printf("Usage: dep %s %s\n", name, args) + logger.Println() + logger.Println(strings.TrimSpace(longHelp)) + logger.Println() + if hasFlags { + logger.Println("Flags:") + logger.Println() + logger.Println(flagBlock.String()) + } + } +} + +// parseArgs determines the name of the dep command and whether the user asked for +// help to be printed. +func parseArgs(args []string) (cmdName string, printCmdUsage bool, exit bool) { + isHelpArg := func() bool { + return strings.Contains(strings.ToLower(args[1]), "help") || strings.ToLower(args[1]) == "-h" + } + + switch len(args) { + case 0, 1: + exit = true + case 2: + if isHelpArg() { + exit = true + } else { + cmdName = args[1] + } + default: + if isHelpArg() { + cmdName = args[2] + printCmdUsage = true + } else { + cmdName = args[1] + } + } + return cmdName, printCmdUsage, exit +} + +// getEnv returns the last instance of an environment variable. +func getEnv(env []string, key string) string { + for i := len(env) - 1; i >= 0; i-- { + v := env[i] + kv := strings.SplitN(v, "=", 2) + if kv[0] == key { + if len(kv) > 1 { + return kv[1] + } + return "" + } + } + return "" +} + +// commentWriter writes a Go comment to the underlying io.Writer, +// using line comment form (//). +// +// Copied from cmd/go/internal/help/help.go. +type commentWriter struct { + W io.Writer + wroteSlashes bool // Wrote "//" at the beginning of the current line. +} + +func (c *commentWriter) Write(p []byte) (int, error) { + var n int + for i, b := range p { + if !c.wroteSlashes { + s := "//" + if b != '\n' { + s = "// " + } + if _, err := io.WriteString(c.W, s); err != nil { + return n, err + } + c.wroteSlashes = true + } + n0, err := c.W.Write(p[i : i+1]) + n += n0 + if err != nil { + return n, err + } + if b == '\n' { + c.wroteSlashes = false + } + } + return len(p), nil +} diff --git a/vendor/github.com/golang/dep/cmd/dep/mkdoc.sh b/vendor/github.com/golang/dep/cmd/dep/mkdoc.sh new file mode 100755 index 00000000..c2e6941f --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/mkdoc.sh @@ -0,0 +1,11 @@ +#!/bin/bash +# Copyright 2017 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. + +set -e + +go build -o dep.latest +./dep.latest help documentation >doc.go +gofmt -w doc.go +rm dep.latest diff --git a/vendor/github.com/golang/dep/cmd/dep/prune.go b/vendor/github.com/golang/dep/cmd/dep/prune.go new file mode 100644 index 00000000..41e5e80e --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/prune.go @@ -0,0 +1,211 @@ +// Copyright 2017 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 main + +import ( + "bytes" + "flag" + "io/ioutil" + "log" + "os" + "path/filepath" + "sort" + "strings" + + "github.com/golang/dep" + "github.com/golang/dep/gps" + "github.com/golang/dep/gps/pkgtree" + "github.com/golang/dep/internal/fs" + "github.com/pkg/errors" +) + +const pruneShortHelp = `Pruning is now performed automatically by dep ensure.` +const pruneLongHelp = ` +Prune was merged into the ensure command. +Set prune options in the manifest and it will be applied after every ensure. +dep prune will be removed in a future version of dep, causing this command to exit non-0. +` + +type pruneCommand struct { +} + +func (cmd *pruneCommand) Name() string { return "prune" } +func (cmd *pruneCommand) Args() string { return "" } +func (cmd *pruneCommand) ShortHelp() string { return pruneShortHelp } +func (cmd *pruneCommand) LongHelp() string { return pruneLongHelp } +func (cmd *pruneCommand) Hidden() bool { return false } + +func (cmd *pruneCommand) Register(fs *flag.FlagSet) { +} + +func (cmd *pruneCommand) Run(ctx *dep.Ctx, args []string) error { + ctx.Err.Printf("Pruning is now performed automatically by dep ensure.\n") + ctx.Err.Printf("Set prune settings in %s and it it will be applied when running ensure.\n", dep.ManifestName) + ctx.Err.Printf("\nThis command currently still prunes as it always has, to ease the transition.\n") + ctx.Err.Printf("However, it will be removed in a future version of dep.\n") + ctx.Err.Printf("\nNow is the time to update your Gopkg.toml and remove `dep prune` from any scripts.\n") + + p, err := ctx.LoadProject() + if err != nil { + return err + } + + sm, err := ctx.SourceManager() + if err != nil { + return err + } + sm.UseDefaultSignalHandling() + defer sm.Release() + + // While the network churns on ListVersions() requests, statically analyze + // code from the current project. + ptree, err := pkgtree.ListPackages(p.ResolvedAbsRoot, string(p.ImportRoot)) + if err != nil { + return errors.Wrap(err, "analysis of local packages failed: %v") + } + + // Set up a solver in order to check the InputHash. + params := p.MakeParams() + params.RootPackageTree = ptree + + if ctx.Verbose { + params.TraceLogger = ctx.Err + } + + s, err := gps.Prepare(params, sm) + if err != nil { + return errors.Wrap(err, "could not set up solver for input hashing") + } + + if p.Lock == nil { + return errors.Errorf("Gopkg.lock must exist for prune to know what files are safe to remove.") + } + + if !bytes.Equal(s.HashInputs(), p.Lock.SolveMeta.InputsDigest) { + return errors.Errorf("Gopkg.lock is out of sync; run dep ensure before pruning.") + } + + pruneLogger := ctx.Err + if !ctx.Verbose { + pruneLogger = log.New(ioutil.Discard, "", 0) + } + return pruneProject(p, sm, pruneLogger) +} + +// pruneProject removes unused packages from a project. +func pruneProject(p *dep.Project, sm gps.SourceManager, logger *log.Logger) error { + td, err := ioutil.TempDir(os.TempDir(), "dep") + if err != nil { + return errors.Wrap(err, "error while creating temp dir for writing manifest/lock/vendor") + } + defer os.RemoveAll(td) + + if err := gps.WriteDepTree(td, p.Lock, sm, gps.CascadingPruneOptions{DefaultOptions: gps.PruneNestedVendorDirs}, logger); err != nil { + return err + } + + var toKeep []string + for _, project := range p.Lock.Projects() { + projectRoot := string(project.Ident().ProjectRoot) + for _, pkg := range project.Packages() { + toKeep = append(toKeep, filepath.Join(projectRoot, pkg)) + } + } + + toDelete, err := calculatePrune(td, toKeep, logger) + if err != nil { + return err + } + + if len(toDelete) > 0 { + logger.Println("Calculated the following directories to prune:") + for _, d := range toDelete { + logger.Printf(" %s\n", d) + } + } else { + logger.Println("No directories found to prune") + } + + if err := deleteDirs(toDelete); err != nil { + return err + } + + vpath := filepath.Join(p.AbsRoot, "vendor") + vendorbak := vpath + ".orig" + var failerr error + if _, err := os.Stat(vpath); err == nil { + // Move out the old vendor dir. just do it into an adjacent dir, to + // try to mitigate the possibility of a pointless cross-filesystem + // move with a temp directory. + if _, err := os.Stat(vendorbak); err == nil { + // If the adjacent dir already exists, bite the bullet and move + // to a proper tempdir. + vendorbak = filepath.Join(td, "vendor.orig") + } + failerr = fs.RenameWithFallback(vpath, vendorbak) + if failerr != nil { + goto fail + } + } + + // Move in the new one. + failerr = fs.RenameWithFallback(td, vpath) + if failerr != nil { + goto fail + } + + os.RemoveAll(vendorbak) + + return nil + +fail: + fs.RenameWithFallback(vendorbak, vpath) + return failerr +} + +func calculatePrune(vendorDir string, keep []string, logger *log.Logger) ([]string, error) { + logger.Println("Calculating prune. Checking the following packages:") + sort.Strings(keep) + toDelete := []string{} + err := filepath.Walk(vendorDir, func(path string, info os.FileInfo, err error) error { + if _, err := os.Lstat(path); err != nil { + return nil + } + if !info.IsDir() { + return nil + } + if path == vendorDir { + return nil + } + + name := strings.TrimPrefix(path, vendorDir+string(filepath.Separator)) + logger.Printf(" %s", name) + i := sort.Search(len(keep), func(i int) bool { + return name <= keep[i] + }) + if i >= len(keep) || !strings.HasPrefix(keep[i], name) { + toDelete = append(toDelete, path) + } + return nil + }) + return toDelete, err +} + +func deleteDirs(toDelete []string) error { + // sort by length so we delete sub dirs first + sort.Sort(byLen(toDelete)) + for _, path := range toDelete { + if err := os.RemoveAll(path); err != nil { + return err + } + } + return nil +} + +type byLen []string + +func (a byLen) Len() int { return len(a) } +func (a byLen) Swap(i, j int) { a[i], a[j] = a[j], a[i] } +func (a byLen) Less(i, j int) bool { return len(a[i]) > len(a[j]) } diff --git a/vendor/github.com/golang/dep/cmd/dep/root_analyzer.go b/vendor/github.com/golang/dep/cmd/dep/root_analyzer.go new file mode 100644 index 00000000..76d410fe --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/root_analyzer.go @@ -0,0 +1,209 @@ +// Copyright 2016 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 main + +import ( + "context" + "io/ioutil" + "log" + + "golang.org/x/sync/errgroup" + + "github.com/golang/dep" + "github.com/golang/dep/gps" + fb "github.com/golang/dep/internal/feedback" + "github.com/golang/dep/internal/importers" +) + +// rootAnalyzer supplies manifest/lock data from both dep and external tool's +// configuration files. +// * When used on the root project, it imports only from external tools. +// * When used by the solver for dependencies, it first looks for dep config, +// then external tools. +type rootAnalyzer struct { + skipTools bool + ctx *dep.Ctx + sm gps.SourceManager + directDeps map[gps.ProjectRoot]bool +} + +func newRootAnalyzer(skipTools bool, ctx *dep.Ctx, directDeps map[gps.ProjectRoot]bool, sm gps.SourceManager) *rootAnalyzer { + return &rootAnalyzer{ + skipTools: skipTools, + ctx: ctx, + sm: sm, + directDeps: directDeps, + } +} + +func (a *rootAnalyzer) InitializeRootManifestAndLock(dir string, pr gps.ProjectRoot) (rootM *dep.Manifest, rootL *dep.Lock, err error) { + if !a.skipTools { + rootM, rootL = a.importManifestAndLock(dir, pr, false) + } + + if rootM == nil { + rootM = dep.NewManifest() + + // Since we didn't find anything to import, dep's cache is empty. + // We are prefetching dependencies and logging so that the subsequent solve step + // doesn't spend a long time retrieving dependencies without feedback for the user. + if err := a.cacheDeps(pr); err != nil { + return nil, nil, err + } + } + if rootL == nil { + rootL = &dep.Lock{} + } + + return +} + +func (a *rootAnalyzer) cacheDeps(pr gps.ProjectRoot) error { + logger := a.ctx.Err + g, _ := errgroup.WithContext(context.TODO()) + concurrency := 4 + + syncDep := func(pr gps.ProjectRoot, sm gps.SourceManager) error { + if err := sm.SyncSourceFor(gps.ProjectIdentifier{ProjectRoot: pr}); err != nil { + logger.Printf("Unable to cache %s - %s", pr, err) + return err + } + return nil + } + + deps := make(chan gps.ProjectRoot) + + for i := 0; i < concurrency; i++ { + g.Go(func() error { + for d := range deps { + err := syncDep(gps.ProjectRoot(d), a.sm) + if err != nil { + return err + } + } + return nil + }) + } + + g.Go(func() error { + defer close(deps) + for pr := range a.directDeps { + logger.Printf("Caching package %q", pr) + deps <- pr + } + return nil + }) + + if err := g.Wait(); err != nil { + return err + } + logger.Printf("Successfully cached all deps.") + return nil +} + +func (a *rootAnalyzer) importManifestAndLock(dir string, pr gps.ProjectRoot, suppressLogs bool) (*dep.Manifest, *dep.Lock) { + logger := a.ctx.Err + if suppressLogs { + logger = log.New(ioutil.Discard, "", 0) + } + + for _, i := range importers.BuildAll(logger, a.ctx.Verbose, a.sm) { + if i.HasDepMetadata(dir) { + a.ctx.Err.Printf("Importing configuration from %s. These are only initial constraints, and are further refined during the solve process.", i.Name()) + m, l, err := i.Import(dir, pr) + if err != nil { + a.ctx.Err.Printf( + "Warning: Encountered an unrecoverable error while trying to import %s config from %q: %s", + i.Name(), dir, err, + ) + break + } + a.removeTransitiveDependencies(m) + return m, l + } + } + + var emptyManifest = dep.NewManifest() + + return emptyManifest, nil +} + +func (a *rootAnalyzer) removeTransitiveDependencies(m *dep.Manifest) { + for pr := range m.Constraints { + if _, isDirect := a.directDeps[pr]; !isDirect { + delete(m.Constraints, pr) + } + } +} + +// DeriveManifestAndLock evaluates a dependency for existing dependency manager +// configuration (ours or external) and passes any configuration found back +// to the solver. +func (a *rootAnalyzer) DeriveManifestAndLock(dir string, pr gps.ProjectRoot) (gps.Manifest, gps.Lock, error) { + // Ignore other tools if we find dep configuration + var depAnalyzer dep.Analyzer + if depAnalyzer.HasDepMetadata(dir) { + return depAnalyzer.DeriveManifestAndLock(dir, pr) + } + + if !a.skipTools { + // The assignment back to an interface prevents interface-based nil checks from failing later + var manifest gps.Manifest = gps.SimpleManifest{} + var lock gps.Lock + im, il := a.importManifestAndLock(dir, pr, true) + if im != nil { + manifest = im + } + if il != nil { + lock = il + } + return manifest, lock, nil + } + + return gps.SimpleManifest{}, nil, nil +} + +func (a *rootAnalyzer) FinalizeRootManifestAndLock(m *dep.Manifest, l *dep.Lock, ol dep.Lock) { + // Iterate through the new projects in solved lock and add them to manifest + // if they are direct deps and log feedback for all the new projects. + for _, y := range l.Projects() { + var f *fb.ConstraintFeedback + pr := y.Ident().ProjectRoot + // New constraints: in new lock and dir dep but not in manifest + if _, ok := a.directDeps[pr]; ok { + if _, ok := m.Constraints[pr]; !ok { + pp := getProjectPropertiesFromVersion(y.Version()) + if pp.Constraint != nil { + m.Constraints[pr] = pp + pc := gps.ProjectConstraint{Ident: y.Ident(), Constraint: pp.Constraint} + f = fb.NewConstraintFeedback(pc, fb.DepTypeDirect) + f.LogFeedback(a.ctx.Err) + } + f = fb.NewLockedProjectFeedback(y, fb.DepTypeDirect) + f.LogFeedback(a.ctx.Err) + } + } else { + // New locked projects: in new lock but not in old lock + newProject := true + for _, opl := range ol.Projects() { + if pr == opl.Ident().ProjectRoot { + newProject = false + } + } + if newProject { + f = fb.NewLockedProjectFeedback(y, fb.DepTypeTransitive) + f.LogFeedback(a.ctx.Err) + } + } + } +} + +// Info provides metadata on the analyzer algorithm used during solve. +func (a *rootAnalyzer) Info() gps.ProjectAnalyzerInfo { + return gps.ProjectAnalyzerInfo{ + Name: "dep", + Version: 1, + } +} diff --git a/vendor/github.com/golang/dep/cmd/dep/status.go b/vendor/github.com/golang/dep/cmd/dep/status.go new file mode 100644 index 00000000..c342b20f --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/status.go @@ -0,0 +1,844 @@ +// Copyright 2016 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 main + +import ( + "bytes" + "encoding/json" + "flag" + "fmt" + "html/template" + "io" + "io/ioutil" + "log" + "sort" + "sync" + "text/tabwriter" + + "github.com/golang/dep" + "github.com/golang/dep/gps" + "github.com/golang/dep/gps/paths" + "github.com/pkg/errors" +) + +const statusShortHelp = `Report the status of the project's dependencies` +const statusLongHelp = ` +With no arguments, print the status of each dependency of the project. + + PROJECT Import path + CONSTRAINT Version constraint, from the manifest + VERSION Version chosen, from the lock + REVISION VCS revision of the chosen version + LATEST Latest VCS revision available + PKGS USED Number of packages from this project that are actually used + +With one or more explicitly specified packages, or with the -detailed flag, +print an extended status output for each dependency of the project. + + TODO Another column description + FOOBAR Another column description + +Status returns exit code zero if all dependencies are in a "good state". +` + +const ( + shortRev uint8 = iota + longRev +) + +var ( + errFailedUpdate = errors.New("failed to fetch updates") + errFailedListPkg = errors.New("failed to list packages") + errMultipleFailures = errors.New("multiple sources of failure") + errInputDigestMismatch = errors.New("input-digest mismatch") +) + +func (cmd *statusCommand) Name() string { return "status" } +func (cmd *statusCommand) Args() string { return "[package...]" } +func (cmd *statusCommand) ShortHelp() string { return statusShortHelp } +func (cmd *statusCommand) LongHelp() string { return statusLongHelp } +func (cmd *statusCommand) Hidden() bool { return false } + +func (cmd *statusCommand) Register(fs *flag.FlagSet) { + fs.BoolVar(&cmd.json, "json", false, "output in JSON format") + fs.StringVar(&cmd.template, "f", "", "output in text/template format") + fs.BoolVar(&cmd.dot, "dot", false, "output the dependency graph in GraphViz format") + fs.BoolVar(&cmd.old, "old", false, "only show out-of-date dependencies") + fs.BoolVar(&cmd.missing, "missing", false, "only show missing dependencies") +} + +type statusCommand struct { + json bool + template string + output string + dot bool + old bool + missing bool +} + +type outputter interface { + BasicHeader() error + BasicLine(*BasicStatus) error + BasicFooter() error + MissingHeader() error + MissingLine(*MissingStatus) error + MissingFooter() error +} + +type tableOutput struct{ w *tabwriter.Writer } + +func (out *tableOutput) BasicHeader() error { + _, err := fmt.Fprintf(out.w, "PROJECT\tCONSTRAINT\tVERSION\tREVISION\tLATEST\tPKGS USED\n") + return err +} + +func (out *tableOutput) BasicFooter() error { + return out.w.Flush() +} + +func (out *tableOutput) BasicLine(bs *BasicStatus) error { + _, err := fmt.Fprintf(out.w, + "%s\t%s\t%s\t%s\t%s\t%d\t\n", + bs.ProjectRoot, + bs.getConsolidatedConstraint(), + formatVersion(bs.Version), + formatVersion(bs.Revision), + bs.getConsolidatedLatest(shortRev), + bs.PackageCount, + ) + return err +} + +func (out *tableOutput) MissingHeader() error { + _, err := fmt.Fprintln(out.w, "PROJECT\tMISSING PACKAGES") + return err +} + +func (out *tableOutput) MissingLine(ms *MissingStatus) error { + _, err := fmt.Fprintf(out.w, + "%s\t%s\t\n", + ms.ProjectRoot, + ms.MissingPackages, + ) + return err +} + +func (out *tableOutput) MissingFooter() error { + return out.w.Flush() +} + +type jsonOutput struct { + w io.Writer + basic []*rawStatus + missing []*MissingStatus +} + +func (out *jsonOutput) BasicHeader() error { + out.basic = []*rawStatus{} + return nil +} + +func (out *jsonOutput) BasicFooter() error { + return json.NewEncoder(out.w).Encode(out.basic) +} + +func (out *jsonOutput) BasicLine(bs *BasicStatus) error { + out.basic = append(out.basic, bs.marshalJSON()) + return nil +} + +func (out *jsonOutput) MissingHeader() error { + out.missing = []*MissingStatus{} + return nil +} + +func (out *jsonOutput) MissingLine(ms *MissingStatus) error { + out.missing = append(out.missing, ms) + return nil +} + +func (out *jsonOutput) MissingFooter() error { + return json.NewEncoder(out.w).Encode(out.missing) +} + +type dotOutput struct { + w io.Writer + o string + g *graphviz + p *dep.Project +} + +func (out *dotOutput) BasicHeader() error { + out.g = new(graphviz).New() + + ptree, err := out.p.ParseRootPackageTree() + // TODO(sdboyer) should be true, true, false, out.p.Manifest.IgnoredPackages() + prm, _ := ptree.ToReachMap(true, false, false, nil) + + out.g.createNode(string(out.p.ImportRoot), "", prm.FlattenFn(paths.IsStandardImportPath)) + + return err +} + +func (out *dotOutput) BasicFooter() error { + gvo := out.g.output() + _, err := fmt.Fprintf(out.w, gvo.String()) + return err +} + +func (out *dotOutput) BasicLine(bs *BasicStatus) error { + out.g.createNode(bs.ProjectRoot, bs.getConsolidatedVersion(), bs.Children) + return nil +} + +func (out *dotOutput) MissingHeader() error { return nil } +func (out *dotOutput) MissingLine(ms *MissingStatus) error { return nil } +func (out *dotOutput) MissingFooter() error { return nil } + +type templateOutput struct { + w io.Writer + tmpl *template.Template +} + +func (out *templateOutput) BasicHeader() error { return nil } +func (out *templateOutput) BasicFooter() error { return nil } + +func (out *templateOutput) BasicLine(bs *BasicStatus) error { + return out.tmpl.Execute(out.w, bs) +} + +func (out *templateOutput) MissingHeader() error { return nil } +func (out *templateOutput) MissingFooter() error { return nil } + +func (out *templateOutput) MissingLine(ms *MissingStatus) error { + return out.tmpl.Execute(out.w, ms) +} + +func (cmd *statusCommand) Run(ctx *dep.Ctx, args []string) error { + if err := cmd.validateFlags(); err != nil { + return err + } + + p, err := ctx.LoadProject() + if err != nil { + return err + } + + sm, err := ctx.SourceManager() + if err != nil { + return err + } + sm.UseDefaultSignalHandling() + defer sm.Release() + + if err := dep.ValidateProjectRoots(ctx, p.Manifest, sm); err != nil { + return err + } + + var buf bytes.Buffer + var out outputter + switch { + case cmd.missing: + return errors.Errorf("not implemented") + case cmd.old: + return errors.Errorf("not implemented") + case cmd.json: + out = &jsonOutput{ + w: &buf, + } + case cmd.dot: + out = &dotOutput{ + p: p, + o: cmd.output, + w: &buf, + } + case cmd.template != "": + tmpl, err := template.New("status").Parse(cmd.template) + if err != nil { + return err + } + out = &templateOutput{ + w: &buf, + tmpl: tmpl, + } + default: + out = &tableOutput{ + w: tabwriter.NewWriter(&buf, 0, 4, 2, ' ', 0), + } + } + + // Check if the lock file exists. + if p.Lock == nil { + return errors.Errorf("no Gopkg.lock found. Run `dep ensure` to generate lock file") + } + + hasMissingPkgs, errCount, err := runStatusAll(ctx, out, p, sm) + if err != nil { + switch err { + case errFailedUpdate: + // Print the results with unknown data + ctx.Out.Println(buf.String()) + // Print the help when in non-verbose mode + if !ctx.Verbose { + ctx.Out.Printf("The status of %d projects are unknown due to errors. Rerun with `-v` flag to see details.\n", errCount) + } + case errInputDigestMismatch: + // Tell the user why mismatch happened and how to resolve it. + if hasMissingPkgs { + ctx.Err.Printf("Lock inputs-digest mismatch due to the following packages missing from the lock:\n\n") + ctx.Out.Print(buf.String()) + ctx.Err.Printf("\nThis happens when a new import is added. Run `dep ensure` to install the missing packages.\n") + } else { + ctx.Err.Printf("Lock inputs-digest mismatch. This happens when Gopkg.toml is modified.\n" + + "Run `dep ensure` to regenerate the inputs-digest.") + } + } + + return err + } + + // Print the status output + ctx.Out.Print(buf.String()) + + return nil +} + +func (cmd *statusCommand) validateFlags() error { + // Operating mode flags. + opModes := []string{} + + if cmd.old { + opModes = append(opModes, "-old") + } + + if cmd.missing { + opModes = append(opModes, "-missing") + } + + // Check if any other flags are passed with -dot. + if cmd.dot { + if cmd.template != "" { + return errors.New("cannot pass template string with -dot") + } + + if cmd.json { + return errors.New("cannot pass multiple output format flags") + } + + if len(opModes) > 0 { + return errors.New("-dot generates dependency graph; cannot pass other flags") + } + } + + if len(opModes) > 1 { + // List the flags because which flags are for operation mode might not + // be apparent to the users. + return errors.Wrapf(errors.New("cannot pass multiple operating mode flags"), "%v", opModes) + } + + return nil +} + +type rawStatus struct { + ProjectRoot string + Constraint string + Version string + Revision string + Latest string + PackageCount int +} + +// BasicStatus contains all the information reported about a single dependency +// in the summary/list status output mode. +type BasicStatus struct { + ProjectRoot string + Children []string + Constraint gps.Constraint + Version gps.UnpairedVersion + Revision gps.Revision + Latest gps.Version + PackageCount int + hasOverride bool + hasError bool +} + +func (bs *BasicStatus) getConsolidatedConstraint() string { + var constraint string + if bs.Constraint != nil { + if v, ok := bs.Constraint.(gps.Version); ok { + constraint = formatVersion(v) + } else { + constraint = bs.Constraint.String() + } + } + + if bs.hasOverride { + constraint += " (override)" + } + + return constraint +} + +func (bs *BasicStatus) getConsolidatedVersion() string { + version := formatVersion(bs.Revision) + if bs.Version != nil { + version = formatVersion(bs.Version) + } + return version +} + +func (bs *BasicStatus) getConsolidatedLatest(revSize uint8) string { + latest := "" + if bs.Latest != nil { + switch revSize { + case shortRev: + latest = formatVersion(bs.Latest) + case longRev: + latest = bs.Latest.String() + } + } + + if bs.hasError { + latest += "unknown" + } + + return latest +} + +func (bs *BasicStatus) marshalJSON() *rawStatus { + return &rawStatus{ + ProjectRoot: bs.ProjectRoot, + Constraint: bs.getConsolidatedConstraint(), + Version: formatVersion(bs.Version), + Revision: string(bs.Revision), + Latest: bs.getConsolidatedLatest(longRev), + PackageCount: bs.PackageCount, + } +} + +// MissingStatus contains information about all the missing packages in a project. +type MissingStatus struct { + ProjectRoot string + MissingPackages []string +} + +func runStatusAll(ctx *dep.Ctx, out outputter, p *dep.Project, sm gps.SourceManager) (hasMissingPkgs bool, errCount int, err error) { + // While the network churns on ListVersions() requests, statically analyze + // code from the current project. + ptree, err := p.ParseRootPackageTree() + if err != nil { + return false, 0, err + } + + // Set up a solver in order to check the InputHash. + params := gps.SolveParameters{ + ProjectAnalyzer: dep.Analyzer{}, + RootDir: p.AbsRoot, + RootPackageTree: ptree, + Manifest: p.Manifest, + // Locks aren't a part of the input hash check, so we can omit it. + } + + logger := ctx.Err + if ctx.Verbose { + params.TraceLogger = ctx.Err + } else { + logger = log.New(ioutil.Discard, "", 0) + } + + if err := ctx.ValidateParams(sm, params); err != nil { + return false, 0, err + } + + s, err := gps.Prepare(params, sm) + if err != nil { + return false, 0, errors.Wrapf(err, "could not set up solver for input hashing") + } + + // Errors while collecting constraints should not fail the whole status run. + // It should count the error and tell the user about incomplete results. + cm, ccerrs := collectConstraints(ctx, p, sm) + if len(ccerrs) > 0 { + errCount += len(ccerrs) + } + + // Get the project list and sort it so that the printed output users see is + // deterministically ordered. (This may be superfluous if the lock is always + // written in alpha order, but it doesn't hurt to double down.) + slp := p.Lock.Projects() + sort.Slice(slp, func(i, j int) bool { + return slp[i].Ident().Less(slp[j].Ident()) + }) + + if bytes.Equal(s.HashInputs(), p.Lock.SolveMeta.InputsDigest) { + // If these are equal, we're guaranteed that the lock is a transitively + // complete picture of all deps. That eliminates the need for at least + // some checks. + + if err := out.BasicHeader(); err != nil { + return false, 0, err + } + + logger.Println("Checking upstream projects:") + + // BasicStatus channel to collect all the BasicStatus. + bsCh := make(chan *BasicStatus, len(slp)) + + // Error channels to collect different errors. + errListPkgCh := make(chan error, len(slp)) + errListVerCh := make(chan error, len(slp)) + + var wg sync.WaitGroup + + for i, proj := range slp { + wg.Add(1) + logger.Printf("(%d/%d) %s\n", i+1, len(slp), proj.Ident().ProjectRoot) + + go func(proj gps.LockedProject) { + bs := BasicStatus{ + ProjectRoot: string(proj.Ident().ProjectRoot), + PackageCount: len(proj.Packages()), + } + + // Get children only for specific outputers + // in order to avoid slower status process. + switch out.(type) { + case *dotOutput: + ptr, err := sm.ListPackages(proj.Ident(), proj.Version()) + + if err != nil { + bs.hasError = true + errListPkgCh <- err + } + + prm, _ := ptr.ToReachMap(true, true, false, p.Manifest.IgnoredPackages()) + bs.Children = prm.FlattenFn(paths.IsStandardImportPath) + } + + // Split apart the version from the lock into its constituent parts. + switch tv := proj.Version().(type) { + case gps.UnpairedVersion: + bs.Version = tv + case gps.Revision: + bs.Revision = tv + case gps.PairedVersion: + bs.Version = tv.Unpair() + bs.Revision = tv.Revision() + } + + // Check if the manifest has an override for this project. If so, + // set that as the constraint. + if pp, has := p.Manifest.Ovr[proj.Ident().ProjectRoot]; has && pp.Constraint != nil { + bs.hasOverride = true + bs.Constraint = pp.Constraint + } else if pp, has := p.Manifest.Constraints[proj.Ident().ProjectRoot]; has && pp.Constraint != nil { + // If the manifest has a constraint then set that as the constraint. + bs.Constraint = pp.Constraint + } else { + bs.Constraint = gps.Any() + for _, c := range cm[bs.ProjectRoot] { + bs.Constraint = c.Constraint.Intersect(bs.Constraint) + } + } + + // Only if we have a non-rev and non-plain version do/can we display + // anything wrt the version's updateability. + if bs.Version != nil && bs.Version.Type() != gps.IsVersion { + c, has := p.Manifest.Constraints[proj.Ident().ProjectRoot] + if !has { + // Get constraint for locked project + for _, lockedP := range p.Lock.P { + if lockedP.Ident().ProjectRoot == proj.Ident().ProjectRoot { + // Use the unpaired version as the constraint for checking updates. + c.Constraint = bs.Version + } + } + } + // TODO: This constraint is only the constraint imposed by the + // current project, not by any transitive deps. As a result, + // transitive project deps will always show "any" here. + bs.Constraint = c.Constraint + + vl, err := sm.ListVersions(proj.Ident()) + if err == nil { + gps.SortPairedForUpgrade(vl) + + for _, v := range vl { + // Because we've sorted the version list for + // upgrade, the first version we encounter that + // matches our constraint will be what we want. + if c.Constraint.Matches(v) { + // Latest should be of the same type as the Version. + if bs.Version.Type() == gps.IsSemver { + bs.Latest = v + } else { + bs.Latest = v.Revision() + } + break + } + } + } else { + // Failed to fetch version list (could happen due to + // network issue). + bs.hasError = true + errListVerCh <- err + } + } + + bsCh <- &bs + + wg.Done() + }(proj) + } + + wg.Wait() + close(bsCh) + close(errListPkgCh) + close(errListVerCh) + + // Newline after printing the status progress output. + logger.Println() + + // List Packages errors. This would happen only for dot output. + if len(errListPkgCh) > 0 { + err = errFailedListPkg + if ctx.Verbose { + for err := range errListPkgCh { + ctx.Err.Println(err.Error()) + } + ctx.Err.Println() + } + } + + // List Version errors. + if len(errListVerCh) > 0 { + if err == nil { + err = errFailedUpdate + } else { + err = errMultipleFailures + } + + // Count ListVersions error because we get partial results when + // this happens. + errCount += len(errListVerCh) + if ctx.Verbose { + for err := range errListVerCh { + ctx.Err.Println(err.Error()) + } + ctx.Err.Println() + } + } + + // A map of ProjectRoot and *BasicStatus. This is used in maintain the + // order of BasicStatus in output by collecting all the BasicStatus and + // then using them in order. + bsMap := make(map[string]*BasicStatus) + for bs := range bsCh { + bsMap[bs.ProjectRoot] = bs + } + + // Use the collected BasicStatus in outputter. + for _, proj := range slp { + if err := out.BasicLine(bsMap[string(proj.Ident().ProjectRoot)]); err != nil { + return false, 0, err + } + } + + if footerErr := out.BasicFooter(); footerErr != nil { + return false, 0, footerErr + } + + return false, errCount, err + } + + // Hash digest mismatch may indicate that some deps are no longer + // needed, some are missing, or that some constraints or source + // locations have changed. + // + // It's possible for digests to not match, but still have a correct + // lock. + rm, _ := ptree.ToReachMap(true, true, false, p.Manifest.IgnoredPackages()) + + external := rm.FlattenFn(paths.IsStandardImportPath) + roots := make(map[gps.ProjectRoot][]string, len(external)) + + type fail struct { + ex string + err error + } + var errs []fail + for _, e := range external { + root, err := sm.DeduceProjectRoot(e) + if err != nil { + errs = append(errs, fail{ + ex: e, + err: err, + }) + continue + } + + roots[root] = append(roots[root], e) + } + + if len(errs) != 0 { + // TODO this is just a fix quick so staticcheck doesn't complain. + // Visually reconciling failure to deduce project roots with the rest of + // the mismatch output is a larger problem. + ctx.Err.Printf("Failed to deduce project roots for import paths:\n") + for _, fail := range errs { + ctx.Err.Printf("\t%s: %s\n", fail.ex, fail.err.Error()) + } + + return false, 0, errors.New("address issues with undeducible import paths to get more status information") + } + + if err = out.MissingHeader(); err != nil { + return false, 0, err + } + +outer: + for root, pkgs := range roots { + // TODO also handle the case where the project is present, but there + // are items missing from just the package list + for _, lp := range slp { + if lp.Ident().ProjectRoot == root { + continue outer + } + } + + hasMissingPkgs = true + err := out.MissingLine(&MissingStatus{ProjectRoot: string(root), MissingPackages: pkgs}) + if err != nil { + return false, 0, err + } + } + if err = out.MissingFooter(); err != nil { + return false, 0, err + } + + // We are here because of an input-digest mismatch. Return error. + return hasMissingPkgs, 0, errInputDigestMismatch +} + +func formatVersion(v gps.Version) string { + if v == nil { + return "" + } + switch v.Type() { + case gps.IsBranch: + return "branch " + v.String() + case gps.IsRevision: + r := v.String() + if len(r) > 7 { + r = r[:7] + } + return r + } + return v.String() +} + +// projectConstraint stores ProjectRoot and Constraint for that project. +type projectConstraint struct { + Project gps.ProjectRoot + Constraint gps.Constraint +} + +// constraintsCollection is a map of ProjectRoot(dependency) and a collection of +// projectConstraint for the dependencies. This can be used to find constraints +// on a dependency and the projects that apply those constraints. +type constraintsCollection map[string][]projectConstraint + +// collectConstraints collects constraints declared by all the dependencies. +// It returns constraintsCollection and a slice of errors encountered while +// collecting the constraints, if any. +func collectConstraints(ctx *dep.Ctx, p *dep.Project, sm gps.SourceManager) (constraintsCollection, []error) { + logger := ctx.Err + if !ctx.Verbose { + logger = log.New(ioutil.Discard, "", 0) + } + + logger.Println("Collecting project constraints:") + + var mutex sync.Mutex + constraintCollection := make(constraintsCollection) + + // Collect the complete set of direct project dependencies, incorporating + // requireds and ignores appropriately. + _, directDeps, err := p.GetDirectDependencyNames(sm) + if err != nil { + // Return empty collection, not nil, if we fail here. + return constraintCollection, []error{errors.Wrap(err, "failed to get direct dependencies")} + } + + // Create a root analyzer. + rootAnalyzer := newRootAnalyzer(true, ctx, directDeps, sm) + + lp := p.Lock.Projects() + + // Channel for receiving all the errors. + errCh := make(chan error, len(lp)) + + var wg sync.WaitGroup + + // Iterate through the locked projects and collect constraints of all the projects. + for i, proj := range lp { + wg.Add(1) + logger.Printf("(%d/%d) %s\n", i+1, len(lp), proj.Ident().ProjectRoot) + + go func(proj gps.LockedProject) { + defer wg.Done() + + manifest, _, err := sm.GetManifestAndLock(proj.Ident(), proj.Version(), rootAnalyzer) + if err != nil { + errCh <- errors.Wrap(err, "error getting manifest and lock") + return + } + + // Get project constraints. + pc := manifest.DependencyConstraints() + + // Obtain a lock for constraintCollection. + mutex.Lock() + defer mutex.Unlock() + // Iterate through the project constraints to get individual dependency + // project and constraint values. + for pr, pp := range pc { + // Check if the project constraint is imported in the root project + if _, ok := directDeps[pr]; !ok { + continue + } + + tempCC := append( + constraintCollection[string(pr)], + projectConstraint{proj.Ident().ProjectRoot, pp.Constraint}, + ) + + // Sort the inner projectConstraint slice by Project string. + // Required for consistent returned value. + sort.Sort(byProject(tempCC)) + constraintCollection[string(pr)] = tempCC + } + }(proj) + } + + wg.Wait() + close(errCh) + + var errs []error + if len(errCh) > 0 { + for e := range errCh { + errs = append(errs, e) + logger.Println(e.Error()) + } + } + + return constraintCollection, errs +} + +type byProject []projectConstraint + +func (p byProject) Len() int { return len(p) } +func (p byProject) Swap(i, j int) { p[i], p[j] = p[j], p[i] } +func (p byProject) Less(i, j int) bool { return p[i].Project < p[j].Project } diff --git a/vendor/github.com/golang/dep/cmd/dep/status_test.go b/vendor/github.com/golang/dep/cmd/dep/status_test.go new file mode 100644 index 00000000..d18f9404 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/status_test.go @@ -0,0 +1,505 @@ +// Copyright 2017 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 main + +import ( + "bytes" + "io/ioutil" + "log" + "path/filepath" + "reflect" + "testing" + "text/tabwriter" + + "strings" + + "github.com/golang/dep" + "github.com/golang/dep/gps" + "github.com/golang/dep/internal/test" + "github.com/pkg/errors" +) + +func TestStatusFormatVersion(t *testing.T) { + t.Parallel() + + tests := map[gps.Version]string{ + nil: "", + gps.NewBranch("master"): "branch master", + gps.NewVersion("1.0.0"): "1.0.0", + gps.Revision("flooboofoobooo"): "flooboo", + } + for version, expected := range tests { + str := formatVersion(version) + if str != expected { + t.Fatalf("expected '%v', got '%v'", expected, str) + } + } +} + +func TestBasicLine(t *testing.T) { + project := dep.Project{} + aSemverConstraint, _ := gps.NewSemverConstraint("1.2.3") + + tests := []struct { + name string + status BasicStatus + wantDotStatus []string + wantJSONStatus []string + wantTableStatus []string + }{ + { + name: "BasicStatus with ProjectRoot only", + status: BasicStatus{ + ProjectRoot: "github.com/foo/bar", + }, + wantDotStatus: []string{`[label="github.com/foo/bar"];`}, + wantJSONStatus: []string{`"Version":""`, `"Revision":""`}, + wantTableStatus: []string{`github.com/foo/bar 0`}, + }, + { + name: "BasicStatus with Revision", + status: BasicStatus{ + ProjectRoot: "github.com/foo/bar", + Revision: gps.Revision("flooboofoobooo"), + }, + wantDotStatus: []string{`[label="github.com/foo/bar\nflooboo"];`}, + wantJSONStatus: []string{`"Version":""`, `"Revision":"flooboofoobooo"`, `"Constraint":""`}, + wantTableStatus: []string{`github.com/foo/bar flooboo 0`}, + }, + { + name: "BasicStatus with Version and Revision", + status: BasicStatus{ + ProjectRoot: "github.com/foo/bar", + Version: gps.NewVersion("1.0.0"), + Revision: gps.Revision("flooboofoobooo"), + }, + wantDotStatus: []string{`[label="github.com/foo/bar\n1.0.0"];`}, + wantJSONStatus: []string{`"Version":"1.0.0"`, `"Revision":"flooboofoobooo"`, `"Constraint":""`}, + wantTableStatus: []string{`github.com/foo/bar 1.0.0 flooboo 0`}, + }, + { + name: "BasicStatus with Constraint, Version and Revision", + status: BasicStatus{ + ProjectRoot: "github.com/foo/bar", + Constraint: aSemverConstraint, + Version: gps.NewVersion("1.0.0"), + Revision: gps.Revision("revxyz"), + }, + wantDotStatus: []string{`[label="github.com/foo/bar\n1.0.0"];`}, + wantJSONStatus: []string{`"Revision":"revxyz"`, `"Constraint":"1.2.3"`, `"Version":"1.0.0"`}, + wantTableStatus: []string{`github.com/foo/bar 1.2.3 1.0.0 revxyz 0`}, + }, + { + name: "BasicStatus with update error", + status: BasicStatus{ + ProjectRoot: "github.com/foo/bar", + hasError: true, + }, + wantDotStatus: []string{`[label="github.com/foo/bar"];`}, + wantJSONStatus: []string{`"Version":""`, `"Revision":""`, `"Latest":"unknown"`}, + wantTableStatus: []string{`github.com/foo/bar unknown 0`}, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + var buf bytes.Buffer + + dotout := &dotOutput{ + p: &project, + w: &buf, + } + dotout.BasicHeader() + dotout.BasicLine(&test.status) + dotout.BasicFooter() + + for _, wantStatus := range test.wantDotStatus { + if ok := strings.Contains(buf.String(), wantStatus); !ok { + t.Errorf("Did not find expected node status: \n\t(GOT) %v \n\t(WNT) %v", buf.String(), wantStatus) + } + } + + buf.Reset() + + jsonout := &jsonOutput{w: &buf} + + jsonout.BasicHeader() + jsonout.BasicLine(&test.status) + jsonout.BasicFooter() + + for _, wantStatus := range test.wantJSONStatus { + if ok := strings.Contains(buf.String(), wantStatus); !ok { + t.Errorf("Did not find expected JSON status: \n\t(GOT) %v \n\t(WNT) %v", buf.String(), wantStatus) + } + } + + buf.Reset() + + tabw := tabwriter.NewWriter(&buf, 0, 4, 2, ' ', 0) + + tableout := &tableOutput{w: tabw} + + tableout.BasicHeader() + tableout.BasicLine(&test.status) + tableout.BasicFooter() + + for _, wantStatus := range test.wantTableStatus { + if ok := strings.Contains(buf.String(), wantStatus); !ok { + t.Errorf("Did not find expected Table status: \n\t(GOT) %v \n\t(WNT) %v", buf.String(), wantStatus) + } + } + }) + } +} + +func TestBasicStatusGetConsolidatedConstraint(t *testing.T) { + aSemverConstraint, _ := gps.NewSemverConstraint("1.2.1") + + testCases := []struct { + name string + basicStatus BasicStatus + wantConstraint string + }{ + { + name: "empty BasicStatus", + basicStatus: BasicStatus{}, + wantConstraint: "", + }, + { + name: "BasicStatus with Any Constraint", + basicStatus: BasicStatus{ + Constraint: gps.Any(), + }, + wantConstraint: "*", + }, + { + name: "BasicStatus with Semver Constraint", + basicStatus: BasicStatus{ + Constraint: aSemverConstraint, + }, + wantConstraint: "1.2.1", + }, + { + name: "BasicStatus with Override", + basicStatus: BasicStatus{ + Constraint: aSemverConstraint, + hasOverride: true, + }, + wantConstraint: "1.2.1 (override)", + }, + { + name: "BasicStatus with Revision Constraint", + basicStatus: BasicStatus{ + Constraint: gps.Revision("ddeb6f5d27091ff291b16232e99076a64fb375b8"), + }, + wantConstraint: "ddeb6f5", + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + if tc.basicStatus.getConsolidatedConstraint() != tc.wantConstraint { + t.Errorf("unexpected consolidated constraint: \n\t(GOT) %v \n\t(WNT) %v", tc.basicStatus.getConsolidatedConstraint(), tc.wantConstraint) + } + }) + } +} + +func TestBasicStatusGetConsolidatedVersion(t *testing.T) { + testCases := []struct { + name string + basicStatus BasicStatus + wantVersion string + }{ + { + name: "empty BasicStatus", + basicStatus: BasicStatus{}, + wantVersion: "", + }, + { + name: "BasicStatus with Version and Revision", + basicStatus: BasicStatus{ + Version: gps.NewVersion("1.0.0"), + Revision: gps.Revision("revxyz"), + }, + wantVersion: "1.0.0", + }, + { + name: "BasicStatus with only Revision", + basicStatus: BasicStatus{ + Revision: gps.Revision("revxyz"), + }, + wantVersion: "revxyz", + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + if tc.basicStatus.getConsolidatedVersion() != tc.wantVersion { + t.Errorf("unexpected consolidated version: \n\t(GOT) %v \n\t(WNT) %v", tc.basicStatus.getConsolidatedVersion(), tc.wantVersion) + } + }) + } +} + +func TestBasicStatusGetConsolidatedLatest(t *testing.T) { + testCases := []struct { + name string + basicStatus BasicStatus + revSize uint8 + wantLatest string + }{ + { + name: "empty BasicStatus", + basicStatus: BasicStatus{}, + revSize: shortRev, + wantLatest: "", + }, + { + name: "nil latest", + basicStatus: BasicStatus{ + Latest: nil, + }, + revSize: shortRev, + wantLatest: "", + }, + { + name: "with error", + basicStatus: BasicStatus{ + hasError: true, + }, + revSize: shortRev, + wantLatest: "unknown", + }, + { + name: "short latest", + basicStatus: BasicStatus{ + Latest: gps.Revision("adummylonglongrevision"), + }, + revSize: shortRev, + wantLatest: "adummyl", + }, + { + name: "long latest", + basicStatus: BasicStatus{ + Latest: gps.Revision("adummylonglongrevision"), + }, + revSize: longRev, + wantLatest: "adummylonglongrevision", + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + gotRev := tc.basicStatus.getConsolidatedLatest(tc.revSize) + if gotRev != tc.wantLatest { + t.Errorf("unexpected consolidated latest: \n\t(GOT) %v \n\t(WNT) %v", gotRev, tc.wantLatest) + } + }) + } +} + +func TestCollectConstraints(t *testing.T) { + ver1, _ := gps.NewSemverConstraintIC("v1.0.0") + ver08, _ := gps.NewSemverConstraintIC("v0.8.0") + ver2, _ := gps.NewSemverConstraintIC("v2.0.0") + + cases := []struct { + name string + lock dep.Lock + wantConstraints constraintsCollection + wantErr bool + }{ + { + name: "without any constraints", + lock: dep.Lock{ + P: []gps.LockedProject{ + gps.NewLockedProject( + gps.ProjectIdentifier{ProjectRoot: gps.ProjectRoot("github.com/sdboyer/deptest")}, + gps.NewVersion("v1.0.0"), + []string{"."}, + ), + }, + }, + wantConstraints: constraintsCollection{}, + }, + { + name: "with multiple constraints", + lock: dep.Lock{ + P: []gps.LockedProject{ + gps.NewLockedProject( + gps.ProjectIdentifier{ProjectRoot: gps.ProjectRoot("github.com/sdboyer/deptest")}, + gps.NewVersion("v1.0.0"), + []string{"."}, + ), + gps.NewLockedProject( + gps.ProjectIdentifier{ProjectRoot: gps.ProjectRoot("github.com/darkowlzz/deptest-project-1")}, + gps.NewVersion("v0.1.0"), + []string{"."}, + ), + gps.NewLockedProject( + gps.ProjectIdentifier{ProjectRoot: gps.ProjectRoot("github.com/darkowlzz/deptest-project-2")}, + gps.NewBranch("master").Pair(gps.Revision("824a8d56a4c6b2f4718824a98cd6d70d3dbd4c3e")), + []string{"."}, + ), + }, + }, + wantConstraints: constraintsCollection{ + "github.com/sdboyer/deptestdos": []projectConstraint{ + {"github.com/darkowlzz/deptest-project-2", ver2}, + }, + "github.com/sdboyer/dep-test": []projectConstraint{ + {"github.com/darkowlzz/deptest-project-2", ver1}, + }, + "github.com/sdboyer/deptest": []projectConstraint{ + {"github.com/darkowlzz/deptest-project-1", ver1}, + {"github.com/darkowlzz/deptest-project-2", ver08}, + }, + }, + }, + { + name: "skip projects with invalid versions", + lock: dep.Lock{ + P: []gps.LockedProject{ + gps.NewLockedProject( + gps.ProjectIdentifier{ProjectRoot: gps.ProjectRoot("github.com/darkowlzz/deptest-project-1")}, + gps.NewVersion("v0.1.0"), + []string{"."}, + ), + gps.NewLockedProject( + gps.ProjectIdentifier{ProjectRoot: gps.ProjectRoot("github.com/darkowlzz/deptest-project-2")}, + gps.NewVersion("v1.0.0"), + []string{"."}, + ), + }, + }, + wantConstraints: constraintsCollection{ + "github.com/sdboyer/deptest": []projectConstraint{ + {"github.com/darkowlzz/deptest-project-1", ver1}, + }, + }, + wantErr: true, + }, + { + name: "collect only applicable constraints", + lock: dep.Lock{ + P: []gps.LockedProject{ + gps.NewLockedProject( + gps.ProjectIdentifier{ProjectRoot: gps.ProjectRoot("github.com/darkowlzz/dep-applicable-constraints")}, + gps.NewVersion("v1.0.0"), + []string{"."}, + ), + }, + }, + wantConstraints: constraintsCollection{ + "github.com/boltdb/bolt": []projectConstraint{ + {"github.com/darkowlzz/dep-applicable-constraints", gps.NewBranch("master")}, + }, + "github.com/sdboyer/deptest": []projectConstraint{ + {"github.com/darkowlzz/dep-applicable-constraints", ver08}, + }, + }, + }, + } + + h := test.NewHelper(t) + defer h.Cleanup() + + testdir := filepath.Join("src", "collect_constraints_test") + h.TempDir(testdir) + h.TempCopy(filepath.Join(testdir, "main.go"), filepath.Join("status", "collect_constraints", "main.go")) + testProjPath := h.Path(testdir) + + discardLogger := log.New(ioutil.Discard, "", 0) + + ctx := &dep.Ctx{ + GOPATH: testProjPath, + Out: discardLogger, + Err: discardLogger, + } + + sm, err := ctx.SourceManager() + h.Must(err) + defer sm.Release() + + // Create new project and set root. Setting root is required for PackageList + // to run properly. + p := new(dep.Project) + p.SetRoot(testProjPath) + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + p.Lock = &c.lock + gotConstraints, err := collectConstraints(ctx, p, sm) + if len(err) > 0 && !c.wantErr { + t.Fatalf("unexpected errors while collecting constraints: %v", err) + } else if len(err) == 0 && c.wantErr { + t.Fatalf("expected errors while collecting constraints, but got none") + } + + if !reflect.DeepEqual(gotConstraints, c.wantConstraints) { + t.Fatalf("unexpected collected constraints: \n\t(GOT): %v\n\t(WNT): %v", gotConstraints, c.wantConstraints) + } + }) + } +} + +func TestValidateFlags(t *testing.T) { + testCases := []struct { + name string + cmd statusCommand + wantErr error + }{ + { + name: "no flags", + cmd: statusCommand{}, + wantErr: nil, + }, + { + name: "-dot only", + cmd: statusCommand{dot: true}, + wantErr: nil, + }, + { + name: "-dot with template", + cmd: statusCommand{dot: true, template: "foo"}, + wantErr: errors.New("cannot pass template string with -dot"), + }, + { + name: "-dot with -json", + cmd: statusCommand{dot: true, json: true}, + wantErr: errors.New("cannot pass multiple output format flags"), + }, + { + name: "-dot with operating mode", + cmd: statusCommand{dot: true, old: true}, + wantErr: errors.New("-dot generates dependency graph; cannot pass other flags"), + }, + { + name: "single operating mode", + cmd: statusCommand{old: true}, + wantErr: nil, + }, + { + name: "multiple operating modes", + cmd: statusCommand{missing: true, old: true}, + wantErr: errors.Wrapf(errors.New("cannot pass multiple operating mode flags"), "[-old -missing]"), + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + err := tc.cmd.validateFlags() + + if err == nil { + if tc.wantErr != nil { + t.Errorf("unexpected error: \n\t(GOT): %v\n\t(WNT): %v", err, tc.wantErr) + } + } else if err.Error() != tc.wantErr.Error() { + t.Errorf("unexpected error: \n\t(GOT): %v\n\t(WNT): %v", err, tc.wantErr) + } + }) + } +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/cachedir/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/cachedir/Gopkg.lock new file mode 100644 index 00000000..c7f497e7 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/cachedir/Gopkg.lock @@ -0,0 +1,15 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "ff2948a2ac8f538c4ecd55962e919d1e13e74baf" + version = "v1.0.0" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "14b07b05e0f01051b03887ab2bf80b516bc5510ea92f75f76c894b1745d8850c" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/cachedir/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/cachedir/Gopkg.toml new file mode 100644 index 00000000..e242e021 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/cachedir/Gopkg.toml @@ -0,0 +1,4 @@ + +[[constraint]] + name = "github.com/sdboyer/deptest" + version = "1.0.0" diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/cachedir/main.go b/vendor/github.com/golang/dep/cmd/dep/testdata/cachedir/main.go new file mode 100644 index 00000000..1fe0d19d --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/cachedir/main.go @@ -0,0 +1,12 @@ +// Copyright 2016 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 main + +import ( + _ "github.com/sdboyer/deptest" +) + +func main() { +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/graphviz/case1.dot b/vendor/github.com/golang/dep/cmd/dep/testdata/graphviz/case1.dot new file mode 100644 index 00000000..3de92727 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/graphviz/case1.dot @@ -0,0 +1,9 @@ +digraph { + node [shape=box]; + 4106060478 [label="project"]; + 2851307223 [label="foo\nmaster"]; + 1991736602 [label="bar\ndev"]; + 4106060478 -> 2851307223; + 4106060478 -> 1991736602; + 2851307223 -> 1991736602; +} \ No newline at end of file diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/graphviz/case2.dot b/vendor/github.com/golang/dep/cmd/dep/testdata/graphviz/case2.dot new file mode 100644 index 00000000..df2d6a47 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/graphviz/case2.dot @@ -0,0 +1,4 @@ +digraph { + node [shape=box]; + 4106060478 [label="project"]; +} \ No newline at end of file diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/graphviz/empty.dot b/vendor/github.com/golang/dep/cmd/dep/testdata/graphviz/empty.dot new file mode 100644 index 00000000..3eabc972 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/graphviz/empty.dot @@ -0,0 +1,3 @@ +digraph { + node [shape=box]; +} \ No newline at end of file diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/README.md b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/README.md new file mode 100644 index 00000000..379caaa2 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/README.md @@ -0,0 +1,85 @@ +# golang/dep Integration Tests + +The `dep` integration tests use a consistent directory structure under `testdata` +to set up the initial project state, run `dep` commands, then check against an +expected final state to see if the test passes. + +The directory structure is as follows: + + testdata/ + harness_tests/ + category1/ + subcategory1/ + case1/ + testcase.json + stdout.txt + initial/ + file1.go + Gopkg.toml + ... + final/ + Gopkg.toml + Gopkg.lock + case2/ + ... + +The test code itself simply walks down the directory tree, looking for +`testcase.json` files. These files can be as many levels down the tree as +desired. The test name will consist of the directory path from `testdata` to +the test case directory itself. In the above example, the test name would be +`category1/subcategory1/case1`, and could be singled out with the `-run` option +of `go test` (i.e. +`go test github.com/golang/dep/cmd/dep -run Integration/category1/subcategory1/case1`). +New tests can be added simply by adding a new directory with the json file to +the `testdata` tree. There is no need for code modification - the new test +will be included automatically. + +The json file needs to be accompanied by `initial` and `final` directories. The +`initial` is copied verbatim into the test project before the `dep` commands are +run, and the `manifest` and `lock` files in `final`, if present, are used to +compare against the test project results after the commands. The `stdout.txt` file +is optional, and if present will be compared with command output. + +The `testcase.json` file has the following format: + + { + "commands": [ + ["init"], + ["ensure", "github.com/sdboyer/deptesttres"] + ], + "gopath-initial": { + "github.com/sdboyer/deptest": "v0.8.0", + "github.com/sdboyer/deptestdos": "a0196baa11ea047dd65037287451d36b861b00ea" + }, + "vendor-initial": { + "github.com/sdboyer/deptesttres": "v2.1.0", + "github.com/sdboyer/deptestquatro": "cf596baa11ea047ddf8797287451d36b861bab45" + }, + "vendor-final": [ + "github.com/sdboyer/deptest", + "github.com/sdboyer/deptestdos", + "github.com/sdboyer/deptesttres", + "github.com/sdboyer/deptestquatro" + ], + "error-expected": "something went wrong" + } + +All of the categories are optional - if the `imports` list for a test is empty, +for example, it can be completely left out. + +The test procedure is as follows: + +1. Create a unique temporary directory (TMPDIR) as the test run's `GOPATH` +2. Create `$TMPDIR/src/github.com/golang/notexist` as the current project +3. Copy the contents of `initial` input directory to the project +4. Fetch the repos and versions in `gopath-initial` into `$TMPDIR/src` directory +5. Fetch the repos and versions in `vendor-initial` to the project's `vendor` directory +6. Run `commands` on the project, in declaration order +7. Ensure that, if any errors are raised, it is only by the final command and their string output matches `error-expected` +8. Ensure that, if a stdout.txt file is present, the command's output matches (excluding trailing whitespace). +9. Check the resulting files against those in the `final` input directory +10. Check the `vendor` directory for the projects listed under `vendor-final` +11. Check that there were no changes to `src` listings +12. Clean up + +Note that for the remote fetches, only git repos are currently supported. diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/all-new-double-spec/final/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/all-new-double-spec/final/Gopkg.lock new file mode 100644 index 00000000..eddb2559 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/all-new-double-spec/final/Gopkg.lock @@ -0,0 +1,21 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "3f4c3bea144e112a69bbe5d8d01c1b09a544253f" + version = "v0.8.1" + +[[projects]] + branch = "master" + name = "github.com/sdboyer/deptesttres" + packages = ["."] + revision = "54aaeb0023e1f3dcf5f98f31dd8c565457945a12" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "645b5b52e1bfb9e3db1cefde758485e009edfe5bad611b490582d94467f9c1b0" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/all-new-double-spec/final/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/all-new-double-spec/final/Gopkg.toml new file mode 100644 index 00000000..47af7688 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/all-new-double-spec/final/Gopkg.toml @@ -0,0 +1,12 @@ + +[[constraint]] + branch = "master" + name = "github.com/sdboyer/deptesttres" + +[prune] + go-tests = true + unused-packages = true + +[[constraint]] + name = "github.com/sdboyer/deptest" + version = "0.8.1" diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/all-new-double-spec/initial/main.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/all-new-double-spec/initial/main.go new file mode 100644 index 00000000..8049e4ec --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/all-new-double-spec/initial/main.go @@ -0,0 +1,13 @@ +// Copyright 2017 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 main + +import ( + "github.com/sdboyer/deptesttres" +) + +func main() { + type a deptesttres.Bar +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/all-new-double-spec/testcase.json b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/all-new-double-spec/testcase.json new file mode 100644 index 00000000..182b683c --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/all-new-double-spec/testcase.json @@ -0,0 +1,10 @@ +{ + "commands": [ + ["init", "-no-examples"], + ["ensure", "-add", "github.com/sdboyer/deptest", "github.com/sdboyer/deptest@v0.8.1"] + ], + "vendor-final": [ + "github.com/sdboyer/deptest", + "github.com/sdboyer/deptesttres" + ] +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/all-new-double/final/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/all-new-double/final/Gopkg.lock new file mode 100644 index 00000000..8481da44 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/all-new-double/final/Gopkg.lock @@ -0,0 +1,24 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "ff2948a2ac8f538c4ecd55962e919d1e13e74baf" + version = "v1.0.0" + +[[projects]] + branch = "master" + name = "github.com/sdboyer/deptesttres" + packages = [ + ".", + "subp" + ] + revision = "54aaeb0023e1f3dcf5f98f31dd8c565457945a12" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "432bc141db9511df4e1b5754c6c4d8cf4dd8b4f8d5a13fd7d189c17c14e000b7" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/all-new-double/final/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/all-new-double/final/Gopkg.toml new file mode 100644 index 00000000..252f9478 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/all-new-double/final/Gopkg.toml @@ -0,0 +1,12 @@ + +[[constraint]] + name = "github.com/sdboyer/deptest" + version = "1.0.0" + +[prune] + go-tests = true + unused-packages = true + +[[constraint]] + branch = "master" + name = "github.com/sdboyer/deptesttres" diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/all-new-double/initial/main.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/all-new-double/initial/main.go new file mode 100644 index 00000000..84f99b68 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/all-new-double/initial/main.go @@ -0,0 +1,13 @@ +// Copyright 2017 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 main + +import ( + "github.com/sdboyer/deptest" +) + +func main() { + type a deptest.Bar +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/all-new-double/testcase.json b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/all-new-double/testcase.json new file mode 100644 index 00000000..2e5161d0 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/all-new-double/testcase.json @@ -0,0 +1,10 @@ +{ + "commands": [ + ["init", "-no-examples"], + ["ensure", "-add", "github.com/sdboyer/deptesttres", "github.com/sdboyer/deptesttres/subp"] + ], + "vendor-final": [ + "github.com/sdboyer/deptest", + "github.com/sdboyer/deptesttres" + ] +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/all-new-spec/final/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/all-new-spec/final/Gopkg.lock new file mode 100644 index 00000000..eddb2559 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/all-new-spec/final/Gopkg.lock @@ -0,0 +1,21 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "3f4c3bea144e112a69bbe5d8d01c1b09a544253f" + version = "v0.8.1" + +[[projects]] + branch = "master" + name = "github.com/sdboyer/deptesttres" + packages = ["."] + revision = "54aaeb0023e1f3dcf5f98f31dd8c565457945a12" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "645b5b52e1bfb9e3db1cefde758485e009edfe5bad611b490582d94467f9c1b0" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/all-new-spec/final/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/all-new-spec/final/Gopkg.toml new file mode 100644 index 00000000..47af7688 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/all-new-spec/final/Gopkg.toml @@ -0,0 +1,12 @@ + +[[constraint]] + branch = "master" + name = "github.com/sdboyer/deptesttres" + +[prune] + go-tests = true + unused-packages = true + +[[constraint]] + name = "github.com/sdboyer/deptest" + version = "0.8.1" diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/all-new-spec/initial/main.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/all-new-spec/initial/main.go new file mode 100644 index 00000000..8049e4ec --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/all-new-spec/initial/main.go @@ -0,0 +1,13 @@ +// Copyright 2017 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 main + +import ( + "github.com/sdboyer/deptesttres" +) + +func main() { + type a deptesttres.Bar +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/all-new-spec/testcase.json b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/all-new-spec/testcase.json new file mode 100644 index 00000000..9f6fa3f3 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/all-new-spec/testcase.json @@ -0,0 +1,10 @@ +{ + "commands": [ + ["init", "-no-examples"], + ["ensure", "-add", "github.com/sdboyer/deptest@v0.8.1"] + ], + "vendor-final": [ + "github.com/sdboyer/deptest", + "github.com/sdboyer/deptesttres" + ] +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/all-new/final/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/all-new/final/Gopkg.lock new file mode 100644 index 00000000..5531a3e1 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/all-new/final/Gopkg.lock @@ -0,0 +1,21 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "ff2948a2ac8f538c4ecd55962e919d1e13e74baf" + version = "v1.0.0" + +[[projects]] + branch = "master" + name = "github.com/sdboyer/deptesttres" + packages = ["."] + revision = "54aaeb0023e1f3dcf5f98f31dd8c565457945a12" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "8f0b74fd1169808bd0e31dd7ad6c601c7b8f7ef25eec9e8a45e72b8a384ebb5c" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/all-new/final/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/all-new/final/Gopkg.toml new file mode 100644 index 00000000..b75fe963 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/all-new/final/Gopkg.toml @@ -0,0 +1,12 @@ + +[[constraint]] + branch = "master" + name = "github.com/sdboyer/deptesttres" + +[prune] + go-tests = true + unused-packages = true + +[[constraint]] + name = "github.com/sdboyer/deptest" + version = "1.0.0" diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/all-new/initial/main.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/all-new/initial/main.go new file mode 100644 index 00000000..8049e4ec --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/all-new/initial/main.go @@ -0,0 +1,13 @@ +// Copyright 2017 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 main + +import ( + "github.com/sdboyer/deptesttres" +) + +func main() { + type a deptesttres.Bar +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/all-new/testcase.json b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/all-new/testcase.json new file mode 100644 index 00000000..3a8d221f --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/all-new/testcase.json @@ -0,0 +1,10 @@ +{ + "commands": [ + ["init", "-no-examples"], + ["ensure", "-add", "github.com/sdboyer/deptest"] + ], + "vendor-final": [ + "github.com/sdboyer/deptest", + "github.com/sdboyer/deptesttres" + ] +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/desync/final/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/desync/final/Gopkg.lock new file mode 100644 index 00000000..a9d0374e --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/desync/final/Gopkg.lock @@ -0,0 +1,27 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "ff2948a2ac8f538c4ecd55962e919d1e13e74baf" + version = "v1.0.0" + +[[projects]] + name = "github.com/sdboyer/deptestdos" + packages = ["."] + revision = "5c607206be5decd28e6263ffffdcee067266015e" + version = "v2.0.0" + +[[projects]] + branch = "master" + name = "github.com/sdboyer/deptesttres" + packages = ["."] + revision = "54aaeb0023e1f3dcf5f98f31dd8c565457945a12" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "86240895e0ee5788e7e8bb56e0d77afd58009a491b69f6835e546db9e5dacfcd" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/desync/final/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/desync/final/Gopkg.toml new file mode 100644 index 00000000..57787fb4 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/desync/final/Gopkg.toml @@ -0,0 +1,6 @@ +[[constraint]] + name = "github.com/sdboyer/deptest" + version = "~0.8.0" +[[constraint]] + branch = "master" + name = "github.com/sdboyer/deptesttres" diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/desync/final/main.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/desync/final/main.go new file mode 100644 index 00000000..2eae5b51 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/desync/final/main.go @@ -0,0 +1,18 @@ +// Copyright 2016 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 main + +import ( + "github.com/sdboyer/deptest" + "github.com/sdboyer/deptestdos" +) + +func main() { + err := nil + if err != nil { + deptest.Map["yo yo!"] + } + deptestdos.diMeLo("whatev") +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/desync/initial/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/desync/initial/Gopkg.lock new file mode 100644 index 00000000..2d6f4c02 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/desync/initial/Gopkg.lock @@ -0,0 +1,15 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + branch = "master" + name = "github.com/sdboyer/deptesttres" + packages = ["."] + revision = "54aaeb0023e1f3dcf5f98f31dd8c565457945a12" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "9a7bd6944c26792ab2e97fed1227cc402f0cc00465016836efbf04239596dd9f" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/desync/initial/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/desync/initial/Gopkg.toml new file mode 100644 index 00000000..532da96a --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/desync/initial/Gopkg.toml @@ -0,0 +1,3 @@ +[[constraint]] + name = "github.com/sdboyer/deptest" + version = "~0.8.0" \ No newline at end of file diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/desync/initial/main.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/desync/initial/main.go new file mode 100644 index 00000000..7ad40aca --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/desync/initial/main.go @@ -0,0 +1,21 @@ +// Copyright 2016 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 main + +import ( + "github.com/sdboyer/deptest" + "github.com/sdboyer/deptestdos" + "github.com/sdboyer/deptesttres" +) + +func main() { + err := nil + if err != nil { + deptest.Map["yo yo!"] + } + deptestdos.diMeLo("whatev") + + type a deptesttres.Bar +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/desync/stdout.txt b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/desync/stdout.txt new file mode 100644 index 00000000..c0d72198 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/desync/stdout.txt @@ -0,0 +1,2 @@ +Warning: Gopkg.lock is out of sync with Gopkg.toml or the project's imports. +Fetching sources... diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/desync/testcase.json b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/desync/testcase.json new file mode 100644 index 00000000..eb95e6f1 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/desync/testcase.json @@ -0,0 +1,10 @@ +{ + "commands": [ + ["ensure", "-add", "github.com/sdboyer/deptesttres@master"] + ], + "vendor-final": [ + "github.com/sdboyer/deptest", + "github.com/sdboyer/deptestdos", + "github.com/sdboyer/deptesttres" + ] +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/double-diff-spec/final/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/double-diff-spec/final/Gopkg.lock new file mode 100644 index 00000000..66ef021c --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/double-diff-spec/final/Gopkg.lock @@ -0,0 +1,15 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + branch = "master" + name = "github.com/sdboyer/deptesttres" + packages = ["."] + revision = "54aaeb0023e1f3dcf5f98f31dd8c565457945a12" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "342afd8c8a616d084eb7b67bf3a891710eca3ce5abc3cf60af0dae4ccfdcd001" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/double-diff-spec/final/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/double-diff-spec/final/Gopkg.toml new file mode 100644 index 00000000..d24b0696 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/double-diff-spec/final/Gopkg.toml @@ -0,0 +1,8 @@ + +[[constraint]] + branch = "master" + name = "github.com/sdboyer/deptesttres" + +[prune] + go-tests = true + unused-packages = true diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/double-diff-spec/initial/main.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/double-diff-spec/initial/main.go new file mode 100644 index 00000000..8049e4ec --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/double-diff-spec/initial/main.go @@ -0,0 +1,13 @@ +// Copyright 2017 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 main + +import ( + "github.com/sdboyer/deptesttres" +) + +func main() { + type a deptesttres.Bar +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/double-diff-spec/testcase.json b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/double-diff-spec/testcase.json new file mode 100644 index 00000000..52cb46b1 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/double-diff-spec/testcase.json @@ -0,0 +1,10 @@ +{ + "commands": [ + ["init", "-no-examples"], + ["ensure", "-add", "github.com/sdboyer/deptest@0.8.1", "github.com/sdboyer/deptest@1.0.0"] + ], + "vendor-final": [ + "github.com/sdboyer/deptesttres" + ], + "error-expected": "can only specify rules once per project being added; rules were given at least twice for github.com/sdboyer/deptest" +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/exists-manifest/final/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/exists-manifest/final/Gopkg.lock new file mode 100644 index 00000000..66ef021c --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/exists-manifest/final/Gopkg.lock @@ -0,0 +1,15 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + branch = "master" + name = "github.com/sdboyer/deptesttres" + packages = ["."] + revision = "54aaeb0023e1f3dcf5f98f31dd8c565457945a12" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "342afd8c8a616d084eb7b67bf3a891710eca3ce5abc3cf60af0dae4ccfdcd001" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/exists-manifest/final/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/exists-manifest/final/Gopkg.toml new file mode 100644 index 00000000..598accd8 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/exists-manifest/final/Gopkg.toml @@ -0,0 +1,7 @@ +[[constraint]] + name = "github.com/sdboyer/deptesttres" + branch = "master" + +[[constraint]] + name = "github.com/sdboyer/deptest" + version = "1.0.0" diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/exists-manifest/initial/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/exists-manifest/initial/Gopkg.lock new file mode 100644 index 00000000..66ef021c --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/exists-manifest/initial/Gopkg.lock @@ -0,0 +1,15 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + branch = "master" + name = "github.com/sdboyer/deptesttres" + packages = ["."] + revision = "54aaeb0023e1f3dcf5f98f31dd8c565457945a12" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "342afd8c8a616d084eb7b67bf3a891710eca3ce5abc3cf60af0dae4ccfdcd001" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/exists-manifest/initial/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/exists-manifest/initial/Gopkg.toml new file mode 100644 index 00000000..598accd8 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/exists-manifest/initial/Gopkg.toml @@ -0,0 +1,7 @@ +[[constraint]] + name = "github.com/sdboyer/deptesttres" + branch = "master" + +[[constraint]] + name = "github.com/sdboyer/deptest" + version = "1.0.0" diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/exists-manifest/initial/main.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/exists-manifest/initial/main.go new file mode 100644 index 00000000..8049e4ec --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/exists-manifest/initial/main.go @@ -0,0 +1,13 @@ +// Copyright 2017 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 main + +import ( + "github.com/sdboyer/deptesttres" +) + +func main() { + type a deptesttres.Bar +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/exists-manifest/testcase.json b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/exists-manifest/testcase.json new file mode 100644 index 00000000..a0d78d31 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/exists-manifest/testcase.json @@ -0,0 +1,6 @@ +{ + "commands": [ + ["ensure", "-add", "github.com/sdboyer/deptest@1.0.0"] + ], + "error-expected": "Gopkg.toml already contains rules for github.com/sdboyer/deptest, cannot specify a version constraint" +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/exists/final/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/exists/final/Gopkg.lock new file mode 100644 index 00000000..c7f497e7 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/exists/final/Gopkg.lock @@ -0,0 +1,15 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "ff2948a2ac8f538c4ecd55962e919d1e13e74baf" + version = "v1.0.0" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "14b07b05e0f01051b03887ab2bf80b516bc5510ea92f75f76c894b1745d8850c" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/exists/final/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/exists/final/Gopkg.toml new file mode 100644 index 00000000..51ff69b3 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/exists/final/Gopkg.toml @@ -0,0 +1,3 @@ +[[constraint]] + name = "github.com/sdboyer/deptest" + version = "1.0.0" diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/exists/initial/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/exists/initial/Gopkg.lock new file mode 100644 index 00000000..c7f497e7 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/exists/initial/Gopkg.lock @@ -0,0 +1,15 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "ff2948a2ac8f538c4ecd55962e919d1e13e74baf" + version = "v1.0.0" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "14b07b05e0f01051b03887ab2bf80b516bc5510ea92f75f76c894b1745d8850c" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/exists/initial/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/exists/initial/Gopkg.toml new file mode 100644 index 00000000..51ff69b3 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/exists/initial/Gopkg.toml @@ -0,0 +1,3 @@ +[[constraint]] + name = "github.com/sdboyer/deptest" + version = "1.0.0" diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/exists/initial/main.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/exists/initial/main.go new file mode 100644 index 00000000..c5b8da51 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/exists/initial/main.go @@ -0,0 +1,13 @@ +// Copyright 2016 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 main + +import ( + "github.com/sdboyer/deptest" +) + +func main() { + _ := deptest.Map["yo yo!"] +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/exists/testcase.json b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/exists/testcase.json new file mode 100644 index 00000000..e4ec92f9 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/exists/testcase.json @@ -0,0 +1,6 @@ +{ + "commands": [ + ["ensure", "-add", "github.com/sdboyer/deptest"] + ], + "error-expected": "nothing to -add, github.com/sdboyer/deptest is already in Gopkg.toml and the project's direct imports or required list" +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/noarg/final/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/noarg/final/Gopkg.lock new file mode 100644 index 00000000..41dd2d41 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/noarg/final/Gopkg.lock @@ -0,0 +1,21 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/sdboyer/deptest" + version = "v0.8.0" + revision = "ff2948a2ac8f538c4ecd55962e919d1e13e74baf" + packages = ["."] + +[[projects]] + name = "github.com/sdboyer/deptestdos" + version = "v2.0.0" + revision = "5c607206be5decd28e6263ffffdcee067266015e" + packages = ["."] + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "9b381263a360eafafe3ef7f9be626672668d17250a3c9a8debd169d1b5e2eebb" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/noarg/final/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/noarg/final/Gopkg.toml new file mode 100644 index 00000000..532da96a --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/noarg/final/Gopkg.toml @@ -0,0 +1,3 @@ +[[constraint]] + name = "github.com/sdboyer/deptest" + version = "~0.8.0" \ No newline at end of file diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/noarg/final/main.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/noarg/final/main.go new file mode 100644 index 00000000..2eae5b51 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/noarg/final/main.go @@ -0,0 +1,18 @@ +// Copyright 2016 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 main + +import ( + "github.com/sdboyer/deptest" + "github.com/sdboyer/deptestdos" +) + +func main() { + err := nil + if err != nil { + deptest.Map["yo yo!"] + } + deptestdos.diMeLo("whatev") +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/noarg/initial/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/noarg/initial/Gopkg.lock new file mode 100644 index 00000000..41dd2d41 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/noarg/initial/Gopkg.lock @@ -0,0 +1,21 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/sdboyer/deptest" + version = "v0.8.0" + revision = "ff2948a2ac8f538c4ecd55962e919d1e13e74baf" + packages = ["."] + +[[projects]] + name = "github.com/sdboyer/deptestdos" + version = "v2.0.0" + revision = "5c607206be5decd28e6263ffffdcee067266015e" + packages = ["."] + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "9b381263a360eafafe3ef7f9be626672668d17250a3c9a8debd169d1b5e2eebb" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/noarg/initial/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/noarg/initial/Gopkg.toml new file mode 100644 index 00000000..532da96a --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/noarg/initial/Gopkg.toml @@ -0,0 +1,3 @@ +[[constraint]] + name = "github.com/sdboyer/deptest" + version = "~0.8.0" \ No newline at end of file diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/noarg/initial/main.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/noarg/initial/main.go new file mode 100644 index 00000000..2eae5b51 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/noarg/initial/main.go @@ -0,0 +1,18 @@ +// Copyright 2016 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 main + +import ( + "github.com/sdboyer/deptest" + "github.com/sdboyer/deptestdos" +) + +func main() { + err := nil + if err != nil { + deptest.Map["yo yo!"] + } + deptestdos.diMeLo("whatev") +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/noarg/testcase.json b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/noarg/testcase.json new file mode 100644 index 00000000..b8b36480 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/noarg/testcase.json @@ -0,0 +1,6 @@ +{ + "commands": [ + ["ensure", "-add"] + ], + "error-expected": "must specify at least one project or package to -add" +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/self-add/case1/final/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/self-add/case1/final/Gopkg.lock new file mode 100644 index 00000000..c7f497e7 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/self-add/case1/final/Gopkg.lock @@ -0,0 +1,15 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "ff2948a2ac8f538c4ecd55962e919d1e13e74baf" + version = "v1.0.0" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "14b07b05e0f01051b03887ab2bf80b516bc5510ea92f75f76c894b1745d8850c" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/self-add/case1/final/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/self-add/case1/final/Gopkg.toml new file mode 100644 index 00000000..51ff69b3 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/self-add/case1/final/Gopkg.toml @@ -0,0 +1,3 @@ +[[constraint]] + name = "github.com/sdboyer/deptest" + version = "1.0.0" diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/self-add/case1/initial/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/self-add/case1/initial/Gopkg.lock new file mode 100644 index 00000000..c7f497e7 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/self-add/case1/initial/Gopkg.lock @@ -0,0 +1,15 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "ff2948a2ac8f538c4ecd55962e919d1e13e74baf" + version = "v1.0.0" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "14b07b05e0f01051b03887ab2bf80b516bc5510ea92f75f76c894b1745d8850c" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/self-add/case1/initial/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/self-add/case1/initial/Gopkg.toml new file mode 100644 index 00000000..51ff69b3 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/self-add/case1/initial/Gopkg.toml @@ -0,0 +1,3 @@ +[[constraint]] + name = "github.com/sdboyer/deptest" + version = "1.0.0" diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/self-add/case1/initial/main.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/self-add/case1/initial/main.go new file mode 100644 index 00000000..c5b8da51 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/self-add/case1/initial/main.go @@ -0,0 +1,13 @@ +// Copyright 2016 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 main + +import ( + "github.com/sdboyer/deptest" +) + +func main() { + _ := deptest.Map["yo yo!"] +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/self-add/case1/testcase.json b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/self-add/case1/testcase.json new file mode 100644 index 00000000..86727bb2 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/self-add/case1/testcase.json @@ -0,0 +1,6 @@ +{ + "commands": [ + ["ensure", "-add", "github.com/golang/notexist"] + ], + "error-expected": "cannot add current project to itself" +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/self-add/case2/final/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/self-add/case2/final/Gopkg.lock new file mode 100644 index 00000000..bef2d009 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/self-add/case2/final/Gopkg.lock @@ -0,0 +1,9 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "ab4fef131ee828e96ba67d31a7d690bd5f2f42040c6766b1b12fe856f87e0ff7" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/self-add/case2/final/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/self-add/case2/final/Gopkg.toml new file mode 100644 index 00000000..db111447 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/self-add/case2/final/Gopkg.toml @@ -0,0 +1,4 @@ + +[prune] + go-tests = true + unused-packages = true diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/self-add/case2/initial/main.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/self-add/case2/initial/main.go new file mode 100644 index 00000000..7a00113b --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/self-add/case2/initial/main.go @@ -0,0 +1,7 @@ +// Copyright 2017 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 main + +func main() {} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/self-add/case2/testcase.json b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/self-add/case2/testcase.json new file mode 100644 index 00000000..490aab5e --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/errs/self-add/case2/testcase.json @@ -0,0 +1,7 @@ +{ + "commands": [ + ["init", "-no-examples"], + ["ensure", "-add", "github.com/golang/notexist"] + ], + "error-expected": "cannot add current project to itself" +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/exists-imports/final/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/exists-imports/final/Gopkg.lock new file mode 100644 index 00000000..66ef021c --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/exists-imports/final/Gopkg.lock @@ -0,0 +1,15 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + branch = "master" + name = "github.com/sdboyer/deptesttres" + packages = ["."] + revision = "54aaeb0023e1f3dcf5f98f31dd8c565457945a12" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "342afd8c8a616d084eb7b67bf3a891710eca3ce5abc3cf60af0dae4ccfdcd001" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/exists-imports/final/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/exists-imports/final/Gopkg.toml new file mode 100644 index 00000000..bbc8cc16 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/exists-imports/final/Gopkg.toml @@ -0,0 +1,4 @@ + +[[constraint]] + branch = "master" + name = "github.com/sdboyer/deptesttres" diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/exists-imports/initial/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/exists-imports/initial/Gopkg.toml new file mode 100644 index 00000000..e69de29b diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/exists-imports/initial/main.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/exists-imports/initial/main.go new file mode 100644 index 00000000..8049e4ec --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/exists-imports/initial/main.go @@ -0,0 +1,13 @@ +// Copyright 2017 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 main + +import ( + "github.com/sdboyer/deptesttres" +) + +func main() { + type a deptesttres.Bar +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/exists-imports/testcase.json b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/exists-imports/testcase.json new file mode 100644 index 00000000..69755349 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/exists-imports/testcase.json @@ -0,0 +1,8 @@ +{ + "commands": [ + ["ensure", "-add", "github.com/sdboyer/deptesttres@master"] + ], + "vendor-final": [ + "github.com/sdboyer/deptesttres" + ] +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/exists-manifest-constraint/final/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/exists-manifest-constraint/final/Gopkg.lock new file mode 100644 index 00000000..e235bce7 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/exists-manifest-constraint/final/Gopkg.lock @@ -0,0 +1,21 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "ff2948a2ac8f538c4ecd55962e919d1e13e74baf" + version = "v1.0.0" + +[[projects]] + branch = "master" + name = "github.com/sdboyer/deptesttres" + packages = ["."] + revision = "54aaeb0023e1f3dcf5f98f31dd8c565457945a12" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "d1fe1d4f4dd98b75908b524bd73d43a4b9e3ce0b9522ea6ce9d6c9ea15190c1d" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/exists-manifest-constraint/final/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/exists-manifest-constraint/final/Gopkg.toml new file mode 100644 index 00000000..598accd8 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/exists-manifest-constraint/final/Gopkg.toml @@ -0,0 +1,7 @@ +[[constraint]] + name = "github.com/sdboyer/deptesttres" + branch = "master" + +[[constraint]] + name = "github.com/sdboyer/deptest" + version = "1.0.0" diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/exists-manifest-constraint/initial/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/exists-manifest-constraint/initial/Gopkg.lock new file mode 100644 index 00000000..66ef021c --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/exists-manifest-constraint/initial/Gopkg.lock @@ -0,0 +1,15 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + branch = "master" + name = "github.com/sdboyer/deptesttres" + packages = ["."] + revision = "54aaeb0023e1f3dcf5f98f31dd8c565457945a12" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "342afd8c8a616d084eb7b67bf3a891710eca3ce5abc3cf60af0dae4ccfdcd001" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/exists-manifest-constraint/initial/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/exists-manifest-constraint/initial/Gopkg.toml new file mode 100644 index 00000000..598accd8 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/exists-manifest-constraint/initial/Gopkg.toml @@ -0,0 +1,7 @@ +[[constraint]] + name = "github.com/sdboyer/deptesttres" + branch = "master" + +[[constraint]] + name = "github.com/sdboyer/deptest" + version = "1.0.0" diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/exists-manifest-constraint/initial/main.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/exists-manifest-constraint/initial/main.go new file mode 100644 index 00000000..8049e4ec --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/exists-manifest-constraint/initial/main.go @@ -0,0 +1,13 @@ +// Copyright 2017 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 main + +import ( + "github.com/sdboyer/deptesttres" +) + +func main() { + type a deptesttres.Bar +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/exists-manifest-constraint/testcase.json b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/exists-manifest-constraint/testcase.json new file mode 100644 index 00000000..6a19d7c2 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/add/exists-manifest-constraint/testcase.json @@ -0,0 +1,9 @@ +{ + "commands": [ + ["ensure", "-add", "github.com/sdboyer/deptest"] + ], + "vendor-final": [ + "github.com/sdboyer/deptest", + "github.com/sdboyer/deptesttres" + ] +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/errs/lockless-vendoronly/final/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/errs/lockless-vendoronly/final/Gopkg.toml new file mode 100644 index 00000000..e242e021 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/errs/lockless-vendoronly/final/Gopkg.toml @@ -0,0 +1,4 @@ + +[[constraint]] + name = "github.com/sdboyer/deptest" + version = "1.0.0" diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/errs/lockless-vendoronly/final/main.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/errs/lockless-vendoronly/final/main.go new file mode 100644 index 00000000..1fe0d19d --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/errs/lockless-vendoronly/final/main.go @@ -0,0 +1,12 @@ +// Copyright 2016 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 main + +import ( + _ "github.com/sdboyer/deptest" +) + +func main() { +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/errs/lockless-vendoronly/initial/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/errs/lockless-vendoronly/initial/Gopkg.toml new file mode 100644 index 00000000..e242e021 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/errs/lockless-vendoronly/initial/Gopkg.toml @@ -0,0 +1,4 @@ + +[[constraint]] + name = "github.com/sdboyer/deptest" + version = "1.0.0" diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/errs/lockless-vendoronly/initial/main.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/errs/lockless-vendoronly/initial/main.go new file mode 100644 index 00000000..1fe0d19d --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/errs/lockless-vendoronly/initial/main.go @@ -0,0 +1,12 @@ +// Copyright 2016 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 main + +import ( + _ "github.com/sdboyer/deptest" +) + +func main() { +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/errs/lockless-vendoronly/testcase.json b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/errs/lockless-vendoronly/testcase.json new file mode 100644 index 00000000..6dc9735c --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/errs/lockless-vendoronly/testcase.json @@ -0,0 +1,6 @@ +{ + "commands": [ + ["ensure", "-vendor-only"] + ], + "error-expected": "no Gopkg.lock exists from which to populate vendor/" +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/errs/specargs/final/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/errs/specargs/final/Gopkg.lock new file mode 100644 index 00000000..c7f497e7 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/errs/specargs/final/Gopkg.lock @@ -0,0 +1,15 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "ff2948a2ac8f538c4ecd55962e919d1e13e74baf" + version = "v1.0.0" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "14b07b05e0f01051b03887ab2bf80b516bc5510ea92f75f76c894b1745d8850c" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/errs/specargs/final/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/errs/specargs/final/Gopkg.toml new file mode 100644 index 00000000..e242e021 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/errs/specargs/final/Gopkg.toml @@ -0,0 +1,4 @@ + +[[constraint]] + name = "github.com/sdboyer/deptest" + version = "1.0.0" diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/errs/specargs/initial/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/errs/specargs/initial/Gopkg.lock new file mode 100644 index 00000000..c7f497e7 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/errs/specargs/initial/Gopkg.lock @@ -0,0 +1,15 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "ff2948a2ac8f538c4ecd55962e919d1e13e74baf" + version = "v1.0.0" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "14b07b05e0f01051b03887ab2bf80b516bc5510ea92f75f76c894b1745d8850c" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/errs/specargs/initial/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/errs/specargs/initial/Gopkg.toml new file mode 100644 index 00000000..e242e021 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/errs/specargs/initial/Gopkg.toml @@ -0,0 +1,4 @@ + +[[constraint]] + name = "github.com/sdboyer/deptest" + version = "1.0.0" diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/errs/specargs/initial/main.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/errs/specargs/initial/main.go new file mode 100644 index 00000000..1fe0d19d --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/errs/specargs/initial/main.go @@ -0,0 +1,12 @@ +// Copyright 2016 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 main + +import ( + _ "github.com/sdboyer/deptest" +) + +func main() { +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/errs/specargs/testcase.json b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/errs/specargs/testcase.json new file mode 100644 index 00000000..f194308f --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/errs/specargs/testcase.json @@ -0,0 +1,6 @@ +{ + "commands": [ + ["ensure", "foobar.com/baz"] + ], + "error-expected": "dep ensure only takes spec arguments with -add or -update" +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-dry/final/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-dry/final/Gopkg.lock new file mode 100644 index 00000000..c7f497e7 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-dry/final/Gopkg.lock @@ -0,0 +1,15 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "ff2948a2ac8f538c4ecd55962e919d1e13e74baf" + version = "v1.0.0" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "14b07b05e0f01051b03887ab2bf80b516bc5510ea92f75f76c894b1745d8850c" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-dry/final/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-dry/final/Gopkg.toml new file mode 100644 index 00000000..e242e021 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-dry/final/Gopkg.toml @@ -0,0 +1,4 @@ + +[[constraint]] + name = "github.com/sdboyer/deptest" + version = "1.0.0" diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-dry/initial/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-dry/initial/Gopkg.lock new file mode 100644 index 00000000..c7f497e7 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-dry/initial/Gopkg.lock @@ -0,0 +1,15 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "ff2948a2ac8f538c4ecd55962e919d1e13e74baf" + version = "v1.0.0" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "14b07b05e0f01051b03887ab2bf80b516bc5510ea92f75f76c894b1745d8850c" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-dry/initial/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-dry/initial/Gopkg.toml new file mode 100644 index 00000000..e242e021 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-dry/initial/Gopkg.toml @@ -0,0 +1,4 @@ + +[[constraint]] + name = "github.com/sdboyer/deptest" + version = "1.0.0" diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-dry/initial/main.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-dry/initial/main.go new file mode 100644 index 00000000..1fe0d19d --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-dry/initial/main.go @@ -0,0 +1,12 @@ +// Copyright 2016 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 main + +import ( + _ "github.com/sdboyer/deptest" +) + +func main() { +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-dry/testcase.json b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-dry/testcase.json new file mode 100644 index 00000000..21daf3e9 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-dry/testcase.json @@ -0,0 +1,5 @@ +{ + "commands": [ + ["ensure", "-dry-run"] + ] +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-novendor-dry/final/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-novendor-dry/final/Gopkg.lock new file mode 100644 index 00000000..c7f497e7 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-novendor-dry/final/Gopkg.lock @@ -0,0 +1,15 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "ff2948a2ac8f538c4ecd55962e919d1e13e74baf" + version = "v1.0.0" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "14b07b05e0f01051b03887ab2bf80b516bc5510ea92f75f76c894b1745d8850c" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-novendor-dry/final/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-novendor-dry/final/Gopkg.toml new file mode 100644 index 00000000..e242e021 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-novendor-dry/final/Gopkg.toml @@ -0,0 +1,4 @@ + +[[constraint]] + name = "github.com/sdboyer/deptest" + version = "1.0.0" diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-novendor-dry/initial/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-novendor-dry/initial/Gopkg.lock new file mode 100644 index 00000000..c7f497e7 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-novendor-dry/initial/Gopkg.lock @@ -0,0 +1,15 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "ff2948a2ac8f538c4ecd55962e919d1e13e74baf" + version = "v1.0.0" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "14b07b05e0f01051b03887ab2bf80b516bc5510ea92f75f76c894b1745d8850c" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-novendor-dry/initial/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-novendor-dry/initial/Gopkg.toml new file mode 100644 index 00000000..e242e021 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-novendor-dry/initial/Gopkg.toml @@ -0,0 +1,4 @@ + +[[constraint]] + name = "github.com/sdboyer/deptest" + version = "1.0.0" diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-novendor-dry/initial/main.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-novendor-dry/initial/main.go new file mode 100644 index 00000000..1fe0d19d --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-novendor-dry/initial/main.go @@ -0,0 +1,12 @@ +// Copyright 2016 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 main + +import ( + _ "github.com/sdboyer/deptest" +) + +func main() { +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-novendor-dry/testcase.json b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-novendor-dry/testcase.json new file mode 100644 index 00000000..f3bdbe7e --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-novendor-dry/testcase.json @@ -0,0 +1,5 @@ +{ + "commands": [ + ["ensure", "-no-vendor", "-dry-run"] + ] +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-novendor/final/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-novendor/final/Gopkg.lock new file mode 100644 index 00000000..c7f497e7 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-novendor/final/Gopkg.lock @@ -0,0 +1,15 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "ff2948a2ac8f538c4ecd55962e919d1e13e74baf" + version = "v1.0.0" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "14b07b05e0f01051b03887ab2bf80b516bc5510ea92f75f76c894b1745d8850c" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-novendor/final/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-novendor/final/Gopkg.toml new file mode 100644 index 00000000..e242e021 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-novendor/final/Gopkg.toml @@ -0,0 +1,4 @@ + +[[constraint]] + name = "github.com/sdboyer/deptest" + version = "1.0.0" diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-novendor/initial/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-novendor/initial/Gopkg.lock new file mode 100644 index 00000000..c7f497e7 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-novendor/initial/Gopkg.lock @@ -0,0 +1,15 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "ff2948a2ac8f538c4ecd55962e919d1e13e74baf" + version = "v1.0.0" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "14b07b05e0f01051b03887ab2bf80b516bc5510ea92f75f76c894b1745d8850c" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-novendor/initial/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-novendor/initial/Gopkg.toml new file mode 100644 index 00000000..e242e021 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-novendor/initial/Gopkg.toml @@ -0,0 +1,4 @@ + +[[constraint]] + name = "github.com/sdboyer/deptest" + version = "1.0.0" diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-novendor/initial/main.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-novendor/initial/main.go new file mode 100644 index 00000000..1fe0d19d --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-novendor/initial/main.go @@ -0,0 +1,12 @@ +// Copyright 2016 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 main + +import ( + _ "github.com/sdboyer/deptest" +) + +func main() { +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-novendor/testcase.json b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-novendor/testcase.json new file mode 100644 index 00000000..7692eecf --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq-novendor/testcase.json @@ -0,0 +1,5 @@ +{ + "commands": [ + ["ensure", "-no-vendor"] + ] +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq/final/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq/final/Gopkg.lock new file mode 100644 index 00000000..c7f497e7 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq/final/Gopkg.lock @@ -0,0 +1,15 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "ff2948a2ac8f538c4ecd55962e919d1e13e74baf" + version = "v1.0.0" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "14b07b05e0f01051b03887ab2bf80b516bc5510ea92f75f76c894b1745d8850c" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq/final/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq/final/Gopkg.toml new file mode 100644 index 00000000..e242e021 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq/final/Gopkg.toml @@ -0,0 +1,4 @@ + +[[constraint]] + name = "github.com/sdboyer/deptest" + version = "1.0.0" diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq/initial/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq/initial/Gopkg.lock new file mode 100644 index 00000000..c7f497e7 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq/initial/Gopkg.lock @@ -0,0 +1,15 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "ff2948a2ac8f538c4ecd55962e919d1e13e74baf" + version = "v1.0.0" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "14b07b05e0f01051b03887ab2bf80b516bc5510ea92f75f76c894b1745d8850c" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq/initial/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq/initial/Gopkg.toml new file mode 100644 index 00000000..e242e021 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq/initial/Gopkg.toml @@ -0,0 +1,4 @@ + +[[constraint]] + name = "github.com/sdboyer/deptest" + version = "1.0.0" diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq/initial/main.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq/initial/main.go new file mode 100644 index 00000000..1fe0d19d --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq/initial/main.go @@ -0,0 +1,12 @@ +// Copyright 2016 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 main + +import ( + _ "github.com/sdboyer/deptest" +) + +func main() { +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq/testcase.json b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq/testcase.json new file mode 100644 index 00000000..19da5270 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hasheq/testcase.json @@ -0,0 +1,8 @@ +{ + "commands": [ + ["ensure"] + ], + "vendor-final": [ + "github.com/sdboyer/deptest" + ] +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hashneq-novendor-dry/final/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hashneq-novendor-dry/final/Gopkg.lock new file mode 100644 index 00000000..11cb12c3 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hashneq-novendor-dry/final/Gopkg.lock @@ -0,0 +1,16 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "ff2948a2ac8f538c4ecd55962e919d1e13e74baf" + version = "v1.0.0" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + # manually modified hash digest, it will not match any known inputs + inputs-digest = "94b07b05e0f01051b03887ab2bf80b516bc5510ea92f75f76c894b1745d8850c" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hashneq-novendor-dry/final/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hashneq-novendor-dry/final/Gopkg.toml new file mode 100644 index 00000000..e242e021 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hashneq-novendor-dry/final/Gopkg.toml @@ -0,0 +1,4 @@ + +[[constraint]] + name = "github.com/sdboyer/deptest" + version = "1.0.0" diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hashneq-novendor-dry/initial/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hashneq-novendor-dry/initial/Gopkg.lock new file mode 100644 index 00000000..11cb12c3 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hashneq-novendor-dry/initial/Gopkg.lock @@ -0,0 +1,16 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "ff2948a2ac8f538c4ecd55962e919d1e13e74baf" + version = "v1.0.0" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + # manually modified hash digest, it will not match any known inputs + inputs-digest = "94b07b05e0f01051b03887ab2bf80b516bc5510ea92f75f76c894b1745d8850c" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hashneq-novendor-dry/initial/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hashneq-novendor-dry/initial/Gopkg.toml new file mode 100644 index 00000000..e242e021 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hashneq-novendor-dry/initial/Gopkg.toml @@ -0,0 +1,4 @@ + +[[constraint]] + name = "github.com/sdboyer/deptest" + version = "1.0.0" diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hashneq-novendor-dry/initial/main.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hashneq-novendor-dry/initial/main.go new file mode 100644 index 00000000..1fe0d19d --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hashneq-novendor-dry/initial/main.go @@ -0,0 +1,12 @@ +// Copyright 2016 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 main + +import ( + _ "github.com/sdboyer/deptest" +) + +func main() { +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hashneq-novendor-dry/testcase.json b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hashneq-novendor-dry/testcase.json new file mode 100644 index 00000000..2e540694 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hashneq-novendor-dry/testcase.json @@ -0,0 +1,6 @@ +{ + "commands": [ + ["ensure", "-no-vendor", "-dry-run"] + ], + "error-expected": "Gopkg.lock was not up to date" +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hashneq-vendoronly/final/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hashneq-vendoronly/final/Gopkg.lock new file mode 100644 index 00000000..11cb12c3 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hashneq-vendoronly/final/Gopkg.lock @@ -0,0 +1,16 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "ff2948a2ac8f538c4ecd55962e919d1e13e74baf" + version = "v1.0.0" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + # manually modified hash digest, it will not match any known inputs + inputs-digest = "94b07b05e0f01051b03887ab2bf80b516bc5510ea92f75f76c894b1745d8850c" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hashneq-vendoronly/final/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hashneq-vendoronly/final/Gopkg.toml new file mode 100644 index 00000000..e242e021 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hashneq-vendoronly/final/Gopkg.toml @@ -0,0 +1,4 @@ + +[[constraint]] + name = "github.com/sdboyer/deptest" + version = "1.0.0" diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hashneq-vendoronly/initial/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hashneq-vendoronly/initial/Gopkg.lock new file mode 100644 index 00000000..11cb12c3 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hashneq-vendoronly/initial/Gopkg.lock @@ -0,0 +1,16 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "ff2948a2ac8f538c4ecd55962e919d1e13e74baf" + version = "v1.0.0" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + # manually modified hash digest, it will not match any known inputs + inputs-digest = "94b07b05e0f01051b03887ab2bf80b516bc5510ea92f75f76c894b1745d8850c" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hashneq-vendoronly/initial/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hashneq-vendoronly/initial/Gopkg.toml new file mode 100644 index 00000000..e242e021 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hashneq-vendoronly/initial/Gopkg.toml @@ -0,0 +1,4 @@ + +[[constraint]] + name = "github.com/sdboyer/deptest" + version = "1.0.0" diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hashneq-vendoronly/initial/main.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hashneq-vendoronly/initial/main.go new file mode 100644 index 00000000..1fe0d19d --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hashneq-vendoronly/initial/main.go @@ -0,0 +1,12 @@ +// Copyright 2016 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 main + +import ( + _ "github.com/sdboyer/deptest" +) + +func main() { +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hashneq-vendoronly/testcase.json b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hashneq-vendoronly/testcase.json new file mode 100644 index 00000000..8a288759 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/hashneq-vendoronly/testcase.json @@ -0,0 +1,8 @@ +{ + "commands": [ + ["ensure", "-vendor-only"] + ], + "vendor-final": [ + "github.com/sdboyer/deptest" + ] +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/nocode-vendoronly/final/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/nocode-vendoronly/final/Gopkg.lock new file mode 100644 index 00000000..11cb12c3 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/nocode-vendoronly/final/Gopkg.lock @@ -0,0 +1,16 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "ff2948a2ac8f538c4ecd55962e919d1e13e74baf" + version = "v1.0.0" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + # manually modified hash digest, it will not match any known inputs + inputs-digest = "94b07b05e0f01051b03887ab2bf80b516bc5510ea92f75f76c894b1745d8850c" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/nocode-vendoronly/final/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/nocode-vendoronly/final/Gopkg.toml new file mode 100644 index 00000000..e242e021 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/nocode-vendoronly/final/Gopkg.toml @@ -0,0 +1,4 @@ + +[[constraint]] + name = "github.com/sdboyer/deptest" + version = "1.0.0" diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/nocode-vendoronly/initial/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/nocode-vendoronly/initial/Gopkg.lock new file mode 100644 index 00000000..11cb12c3 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/nocode-vendoronly/initial/Gopkg.lock @@ -0,0 +1,16 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "ff2948a2ac8f538c4ecd55962e919d1e13e74baf" + version = "v1.0.0" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + # manually modified hash digest, it will not match any known inputs + inputs-digest = "94b07b05e0f01051b03887ab2bf80b516bc5510ea92f75f76c894b1745d8850c" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/nocode-vendoronly/initial/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/nocode-vendoronly/initial/Gopkg.toml new file mode 100644 index 00000000..e242e021 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/nocode-vendoronly/initial/Gopkg.toml @@ -0,0 +1,4 @@ + +[[constraint]] + name = "github.com/sdboyer/deptest" + version = "1.0.0" diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/nocode-vendoronly/testcase.json b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/nocode-vendoronly/testcase.json new file mode 100644 index 00000000..8a288759 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/default/nocode-vendoronly/testcase.json @@ -0,0 +1,8 @@ +{ + "commands": [ + ["ensure", "-vendor-only"] + ], + "vendor-final": [ + "github.com/sdboyer/deptest" + ] +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/empty/case1/final/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/empty/case1/final/Gopkg.lock new file mode 100644 index 00000000..c7f497e7 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/empty/case1/final/Gopkg.lock @@ -0,0 +1,15 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "ff2948a2ac8f538c4ecd55962e919d1e13e74baf" + version = "v1.0.0" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "14b07b05e0f01051b03887ab2bf80b516bc5510ea92f75f76c894b1745d8850c" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/empty/case1/final/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/empty/case1/final/Gopkg.toml new file mode 100644 index 00000000..51a3481d --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/empty/case1/final/Gopkg.toml @@ -0,0 +1,8 @@ + +[[constraint]] + name = "github.com/sdboyer/deptest" + version = "1.0.0" + +[prune] + go-tests = true + unused-packages = true diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/empty/case1/initial/main.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/empty/case1/initial/main.go new file mode 100644 index 00000000..1fe0d19d --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/empty/case1/initial/main.go @@ -0,0 +1,12 @@ +// Copyright 2016 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 main + +import ( + _ "github.com/sdboyer/deptest" +) + +func main() { +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/empty/case1/testcase.json b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/empty/case1/testcase.json new file mode 100644 index 00000000..0cf0fd90 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/empty/case1/testcase.json @@ -0,0 +1,9 @@ +{ + "commands": [ + ["init", "-skip-tools", "-no-examples"], + ["ensure", "-update"] + ], + "vendor-final": [ + "github.com/sdboyer/deptest" + ] +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/empty/case2/final/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/empty/case2/final/Gopkg.lock new file mode 100644 index 00000000..a783451f --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/empty/case2/final/Gopkg.lock @@ -0,0 +1,15 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "ff2948a2ac8f538c4ecd55962e919d1e13e74baf" + version = "v1.0.0" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "e7725ea56516a42a641aaaf5d48754258d9f3c59949cb8a0e8a21b1ab6e07179" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/empty/case2/final/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/empty/case2/final/Gopkg.toml new file mode 100644 index 00000000..532da96a --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/empty/case2/final/Gopkg.toml @@ -0,0 +1,3 @@ +[[constraint]] + name = "github.com/sdboyer/deptest" + version = "~0.8.0" \ No newline at end of file diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/empty/case2/initial/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/empty/case2/initial/Gopkg.toml new file mode 100644 index 00000000..532da96a --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/empty/case2/initial/Gopkg.toml @@ -0,0 +1,3 @@ +[[constraint]] + name = "github.com/sdboyer/deptest" + version = "~0.8.0" \ No newline at end of file diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/empty/case2/initial/main.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/empty/case2/initial/main.go new file mode 100644 index 00000000..1fe0d19d --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/empty/case2/initial/main.go @@ -0,0 +1,12 @@ +// Copyright 2016 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 main + +import ( + _ "github.com/sdboyer/deptest" +) + +func main() { +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/empty/case2/testcase.json b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/empty/case2/testcase.json new file mode 100644 index 00000000..729de9d0 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/empty/case2/testcase.json @@ -0,0 +1,9 @@ +{ + "commands": [ + ["ensure"] + ], + "error-expected": "", + "vendor-final": [ + "github.com/sdboyer/deptest" + ] +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/empty/case3/README.md b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/empty/case3/README.md new file mode 100644 index 00000000..34b1e0c1 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/empty/case3/README.md @@ -0,0 +1,2 @@ +Validate that packages imported in an ignored package are not +included in the manifest or lock. \ No newline at end of file diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/empty/case3/final/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/empty/case3/final/Gopkg.lock new file mode 100644 index 00000000..d2153e37 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/empty/case3/final/Gopkg.lock @@ -0,0 +1,15 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + branch = "master" + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "3f4c3bea144e112a69bbe5d8d01c1b09a544253f" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "e5c16e09ed6f0a1a2b3cf472c34b7fd50861dd070e81d5e623f72e8173f0c065" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/empty/case3/final/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/empty/case3/final/Gopkg.toml new file mode 100644 index 00000000..d77e367c --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/empty/case3/final/Gopkg.toml @@ -0,0 +1,5 @@ +ignored = ["github.com/sdboyer/deptestdos"] + +[[constraint]] + branch = "master" + name = "github.com/sdboyer/deptest" diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/empty/case3/initial/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/empty/case3/initial/Gopkg.lock new file mode 100644 index 00000000..5bfebb27 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/empty/case3/initial/Gopkg.lock @@ -0,0 +1,15 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + branch = "master" + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "3f4c3bea144e112a69bbe5d8d01c1b09a544253f" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "8114537cd7d93f5eacebdea7dfec0c3c10919d7f952d056e2a3142fee1c33aee" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/empty/case3/initial/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/empty/case3/initial/Gopkg.toml new file mode 100644 index 00000000..d77e367c --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/empty/case3/initial/Gopkg.toml @@ -0,0 +1,5 @@ +ignored = ["github.com/sdboyer/deptestdos"] + +[[constraint]] + branch = "master" + name = "github.com/sdboyer/deptest" diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/empty/case3/initial/main.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/empty/case3/initial/main.go new file mode 100644 index 00000000..1fe0d19d --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/empty/case3/initial/main.go @@ -0,0 +1,12 @@ +// Copyright 2016 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 main + +import ( + _ "github.com/sdboyer/deptest" +) + +func main() { +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/empty/case3/initial/samples/samples.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/empty/case3/initial/samples/samples.go new file mode 100644 index 00000000..822fc935 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/empty/case3/initial/samples/samples.go @@ -0,0 +1,7 @@ +// Copyright 2016 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 samples + +import _ "github.com/sdboyer/deptestdos" diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/empty/case3/testcase.json b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/empty/case3/testcase.json new file mode 100644 index 00000000..729de9d0 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/empty/case3/testcase.json @@ -0,0 +1,9 @@ +{ + "commands": [ + ["ensure"] + ], + "error-expected": "", + "vendor-final": [ + "github.com/sdboyer/deptest" + ] +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-errors/case1/final/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-errors/case1/final/Gopkg.lock new file mode 100644 index 00000000..bef2d009 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-errors/case1/final/Gopkg.lock @@ -0,0 +1,9 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "ab4fef131ee828e96ba67d31a7d690bd5f2f42040c6766b1b12fe856f87e0ff7" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-errors/case1/final/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-errors/case1/final/Gopkg.toml new file mode 100644 index 00000000..db111447 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-errors/case1/final/Gopkg.toml @@ -0,0 +1,4 @@ + +[prune] + go-tests = true + unused-packages = true diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-errors/case1/testcase.json b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-errors/case1/testcase.json new file mode 100644 index 00000000..fede436f --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-errors/case1/testcase.json @@ -0,0 +1,8 @@ +{ + "commands": [ + ["init", "-no-examples", "-skip-tools"], + ["ensure", "-update"] + ], + "error-expected": "no dirs contained any Go code", + "vendor-final": [] +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-errors/case2/final/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-errors/case2/final/Gopkg.toml new file mode 100644 index 00000000..e69de29b diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-errors/case2/initial/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-errors/case2/initial/Gopkg.toml new file mode 100644 index 00000000..e69de29b diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-errors/case2/initial/bar/bar.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-errors/case2/initial/bar/bar.go new file mode 100644 index 00000000..b007341e --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-errors/case2/initial/bar/bar.go @@ -0,0 +1,3 @@ +// Copyright 2017 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. diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-errors/case2/initial/baz/.gitignore b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-errors/case2/initial/baz/.gitignore new file mode 100644 index 00000000..e69de29b diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-errors/case2/testcase.json b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-errors/case2/testcase.json new file mode 100644 index 00000000..5353ea6b --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-errors/case2/testcase.json @@ -0,0 +1,7 @@ +{ + "commands": [ + ["ensure"] + ], + "error-expected": "found 1 errors", + "vendor-final": [] +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-ignore/final/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-ignore/final/Gopkg.lock new file mode 100644 index 00000000..1e637dd5 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-ignore/final/Gopkg.lock @@ -0,0 +1,15 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "3f4c3bea144e112a69bbe5d8d01c1b09a544253f" + version = "v0.8.1" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "5210e61a67f6e64dabb1eb8f28df2dbeeedfca1588c102067a6ec8a35e0b15f9" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-ignore/final/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-ignore/final/Gopkg.toml new file mode 100644 index 00000000..5e109dd4 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-ignore/final/Gopkg.toml @@ -0,0 +1,5 @@ +ignored = ["github.com/golang/notexist/samples*"] + +[[constraint]] + branch = "master" + name = "github.com/sdboyer/deptest" diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-ignore/initial/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-ignore/initial/Gopkg.lock new file mode 100644 index 00000000..bef2d009 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-ignore/initial/Gopkg.lock @@ -0,0 +1,9 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "ab4fef131ee828e96ba67d31a7d690bd5f2f42040c6766b1b12fe856f87e0ff7" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-ignore/initial/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-ignore/initial/Gopkg.toml new file mode 100644 index 00000000..5e109dd4 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-ignore/initial/Gopkg.toml @@ -0,0 +1,5 @@ +ignored = ["github.com/golang/notexist/samples*"] + +[[constraint]] + branch = "master" + name = "github.com/sdboyer/deptest" diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-ignore/initial/main.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-ignore/initial/main.go new file mode 100644 index 00000000..e23fcf34 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-ignore/initial/main.go @@ -0,0 +1,12 @@ +// Copyright 2017 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 main + +import ( + _ "github.com/sdboyer/deptest" +) + +func main() { +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-ignore/initial/samples/samples.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-ignore/initial/samples/samples.go new file mode 100644 index 00000000..d07de170 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-ignore/initial/samples/samples.go @@ -0,0 +1,7 @@ +// Copyright 2017 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 samples + +import _ "github.com/sdboyer/deptestdos" diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-ignore/initial/samples/subsamples/subsamples.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-ignore/initial/samples/subsamples/subsamples.go new file mode 100644 index 00000000..5136538e --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-ignore/initial/samples/subsamples/subsamples.go @@ -0,0 +1,7 @@ +// Copyright 2017 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 subsamples + +import _ "github.com/sdboyer/dep-test" diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-ignore/stdout.txt b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-ignore/stdout.txt new file mode 100644 index 00000000..74542e41 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-ignore/stdout.txt @@ -0,0 +1,11 @@ +-CONSTRAINTS- +github.com/sdboyer/deptest +b-master +-IMPORTS/REQS- +github.com/sdboyer/deptest +-IGNORES- +-OVERRIDES- +-ANALYZER- +dep +1 + diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-ignore/testcase.json b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-ignore/testcase.json new file mode 100644 index 00000000..5641e856 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-ignore/testcase.json @@ -0,0 +1,10 @@ +{ + "commands": [ + ["ensure"], + ["hash-inputs"] + ], + "error-expected": "", + "vendor-final": [ + "github.com/sdboyer/deptest" + ] +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-other-root/final/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-other-root/final/Gopkg.lock new file mode 100644 index 00000000..53e42dcc --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-other-root/final/Gopkg.lock @@ -0,0 +1,9 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "b02b7a80e20404724ba5dbffab28e772017b03800916327f58bff0da86071b6a" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-other-root/final/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-other-root/final/Gopkg.toml new file mode 100644 index 00000000..f54b63d5 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-other-root/final/Gopkg.toml @@ -0,0 +1 @@ +ignored = ["github.com/sdboyer/deptest*", "github.com/golang/notexist/samples*"] diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-other-root/initial/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-other-root/initial/Gopkg.lock new file mode 100644 index 00000000..bef2d009 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-other-root/initial/Gopkg.lock @@ -0,0 +1,9 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "ab4fef131ee828e96ba67d31a7d690bd5f2f42040c6766b1b12fe856f87e0ff7" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-other-root/initial/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-other-root/initial/Gopkg.toml new file mode 100644 index 00000000..f54b63d5 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-other-root/initial/Gopkg.toml @@ -0,0 +1 @@ +ignored = ["github.com/sdboyer/deptest*", "github.com/golang/notexist/samples*"] diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-other-root/initial/main.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-other-root/initial/main.go new file mode 100644 index 00000000..e23fcf34 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-other-root/initial/main.go @@ -0,0 +1,12 @@ +// Copyright 2017 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 main + +import ( + _ "github.com/sdboyer/deptest" +) + +func main() { +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-other-root/initial/samples/samples.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-other-root/initial/samples/samples.go new file mode 100644 index 00000000..d07de170 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-other-root/initial/samples/samples.go @@ -0,0 +1,7 @@ +// Copyright 2017 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 samples + +import _ "github.com/sdboyer/deptestdos" diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-other-root/initial/samples/subsamples/subsamples.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-other-root/initial/samples/subsamples/subsamples.go new file mode 100644 index 00000000..5136538e --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-other-root/initial/samples/subsamples/subsamples.go @@ -0,0 +1,7 @@ +// Copyright 2017 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 subsamples + +import _ "github.com/sdboyer/dep-test" diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-other-root/stdout.txt b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-other-root/stdout.txt new file mode 100644 index 00000000..a273de0e --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-other-root/stdout.txt @@ -0,0 +1,9 @@ +-CONSTRAINTS- +-IMPORTS/REQS- +-IGNORES- +github.com/sdboyer/deptest* +-OVERRIDES- +-ANALYZER- +dep +1 + diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-other-root/testcase.json b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-other-root/testcase.json new file mode 100644 index 00000000..4f16d1c6 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/pkg-ignored/wildcard-other-root/testcase.json @@ -0,0 +1,8 @@ +{ + "commands": [ + ["ensure"], + ["hash-inputs"] + ], + "error-expected": "", + "vendor-final": [] +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/case1/final/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/case1/final/Gopkg.lock new file mode 100644 index 00000000..1a7b1983 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/case1/final/Gopkg.lock @@ -0,0 +1,21 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "ff2948a2ac8f538c4ecd55962e919d1e13e74baf" + version = "v1.0.0" + +[[projects]] + name = "github.com/sdboyer/deptestdos" + packages = ["."] + revision = "5c607206be5decd28e6263ffffdcee067266015e" + version = "v2.0.0" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "1b381263a360eafafe3ef7f9be626672668d17250a3c9a8debd169d1b5e2eebb" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/case1/final/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/case1/final/Gopkg.toml new file mode 100644 index 00000000..532da96a --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/case1/final/Gopkg.toml @@ -0,0 +1,3 @@ +[[constraint]] + name = "github.com/sdboyer/deptest" + version = "~0.8.0" \ No newline at end of file diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/case1/initial/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/case1/initial/Gopkg.lock new file mode 100644 index 00000000..7265a555 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/case1/initial/Gopkg.lock @@ -0,0 +1,21 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/sdboyer/deptest" + version = "v0.8.0" + revision = "ff2948a2ac8f538c4ecd55962e919d1e13e74baf" + packages = ["."] + +[[projects]] + name = "github.com/sdboyer/deptestdos" + version = "v2.0.0" + revision = "5c607206be5decd28e6263ffffdcee067266015e" + packages = ["."] + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "1b381263a360eafafe3ef7f9be626672668d17250a3c9a8debd169d1b5e2eebb" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/case1/initial/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/case1/initial/Gopkg.toml new file mode 100644 index 00000000..532da96a --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/case1/initial/Gopkg.toml @@ -0,0 +1,3 @@ +[[constraint]] + name = "github.com/sdboyer/deptest" + version = "~0.8.0" \ No newline at end of file diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/case1/initial/main.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/case1/initial/main.go new file mode 100644 index 00000000..2eae5b51 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/case1/initial/main.go @@ -0,0 +1,18 @@ +// Copyright 2016 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 main + +import ( + "github.com/sdboyer/deptest" + "github.com/sdboyer/deptestdos" +) + +func main() { + err := nil + if err != nil { + deptest.Map["yo yo!"] + } + deptestdos.diMeLo("whatev") +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/case1/testcase.json b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/case1/testcase.json new file mode 100644 index 00000000..07bc6352 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/case1/testcase.json @@ -0,0 +1,10 @@ +{ + "commands": [ + ["ensure", "-update", "github.com/sdboyer/deptest"] + ], + "error-expected": "", + "vendor-final": [ + "github.com/sdboyer/deptest", + "github.com/sdboyer/deptestdos" + ] +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/desync/final/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/desync/final/Gopkg.lock new file mode 100644 index 00000000..1a7b1983 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/desync/final/Gopkg.lock @@ -0,0 +1,21 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "ff2948a2ac8f538c4ecd55962e919d1e13e74baf" + version = "v1.0.0" + +[[projects]] + name = "github.com/sdboyer/deptestdos" + packages = ["."] + revision = "5c607206be5decd28e6263ffffdcee067266015e" + version = "v2.0.0" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "1b381263a360eafafe3ef7f9be626672668d17250a3c9a8debd169d1b5e2eebb" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/desync/final/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/desync/final/Gopkg.toml new file mode 100644 index 00000000..532da96a --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/desync/final/Gopkg.toml @@ -0,0 +1,3 @@ +[[constraint]] + name = "github.com/sdboyer/deptest" + version = "~0.8.0" \ No newline at end of file diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/desync/final/main.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/desync/final/main.go new file mode 100644 index 00000000..2eae5b51 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/desync/final/main.go @@ -0,0 +1,18 @@ +// Copyright 2016 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 main + +import ( + "github.com/sdboyer/deptest" + "github.com/sdboyer/deptestdos" +) + +func main() { + err := nil + if err != nil { + deptest.Map["yo yo!"] + } + deptestdos.diMeLo("whatev") +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/desync/initial/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/desync/initial/Gopkg.lock new file mode 100644 index 00000000..41dd2d41 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/desync/initial/Gopkg.lock @@ -0,0 +1,21 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/sdboyer/deptest" + version = "v0.8.0" + revision = "ff2948a2ac8f538c4ecd55962e919d1e13e74baf" + packages = ["."] + +[[projects]] + name = "github.com/sdboyer/deptestdos" + version = "v2.0.0" + revision = "5c607206be5decd28e6263ffffdcee067266015e" + packages = ["."] + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "9b381263a360eafafe3ef7f9be626672668d17250a3c9a8debd169d1b5e2eebb" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/desync/initial/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/desync/initial/Gopkg.toml new file mode 100644 index 00000000..532da96a --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/desync/initial/Gopkg.toml @@ -0,0 +1,3 @@ +[[constraint]] + name = "github.com/sdboyer/deptest" + version = "~0.8.0" \ No newline at end of file diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/desync/initial/main.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/desync/initial/main.go new file mode 100644 index 00000000..2eae5b51 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/desync/initial/main.go @@ -0,0 +1,18 @@ +// Copyright 2016 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 main + +import ( + "github.com/sdboyer/deptest" + "github.com/sdboyer/deptestdos" +) + +func main() { + err := nil + if err != nil { + deptest.Map["yo yo!"] + } + deptestdos.diMeLo("whatev") +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/desync/stdout.txt b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/desync/stdout.txt new file mode 100644 index 00000000..9adb1974 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/desync/stdout.txt @@ -0,0 +1 @@ +Warning: Gopkg.lock is out of sync with Gopkg.toml or the project's imports. diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/desync/testcase.json b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/desync/testcase.json new file mode 100644 index 00000000..81a7c232 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/desync/testcase.json @@ -0,0 +1,9 @@ +{ + "commands": [ + ["ensure", "-update"] + ], + "vendor-final": [ + "github.com/sdboyer/deptest", + "github.com/sdboyer/deptestdos" + ] +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/lockless/final/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/lockless/final/Gopkg.toml new file mode 100644 index 00000000..e242e021 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/lockless/final/Gopkg.toml @@ -0,0 +1,4 @@ + +[[constraint]] + name = "github.com/sdboyer/deptest" + version = "1.0.0" diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/lockless/final/main.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/lockless/final/main.go new file mode 100644 index 00000000..1fe0d19d --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/lockless/final/main.go @@ -0,0 +1,12 @@ +// Copyright 2016 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 main + +import ( + _ "github.com/sdboyer/deptest" +) + +func main() { +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/lockless/initial/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/lockless/initial/Gopkg.toml new file mode 100644 index 00000000..e242e021 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/lockless/initial/Gopkg.toml @@ -0,0 +1,4 @@ + +[[constraint]] + name = "github.com/sdboyer/deptest" + version = "1.0.0" diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/lockless/initial/main.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/lockless/initial/main.go new file mode 100644 index 00000000..1fe0d19d --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/lockless/initial/main.go @@ -0,0 +1,12 @@ +// Copyright 2016 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 main + +import ( + _ "github.com/sdboyer/deptest" +) + +func main() { +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/lockless/testcase.json b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/lockless/testcase.json new file mode 100644 index 00000000..a69d08d0 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/lockless/testcase.json @@ -0,0 +1,6 @@ +{ + "commands": [ + ["ensure", "-update"] + ], + "error-expected": "-update works by updating the versions recorded in Gopkg.lock, but Gopkg.lock does not exist" +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/nonroot-arg/final/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/nonroot-arg/final/Gopkg.lock new file mode 100644 index 00000000..c7f497e7 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/nonroot-arg/final/Gopkg.lock @@ -0,0 +1,15 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "ff2948a2ac8f538c4ecd55962e919d1e13e74baf" + version = "v1.0.0" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "14b07b05e0f01051b03887ab2bf80b516bc5510ea92f75f76c894b1745d8850c" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/nonroot-arg/final/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/nonroot-arg/final/Gopkg.toml new file mode 100644 index 00000000..51ff69b3 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/nonroot-arg/final/Gopkg.toml @@ -0,0 +1,3 @@ +[[constraint]] + name = "github.com/sdboyer/deptest" + version = "1.0.0" diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/nonroot-arg/initial/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/nonroot-arg/initial/Gopkg.lock new file mode 100644 index 00000000..c7f497e7 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/nonroot-arg/initial/Gopkg.lock @@ -0,0 +1,15 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "ff2948a2ac8f538c4ecd55962e919d1e13e74baf" + version = "v1.0.0" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "14b07b05e0f01051b03887ab2bf80b516bc5510ea92f75f76c894b1745d8850c" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/nonroot-arg/initial/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/nonroot-arg/initial/Gopkg.toml new file mode 100644 index 00000000..51ff69b3 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/nonroot-arg/initial/Gopkg.toml @@ -0,0 +1,3 @@ +[[constraint]] + name = "github.com/sdboyer/deptest" + version = "1.0.0" diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/nonroot-arg/initial/main.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/nonroot-arg/initial/main.go new file mode 100644 index 00000000..c5b8da51 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/nonroot-arg/initial/main.go @@ -0,0 +1,13 @@ +// Copyright 2016 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 main + +import ( + "github.com/sdboyer/deptest" +) + +func main() { + _ := deptest.Map["yo yo!"] +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/nonroot-arg/testcase.json b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/nonroot-arg/testcase.json new file mode 100644 index 00000000..4b4b4fe0 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/nonroot-arg/testcase.json @@ -0,0 +1,6 @@ +{ + "commands": [ + ["ensure", "-update", "github.com/sdboyer/deptest/subpkg"] + ], + "error-expected": "github.com/sdboyer/deptest/subpkg is not a project root, try github.com/sdboyer/deptest instead" +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/not-in-lock/final/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/not-in-lock/final/Gopkg.lock new file mode 100644 index 00000000..c7f497e7 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/not-in-lock/final/Gopkg.lock @@ -0,0 +1,15 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "ff2948a2ac8f538c4ecd55962e919d1e13e74baf" + version = "v1.0.0" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "14b07b05e0f01051b03887ab2bf80b516bc5510ea92f75f76c894b1745d8850c" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/not-in-lock/final/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/not-in-lock/final/Gopkg.toml new file mode 100644 index 00000000..51ff69b3 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/not-in-lock/final/Gopkg.toml @@ -0,0 +1,3 @@ +[[constraint]] + name = "github.com/sdboyer/deptest" + version = "1.0.0" diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/not-in-lock/initial/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/not-in-lock/initial/Gopkg.lock new file mode 100644 index 00000000..c7f497e7 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/not-in-lock/initial/Gopkg.lock @@ -0,0 +1,15 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "ff2948a2ac8f538c4ecd55962e919d1e13e74baf" + version = "v1.0.0" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "14b07b05e0f01051b03887ab2bf80b516bc5510ea92f75f76c894b1745d8850c" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/not-in-lock/initial/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/not-in-lock/initial/Gopkg.toml new file mode 100644 index 00000000..51ff69b3 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/not-in-lock/initial/Gopkg.toml @@ -0,0 +1,3 @@ +[[constraint]] + name = "github.com/sdboyer/deptest" + version = "1.0.0" diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/not-in-lock/initial/main.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/not-in-lock/initial/main.go new file mode 100644 index 00000000..c5b8da51 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/not-in-lock/initial/main.go @@ -0,0 +1,13 @@ +// Copyright 2016 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 main + +import ( + "github.com/sdboyer/deptest" +) + +func main() { + _ := deptest.Map["yo yo!"] +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/not-in-lock/testcase.json b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/not-in-lock/testcase.json new file mode 100644 index 00000000..0fda36ed --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/not-in-lock/testcase.json @@ -0,0 +1,6 @@ +{ + "commands": [ + ["ensure", "-update", "github.com/sdboyer/deptesttres"] + ], + "error-expected": "github.com/sdboyer/deptesttres is not present in Gopkg.lock, cannot -update it" +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/spec-with-constraint/final/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/spec-with-constraint/final/Gopkg.lock new file mode 100644 index 00000000..c7f497e7 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/spec-with-constraint/final/Gopkg.lock @@ -0,0 +1,15 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "ff2948a2ac8f538c4ecd55962e919d1e13e74baf" + version = "v1.0.0" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "14b07b05e0f01051b03887ab2bf80b516bc5510ea92f75f76c894b1745d8850c" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/spec-with-constraint/final/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/spec-with-constraint/final/Gopkg.toml new file mode 100644 index 00000000..51ff69b3 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/spec-with-constraint/final/Gopkg.toml @@ -0,0 +1,3 @@ +[[constraint]] + name = "github.com/sdboyer/deptest" + version = "1.0.0" diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/spec-with-constraint/initial/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/spec-with-constraint/initial/Gopkg.lock new file mode 100644 index 00000000..c7f497e7 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/spec-with-constraint/initial/Gopkg.lock @@ -0,0 +1,15 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "ff2948a2ac8f538c4ecd55962e919d1e13e74baf" + version = "v1.0.0" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "14b07b05e0f01051b03887ab2bf80b516bc5510ea92f75f76c894b1745d8850c" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/spec-with-constraint/initial/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/spec-with-constraint/initial/Gopkg.toml new file mode 100644 index 00000000..51ff69b3 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/spec-with-constraint/initial/Gopkg.toml @@ -0,0 +1,3 @@ +[[constraint]] + name = "github.com/sdboyer/deptest" + version = "1.0.0" diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/spec-with-constraint/initial/main.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/spec-with-constraint/initial/main.go new file mode 100644 index 00000000..c5b8da51 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/spec-with-constraint/initial/main.go @@ -0,0 +1,13 @@ +// Copyright 2016 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 main + +import ( + "github.com/sdboyer/deptest" +) + +func main() { + _ := deptest.Map["yo yo!"] +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/spec-with-constraint/testcase.json b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/spec-with-constraint/testcase.json new file mode 100644 index 00000000..7332bc49 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/spec-with-constraint/testcase.json @@ -0,0 +1,6 @@ +{ + "commands": [ + ["ensure", "-update", "github.com/sdboyer/deptest:github.com/other/deptest"] + ], + "error-expected": "cannot specify alternate sources on -update (github.com/other/deptest)" +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/spec-with-source/final/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/spec-with-source/final/Gopkg.lock new file mode 100644 index 00000000..c7f497e7 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/spec-with-source/final/Gopkg.lock @@ -0,0 +1,15 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "ff2948a2ac8f538c4ecd55962e919d1e13e74baf" + version = "v1.0.0" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "14b07b05e0f01051b03887ab2bf80b516bc5510ea92f75f76c894b1745d8850c" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/spec-with-source/final/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/spec-with-source/final/Gopkg.toml new file mode 100644 index 00000000..51ff69b3 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/spec-with-source/final/Gopkg.toml @@ -0,0 +1,3 @@ +[[constraint]] + name = "github.com/sdboyer/deptest" + version = "1.0.0" diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/spec-with-source/initial/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/spec-with-source/initial/Gopkg.lock new file mode 100644 index 00000000..c7f497e7 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/spec-with-source/initial/Gopkg.lock @@ -0,0 +1,15 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "ff2948a2ac8f538c4ecd55962e919d1e13e74baf" + version = "v1.0.0" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "14b07b05e0f01051b03887ab2bf80b516bc5510ea92f75f76c894b1745d8850c" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/spec-with-source/initial/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/spec-with-source/initial/Gopkg.toml new file mode 100644 index 00000000..51ff69b3 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/spec-with-source/initial/Gopkg.toml @@ -0,0 +1,3 @@ +[[constraint]] + name = "github.com/sdboyer/deptest" + version = "1.0.0" diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/spec-with-source/initial/main.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/spec-with-source/initial/main.go new file mode 100644 index 00000000..c5b8da51 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/spec-with-source/initial/main.go @@ -0,0 +1,13 @@ +// Copyright 2016 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 main + +import ( + "github.com/sdboyer/deptest" +) + +func main() { + _ := deptest.Map["yo yo!"] +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/spec-with-source/testcase.json b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/spec-with-source/testcase.json new file mode 100644 index 00000000..27c8a5fc --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/errs/spec-with-source/testcase.json @@ -0,0 +1,6 @@ +{ + "commands": [ + ["ensure", "-update", "github.com/sdboyer/deptest@1.0.0"] + ], + "error-expected": "version constraint ^1.0.0 passed for github.com/sdboyer/deptest, but -update follows constraints declared in" +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/novendor/final/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/novendor/final/Gopkg.lock new file mode 100644 index 00000000..c7f497e7 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/novendor/final/Gopkg.lock @@ -0,0 +1,15 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "ff2948a2ac8f538c4ecd55962e919d1e13e74baf" + version = "v1.0.0" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "14b07b05e0f01051b03887ab2bf80b516bc5510ea92f75f76c894b1745d8850c" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/novendor/final/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/novendor/final/Gopkg.toml new file mode 100644 index 00000000..e242e021 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/novendor/final/Gopkg.toml @@ -0,0 +1,4 @@ + +[[constraint]] + name = "github.com/sdboyer/deptest" + version = "1.0.0" diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/novendor/initial/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/novendor/initial/Gopkg.lock new file mode 100644 index 00000000..810f1b03 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/novendor/initial/Gopkg.lock @@ -0,0 +1,15 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "3f4c3bea144e112a69bbe5d8d01c1b09a544253f" + version = "v0.8.1" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "14b07b05e0f01051b03887ab2bf80b516bc5510ea92f75f76c894b1745d8850c" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/novendor/initial/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/novendor/initial/Gopkg.toml new file mode 100644 index 00000000..e242e021 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/novendor/initial/Gopkg.toml @@ -0,0 +1,4 @@ + +[[constraint]] + name = "github.com/sdboyer/deptest" + version = "1.0.0" diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/novendor/initial/main.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/novendor/initial/main.go new file mode 100644 index 00000000..e23fcf34 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/novendor/initial/main.go @@ -0,0 +1,12 @@ +// Copyright 2017 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 main + +import ( + _ "github.com/sdboyer/deptest" +) + +func main() { +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/novendor/testcase.json b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/novendor/testcase.json new file mode 100644 index 00000000..518f5efb --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/ensure/update/novendor/testcase.json @@ -0,0 +1,5 @@ +{ + "commands": [ + ["ensure", "-update", "-no-vendor"] + ] +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case1/final/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case1/final/Gopkg.lock new file mode 100644 index 00000000..15b4e08b --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case1/final/Gopkg.lock @@ -0,0 +1,20 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "ff2948a2ac8f538c4ecd55962e919d1e13e74baf" + version = "v0.8.0" + +[[projects]] + name = "github.com/sdboyer/deptestdos" + packages = ["."] + revision = "a0196baa11ea047dd65037287451d36b861b00ea" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "1b381263a360eafafe3ef7f9be626672668d17250a3c9a8debd169d1b5e2eebb" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case1/final/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case1/final/Gopkg.toml new file mode 100644 index 00000000..c262475f --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case1/final/Gopkg.toml @@ -0,0 +1,8 @@ + +[[constraint]] + name = "github.com/sdboyer/deptest" + version = "0.8.0" + +[prune] + go-tests = true + unused-packages = true diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case1/initial/foo/bar.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case1/initial/foo/bar.go new file mode 100644 index 00000000..c1ed69fc --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case1/initial/foo/bar.go @@ -0,0 +1,13 @@ +// Copyright 2017 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 foo + +import "github.com/sdboyer/deptest" + +func Foo() deptest.Foo { + var y deptest.Foo + + return y +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case1/initial/main.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case1/initial/main.go new file mode 100644 index 00000000..83a4dfcd --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case1/initial/main.go @@ -0,0 +1,19 @@ +// Copyright 2017 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 main + +import ( + "fmt" + + "github.com/golang/notexist/foo" + "github.com/sdboyer/deptestdos" +) + +func main() { + var x deptestdos.Bar + y := foo.FooFunc() + + fmt.Println(x, y) +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case1/testcase.json b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case1/testcase.json new file mode 100644 index 00000000..ad5663ad --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case1/testcase.json @@ -0,0 +1,14 @@ +{ + "commands": [ + ["init", "-no-examples", "-skip-tools", "-gopath"] + ], + "error-expected": "", + "gopath-initial": { + "github.com/sdboyer/deptest": "v0.8.0", + "github.com/sdboyer/deptestdos": "a0196baa11ea047dd65037287451d36b861b00ea" + }, + "vendor-final": [ + "github.com/sdboyer/deptest", + "github.com/sdboyer/deptestdos" + ] +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case2/final/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case2/final/Gopkg.lock new file mode 100644 index 00000000..608d5a8d --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case2/final/Gopkg.lock @@ -0,0 +1,21 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "ff2948a2ac8f538c4ecd55962e919d1e13e74baf" + version = "v0.8.0" + +[[projects]] + name = "github.com/sdboyer/deptestdos" + packages = ["."] + revision = "5c607206be5decd28e6263ffffdcee067266015e" + version = "v2.0.0" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "ced51326ad990b11098d8076d0f7d72d89eee1ba6e8dacc7bc73be05cddac438" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case2/final/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case2/final/Gopkg.toml new file mode 100644 index 00000000..58a9d894 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case2/final/Gopkg.toml @@ -0,0 +1,12 @@ + +[[constraint]] + name = "github.com/sdboyer/deptest" + version = "0.8.0" + +[[constraint]] + name = "github.com/sdboyer/deptestdos" + version = "2.0.0" + +[prune] + go-tests = true + unused-packages = true diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case2/initial/foo/bar.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case2/initial/foo/bar.go new file mode 100644 index 00000000..c1ed69fc --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case2/initial/foo/bar.go @@ -0,0 +1,13 @@ +// Copyright 2017 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 foo + +import "github.com/sdboyer/deptest" + +func Foo() deptest.Foo { + var y deptest.Foo + + return y +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case2/initial/main.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case2/initial/main.go new file mode 100644 index 00000000..83a4dfcd --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case2/initial/main.go @@ -0,0 +1,19 @@ +// Copyright 2017 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 main + +import ( + "fmt" + + "github.com/golang/notexist/foo" + "github.com/sdboyer/deptestdos" +) + +func main() { + var x deptestdos.Bar + y := foo.FooFunc() + + fmt.Println(x, y) +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case2/testcase.json b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case2/testcase.json new file mode 100644 index 00000000..df646872 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case2/testcase.json @@ -0,0 +1,13 @@ +{ + "commands": [ + ["init", "-no-examples", "-skip-tools", "-gopath"] + ], + "error-expected": "", + "gopath-initial": { + "github.com/sdboyer/deptest": "v0.8.0" + }, + "vendor-final": [ + "github.com/sdboyer/deptest", + "github.com/sdboyer/deptestdos" + ] +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case3/final/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case3/final/Gopkg.lock new file mode 100644 index 00000000..c4f18284 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case3/final/Gopkg.lock @@ -0,0 +1,20 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + branch = "master" + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "3f4c3bea144e112a69bbe5d8d01c1b09a544253f" + +[[projects]] + name = "github.com/sdboyer/deptestdos" + packages = ["."] + revision = "a0196baa11ea047dd65037287451d36b861b00ea" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "af9a783a5430dabcaaf44683c09e2b729e1c0d61f13bfdf6677c4fd0b41387ca" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case3/final/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case3/final/Gopkg.toml new file mode 100644 index 00000000..20aa1ae8 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case3/final/Gopkg.toml @@ -0,0 +1,8 @@ + +[[constraint]] + branch = "master" + name = "github.com/sdboyer/deptest" + +[prune] + go-tests = true + unused-packages = true diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case3/initial/foo/bar.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case3/initial/foo/bar.go new file mode 100644 index 00000000..c1ed69fc --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case3/initial/foo/bar.go @@ -0,0 +1,13 @@ +// Copyright 2017 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 foo + +import "github.com/sdboyer/deptest" + +func Foo() deptest.Foo { + var y deptest.Foo + + return y +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case3/initial/main.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case3/initial/main.go new file mode 100644 index 00000000..83a4dfcd --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case3/initial/main.go @@ -0,0 +1,19 @@ +// Copyright 2017 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 main + +import ( + "fmt" + + "github.com/golang/notexist/foo" + "github.com/sdboyer/deptestdos" +) + +func main() { + var x deptestdos.Bar + y := foo.FooFunc() + + fmt.Println(x, y) +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case3/testcase.json b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case3/testcase.json new file mode 100644 index 00000000..04cfb832 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case3/testcase.json @@ -0,0 +1,13 @@ +{ + "commands": [ + ["init", "-no-examples", "-skip-tools", "-gopath"] + ], + "error-expected": "", + "gopath-initial": { + "github.com/sdboyer/deptestdos": "a0196baa11ea047dd65037287451d36b861b00ea" + }, + "vendor-final": [ + "github.com/sdboyer/deptest", + "github.com/sdboyer/deptestdos" + ] +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case4/final/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case4/final/Gopkg.lock new file mode 100644 index 00000000..e076e162 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case4/final/Gopkg.lock @@ -0,0 +1,21 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "ff2948a2ac8f538c4ecd55962e919d1e13e74baf" + version = "v1.0.0" + +[[projects]] + name = "github.com/sdboyer/deptestdos" + packages = ["."] + revision = "5c607206be5decd28e6263ffffdcee067266015e" + version = "v2.0.0" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "a6ba2237d28d125b55fc6c86e94e33363f1dfd880d471118d36d7587398c30b4" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case4/final/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case4/final/Gopkg.toml new file mode 100644 index 00000000..2e8f9de1 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case4/final/Gopkg.toml @@ -0,0 +1,12 @@ + +[[constraint]] + name = "github.com/sdboyer/deptest" + version = "1.0.0" + +[[constraint]] + name = "github.com/sdboyer/deptestdos" + version = "2.0.0" + +[prune] + go-tests = true + unused-packages = true diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case4/initial/foo/bar.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case4/initial/foo/bar.go new file mode 100644 index 00000000..c1ed69fc --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case4/initial/foo/bar.go @@ -0,0 +1,13 @@ +// Copyright 2017 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 foo + +import "github.com/sdboyer/deptest" + +func Foo() deptest.Foo { + var y deptest.Foo + + return y +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case4/initial/main.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case4/initial/main.go new file mode 100644 index 00000000..83a4dfcd --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case4/initial/main.go @@ -0,0 +1,19 @@ +// Copyright 2017 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 main + +import ( + "fmt" + + "github.com/golang/notexist/foo" + "github.com/sdboyer/deptestdos" +) + +func main() { + var x deptestdos.Bar + y := foo.FooFunc() + + fmt.Println(x, y) +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case4/testcase.json b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case4/testcase.json new file mode 100644 index 00000000..13cba35a --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/case4/testcase.json @@ -0,0 +1,12 @@ +{ + "commands": [ + ["init", "-no-examples"] + ], + "gopath-initial": { + "github.com/sdboyer/deptestdos": "a0196baa11ea047dd65037287451d36b861b00ea" + }, + "vendor-final": [ + "github.com/sdboyer/deptest", + "github.com/sdboyer/deptestdos" + ] +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case1/README.md b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case1/README.md new file mode 100644 index 00000000..899680ac --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case1/README.md @@ -0,0 +1 @@ +Import glide config at project root. \ No newline at end of file diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case1/final/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case1/final/Gopkg.lock new file mode 100644 index 00000000..7455467c --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case1/final/Gopkg.lock @@ -0,0 +1,26 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/carolynvs/deptest-subpkg" + packages = ["subby"] + revision = "6c41d90f78bb1015696a2ad591debfa8971512d5" + +[[projects]] + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "ff2948a2ac8f538c4ecd55962e919d1e13e74baf" + version = "v1.0.0" + +[[projects]] + name = "github.com/sdboyer/deptestdos" + packages = ["."] + revision = "5c607206be5decd28e6263ffffdcee067266015e" + version = "v2.0.0" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "def34af0f7cd619e1601eb68bdabf399c9b36a79c2081306adefa0ced03d182b" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case1/final/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case1/final/Gopkg.toml new file mode 100644 index 00000000..f0bb3b09 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case1/final/Gopkg.toml @@ -0,0 +1,12 @@ +ignored = [ + "github.com/golang/notexist/samples", + "github.com/sdboyer/dep-test" +] + +[[constraint]] + name = "github.com/sdboyer/deptestdos" + version = "2.0.0" + +[prune] + go-tests = true + unused-packages = true diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case1/initial/glide.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case1/initial/glide.lock new file mode 100644 index 00000000..7a36a4a0 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case1/initial/glide.lock @@ -0,0 +1,14 @@ +hash: 16053c82a71f9bd509b05a4523df6bc418aed2083e4b8bd97a870bbc003256f8 +updated: 2017-03-07T17:02:32.214383898-06:00 +imports: +- name: github.com/sdboyer/deptest + repo: https://github.com/sdboyer/deptest.git + vcs: git + version: ff2948a2ac8f538c4ecd55962e919d1e13e74baf +- name: github.com/sdboyer/deptestdos + version: 5c607206be5decd28e6263ffffdcee067266015e +- name: github.com/carolynvs/deptest-subpkg/subby + version: 6c41d90f78bb1015696a2ad591debfa8971512d5 +testImports: +- name: github.com/golang/lint + version: cb00e5669539f047b2f4c53a421a01b0c8e172c6 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case1/initial/glide.yaml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case1/initial/glide.yaml new file mode 100644 index 00000000..64b8b6b6 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case1/initial/glide.yaml @@ -0,0 +1,21 @@ +package: github.com/golang/notexist +homepage: http://example.com +license: MIT +owners: +- name: Sam Boyer + email: sdboyer@example.com + homepage: http://sdboyer.io +ignore: +- github.com/sdboyer/dep-test +excludeDirs: +- samples +import: +- package: github.com/sdboyer/deptest # This is a transitive dep and will be ignored + repo: https://github.com/sdboyer/deptest.git + vcs: git + version: v1.0.0 +- package: github.com/sdboyer/deptestdos + version: v2.0.0 +- package: github.com/carolynvs/deptest-subpkg/subby +testImport: +- package: github.com/golang/lint diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case1/initial/main.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case1/initial/main.go new file mode 100644 index 00000000..5238b249 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case1/initial/main.go @@ -0,0 +1,17 @@ +// Copyright 2017 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 main + +import ( + "fmt" + + _ "github.com/carolynvs/deptest-subpkg/subby" + "github.com/sdboyer/deptestdos" +) + +func main() { + var x deptestdos.Bar + fmt.Println(x) +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case1/initial/samples/samples.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case1/initial/samples/samples.go new file mode 100644 index 00000000..3e160f22 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case1/initial/samples/samples.go @@ -0,0 +1,12 @@ +// Copyright 2016 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 samples + +import dt "github.com/carolynvs/go-dep-test" + +func Sample1() int { + var x = dt.Thing + return x +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case1/testcase.json b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case1/testcase.json new file mode 100644 index 00000000..cf0d7908 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case1/testcase.json @@ -0,0 +1,15 @@ +{ + "commands": [ + ["init", "-no-examples", "-gopath"] + ], + "error-expected": "", + "gopath-initial": { + "github.com/sdboyer/deptest": "3f4c3bea144e112a69bbe5d8d01c1b09a544253f", + "github.com/sdboyer/deptestdos": "5c607206be5decd28e6263ffffdcee067266015e" + }, + "vendor-final": [ + "github.com/carolynvs/deptest-subpkg", + "github.com/sdboyer/deptest", + "github.com/sdboyer/deptestdos" + ] +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case2/README.md b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case2/README.md new file mode 100644 index 00000000..f6e3eaf4 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case2/README.md @@ -0,0 +1 @@ +Ignore glide config at root when -skip-tools is specified. \ No newline at end of file diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case2/final/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case2/final/Gopkg.lock new file mode 100644 index 00000000..ac445c05 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case2/final/Gopkg.lock @@ -0,0 +1,21 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "3f4c3bea144e112a69bbe5d8d01c1b09a544253f" + version = "v0.8.1" + +[[projects]] + name = "github.com/sdboyer/deptestdos" + packages = ["."] + revision = "5c607206be5decd28e6263ffffdcee067266015e" + version = "v2.0.0" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "1ed417a0bec57ffe988fae1cba8f3d49994fb893394d61844e0b3c96d69573fe" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case2/final/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case2/final/Gopkg.toml new file mode 100644 index 00000000..e3e66aac --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case2/final/Gopkg.toml @@ -0,0 +1,8 @@ + +[[constraint]] + name = "github.com/sdboyer/deptestdos" + version = "2.0.0" + +[prune] + go-tests = true + unused-packages = true diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case2/initial/glide.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case2/initial/glide.lock new file mode 100644 index 00000000..1d295099 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case2/initial/glide.lock @@ -0,0 +1,12 @@ +hash: 16053c82a71f9bd509b05a4523df6bc418aed2083e4b8bd97a870bbc003256f8 +updated: 2017-03-07T17:02:32.214383898-06:00 +imports: +- name: github.com/sdboyer/deptest + repo: https://github.com/sdboyer/deptest.git + vcs: git + version: ff2948a2ac8f538c4ecd55962e919d1e13e74baf +- name: github.com/sdboyer/deptestdos + version: 5c607206be5decd28e6263ffffdcee067266015e +testImports: +- name: github.com/golang/lint + version: cb00e5669539f047b2f4c53a421a01b0c8e172c6 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case2/initial/glide.yaml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case2/initial/glide.yaml new file mode 100644 index 00000000..ee269a39 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case2/initial/glide.yaml @@ -0,0 +1,20 @@ +package: github.com/golang/notexist +homepage: http://example.com +license: MIT +owners: +- name: Sam Boyer + email: sdboyer@example.com + homepage: http://sdboyer.io +ignore: +- github.com/sdboyer/dep-test +excludeDirs: +- samples +import: +- package: github.com/sdboyer/deptest # This is a transitive dep and will be ignored + repo: https://github.com/sdboyer/deptest.git + vcs: git + version: v1.0.0 +- package: github.com/sdboyer/deptestdos + version: v2.0.0 +testImport: +- package: github.com/golang/lint diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case2/initial/main.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case2/initial/main.go new file mode 100644 index 00000000..2b2c7c39 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case2/initial/main.go @@ -0,0 +1,16 @@ +// Copyright 2017 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 main + +import ( + "fmt" + + "github.com/sdboyer/deptestdos" +) + +func main() { + var x deptestdos.Bar + fmt.Println(x) +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case2/testcase.json b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case2/testcase.json new file mode 100644 index 00000000..39c7d874 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case2/testcase.json @@ -0,0 +1,14 @@ +{ + "commands": [ + ["init", "-no-examples", "-skip-tools", "-gopath"] + ], + "error-expected": "", + "gopath-initial": { + "github.com/sdboyer/deptest": "3f4c3bea144e112a69bbe5d8d01c1b09a544253f", + "github.com/sdboyer/deptestdos": "5c607206be5decd28e6263ffffdcee067266015e" + }, + "vendor-final": [ + "github.com/sdboyer/deptest", + "github.com/sdboyer/deptestdos" + ] +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case3/README.md b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case3/README.md new file mode 100644 index 00000000..f46ccd19 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case3/README.md @@ -0,0 +1 @@ +Import glide config in dependencies. \ No newline at end of file diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case3/final/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case3/final/Gopkg.lock new file mode 100644 index 00000000..440c2826 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case3/final/Gopkg.lock @@ -0,0 +1,21 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/carolynvs/deptestglide" + packages = ["."] + revision = "aa7fea6e17ca281c6f210afb93fc3c98ef29a695" + version = "v0.1.1" + +[[projects]] + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "3f4c3bea144e112a69bbe5d8d01c1b09a544253f" + version = "v0.8.1" + +[solve-meta] + analyzer-name = "dep+import" + analyzer-version = 1 + inputs-digest = "07eddb7ff09071bde95b019911e1fb30d91bddabbb23f4c797c6ce61b58cd7be" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case3/final/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case3/final/Gopkg.toml new file mode 100644 index 00000000..6f8b8098 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case3/final/Gopkg.toml @@ -0,0 +1,8 @@ + +[[constraint]] + name = "github.com/carolynvs/deptestglide" + version = "0.1.1" + +[prune] + go-tests = true + unused-packages = true diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case3/initial/main.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case3/initial/main.go new file mode 100644 index 00000000..3e509998 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case3/initial/main.go @@ -0,0 +1,16 @@ +// Copyright 2017 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 main + +import ( + "fmt" + + "github.com/carolynvs/deptestglide" +) + +func main() { + var x = deptestglide.MyFoo + fmt.Println(x) +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case3/testcase.json.ignore b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case3/testcase.json.ignore new file mode 100644 index 00000000..e3e51560 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case3/testcase.json.ignore @@ -0,0 +1,11 @@ +{ + "commands": [ + ["init", "-no-examples"] + ], + "error-expected": "", + "gopath-initial": {}, + "vendor-final": [ + "github.com/carolynvs/deptestglide", + "github.com/sdboyer/deptest" + ] +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case4/README.md b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case4/README.md new file mode 100644 index 00000000..912e4084 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case4/README.md @@ -0,0 +1 @@ +Ignore glide config if glide.yaml is malformed and cannot be parsed correctly. diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case4/final/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case4/final/Gopkg.lock new file mode 100644 index 00000000..1aadf7f9 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case4/final/Gopkg.lock @@ -0,0 +1,21 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "ff2948a2ac8f538c4ecd55962e919d1e13e74baf" + version = "v1.0.0" + +[[projects]] + name = "github.com/sdboyer/deptestdos" + packages = ["."] + revision = "5c607206be5decd28e6263ffffdcee067266015e" + version = "v2.0.0" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "1ed417a0bec57ffe988fae1cba8f3d49994fb893394d61844e0b3c96d69573fe" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case4/final/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case4/final/Gopkg.toml new file mode 100644 index 00000000..e3e66aac --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case4/final/Gopkg.toml @@ -0,0 +1,8 @@ + +[[constraint]] + name = "github.com/sdboyer/deptestdos" + version = "2.0.0" + +[prune] + go-tests = true + unused-packages = true diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case4/initial/glide.yaml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case4/initial/glide.yaml new file mode 100644 index 00000000..a9c8e891 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case4/initial/glide.yaml @@ -0,0 +1,20 @@ +'package: github.com/golang/notexist +homepage: http://example.com +license: MIT +owners: +- name: Sam Boyer + email: sdboyer@example.com + homepage: http://sdboyer.io +ignore: +- github.com/sdboyer/dep-test +excludeDirs: +- samples +import: +- package: github.com/sdboyer/deptest # This is a transitive dep and will be ignored + repo: https://github.com/sdboyer/deptest.git + vcs: git + version: v1.0.0 +- package: github.com/sdboyer/deptestdos + version: v2.0.0 +testImport: +- package: github.com/golang/lint diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case4/initial/main.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case4/initial/main.go new file mode 100644 index 00000000..2b2c7c39 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case4/initial/main.go @@ -0,0 +1,16 @@ +// Copyright 2017 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 main + +import ( + "fmt" + + "github.com/sdboyer/deptestdos" +) + +func main() { + var x deptestdos.Bar + fmt.Println(x) +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case4/testcase.json b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case4/testcase.json new file mode 100644 index 00000000..85a05ed6 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glide/case4/testcase.json @@ -0,0 +1,14 @@ +{ + "commands": [ + ["init", "-no-examples"] + ], + "error-expected": "", + "gopath-initial": { + "github.com/sdboyer/deptest": "3f4c3bea144e112a69bbe5d8d01c1b09a544253f", + "github.com/sdboyer/deptestdos": "5c607206be5decd28e6263ffffdcee067266015e" + }, + "vendor-final": [ + "github.com/sdboyer/deptest", + "github.com/sdboyer/deptestdos" + ] +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glock/case1/final/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glock/case1/final/Gopkg.lock new file mode 100644 index 00000000..ac445c05 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glock/case1/final/Gopkg.lock @@ -0,0 +1,21 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "3f4c3bea144e112a69bbe5d8d01c1b09a544253f" + version = "v0.8.1" + +[[projects]] + name = "github.com/sdboyer/deptestdos" + packages = ["."] + revision = "5c607206be5decd28e6263ffffdcee067266015e" + version = "v2.0.0" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "1ed417a0bec57ffe988fae1cba8f3d49994fb893394d61844e0b3c96d69573fe" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glock/case1/final/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glock/case1/final/Gopkg.toml new file mode 100644 index 00000000..e3e66aac --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glock/case1/final/Gopkg.toml @@ -0,0 +1,8 @@ + +[[constraint]] + name = "github.com/sdboyer/deptestdos" + version = "2.0.0" + +[prune] + go-tests = true + unused-packages = true diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glock/case1/initial/GLOCKFILE b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glock/case1/initial/GLOCKFILE new file mode 100644 index 00000000..27f499a4 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glock/case1/initial/GLOCKFILE @@ -0,0 +1,3 @@ +cmd github.com/golang/lint +github.com/sdboyer/deptest 3f4c3bea144e112a69bbe5d8d01c1b09a544253f +github.com/sdboyer/deptestdos 5c607206be5decd28e6263ffffdcee067266015e diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glock/case1/initial/main.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glock/case1/initial/main.go new file mode 100644 index 00000000..2b2c7c39 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glock/case1/initial/main.go @@ -0,0 +1,16 @@ +// Copyright 2017 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 main + +import ( + "fmt" + + "github.com/sdboyer/deptestdos" +) + +func main() { + var x deptestdos.Bar + fmt.Println(x) +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glock/case1/testcase.json b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glock/case1/testcase.json new file mode 100644 index 00000000..017dc4cd --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/glock/case1/testcase.json @@ -0,0 +1,13 @@ +{ + "commands": [ + ["init", "-no-examples"] + ], + "error-expected": "", + "gopath-initial": { + "github.com/sdboyer/deptest": "3f4c3bea144e112a69bbe5d8d01c1b09a544253f" + }, + "vendor-final": [ + "github.com/sdboyer/deptest", + "github.com/sdboyer/deptestdos" + ] +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/godep/case1/final/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/godep/case1/final/Gopkg.lock new file mode 100644 index 00000000..ac445c05 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/godep/case1/final/Gopkg.lock @@ -0,0 +1,21 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "3f4c3bea144e112a69bbe5d8d01c1b09a544253f" + version = "v0.8.1" + +[[projects]] + name = "github.com/sdboyer/deptestdos" + packages = ["."] + revision = "5c607206be5decd28e6263ffffdcee067266015e" + version = "v2.0.0" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "1ed417a0bec57ffe988fae1cba8f3d49994fb893394d61844e0b3c96d69573fe" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/godep/case1/final/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/godep/case1/final/Gopkg.toml new file mode 100644 index 00000000..e3e66aac --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/godep/case1/final/Gopkg.toml @@ -0,0 +1,8 @@ + +[[constraint]] + name = "github.com/sdboyer/deptestdos" + version = "2.0.0" + +[prune] + go-tests = true + unused-packages = true diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/godep/case1/initial/Godeps/Godeps.json b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/godep/case1/initial/Godeps/Godeps.json new file mode 100644 index 00000000..ee87370e --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/godep/case1/initial/Godeps/Godeps.json @@ -0,0 +1,17 @@ +{ + "ImportPath": "github.com/golang/notexist", + "GoVersion": "go1.8", + "GodepVersion": "vXYZ", + "Deps": [ + { + "ImportPath": "github.com/sdboyer/deptest", + "Comment": "master", + "Rev": "3f4c3bea144e112a69bbe5d8d01c1b09a544253f" + }, + { + "ImportPath": "github.com/sdboyer/deptestdos", + "Comment": "v2.0.0", + "Rev": "5c607206be5decd28e6263ffffdcee067266015e" + } + ] +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/godep/case1/initial/main.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/godep/case1/initial/main.go new file mode 100644 index 00000000..2b2c7c39 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/godep/case1/initial/main.go @@ -0,0 +1,16 @@ +// Copyright 2017 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 main + +import ( + "fmt" + + "github.com/sdboyer/deptestdos" +) + +func main() { + var x deptestdos.Bar + fmt.Println(x) +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/godep/case1/testcase.json b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/godep/case1/testcase.json new file mode 100644 index 00000000..017dc4cd --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/godep/case1/testcase.json @@ -0,0 +1,13 @@ +{ + "commands": [ + ["init", "-no-examples"] + ], + "error-expected": "", + "gopath-initial": { + "github.com/sdboyer/deptest": "3f4c3bea144e112a69bbe5d8d01c1b09a544253f" + }, + "vendor-final": [ + "github.com/sdboyer/deptest", + "github.com/sdboyer/deptestdos" + ] +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/govend/case1/final/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/govend/case1/final/Gopkg.lock new file mode 100644 index 00000000..ac445c05 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/govend/case1/final/Gopkg.lock @@ -0,0 +1,21 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "3f4c3bea144e112a69bbe5d8d01c1b09a544253f" + version = "v0.8.1" + +[[projects]] + name = "github.com/sdboyer/deptestdos" + packages = ["."] + revision = "5c607206be5decd28e6263ffffdcee067266015e" + version = "v2.0.0" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "1ed417a0bec57ffe988fae1cba8f3d49994fb893394d61844e0b3c96d69573fe" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/govend/case1/final/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/govend/case1/final/Gopkg.toml new file mode 100644 index 00000000..e3e66aac --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/govend/case1/final/Gopkg.toml @@ -0,0 +1,8 @@ + +[[constraint]] + name = "github.com/sdboyer/deptestdos" + version = "2.0.0" + +[prune] + go-tests = true + unused-packages = true diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/govend/case1/initial/main.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/govend/case1/initial/main.go new file mode 100644 index 00000000..2b2c7c39 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/govend/case1/initial/main.go @@ -0,0 +1,16 @@ +// Copyright 2017 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 main + +import ( + "fmt" + + "github.com/sdboyer/deptestdos" +) + +func main() { + var x deptestdos.Bar + fmt.Println(x) +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/govend/case1/initial/vendor.yml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/govend/case1/initial/vendor.yml new file mode 100644 index 00000000..c5c933f6 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/govend/case1/initial/vendor.yml @@ -0,0 +1,5 @@ +vendors: +- path: github.com/sdboyer/deptest + rev: 3f4c3bea144e112a69bbe5d8d01c1b09a544253f +- path: github.com/sdboyer/deptestdos + rev: 5c607206be5decd28e6263ffffdcee067266015e diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/govend/case1/testcase.json b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/govend/case1/testcase.json new file mode 100644 index 00000000..017dc4cd --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/govend/case1/testcase.json @@ -0,0 +1,13 @@ +{ + "commands": [ + ["init", "-no-examples"] + ], + "error-expected": "", + "gopath-initial": { + "github.com/sdboyer/deptest": "3f4c3bea144e112a69bbe5d8d01c1b09a544253f" + }, + "vendor-final": [ + "github.com/sdboyer/deptest", + "github.com/sdboyer/deptestdos" + ] +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/govendor/case1/README.md b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/govendor/case1/README.md new file mode 100644 index 00000000..640eb069 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/govendor/case1/README.md @@ -0,0 +1 @@ +Import govendor config in vendor dir. diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/govendor/case1/final/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/govendor/case1/final/Gopkg.lock new file mode 100644 index 00000000..529e4889 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/govendor/case1/final/Gopkg.lock @@ -0,0 +1,21 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "3f4c3bea144e112a69bbe5d8d01c1b09a544253f" + version = "v0.8.1" + +[[projects]] + name = "github.com/sdboyer/deptestdos" + packages = ["."] + revision = "5c607206be5decd28e6263ffffdcee067266015e" + version = "v2.0.0" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "9cc662f2e1b80c8df205d9d667fe2c47825a06961ceae378f44a8290d01dd359" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/govendor/case1/final/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/govendor/case1/final/Gopkg.toml new file mode 100644 index 00000000..012e5631 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/govendor/case1/final/Gopkg.toml @@ -0,0 +1,12 @@ +ignored = [ + "github.com/golang/notexist/samples*", + "github.com/sdboyer/dep-test*" +] + +[[constraint]] + name = "github.com/sdboyer/deptestdos" + version = "2.0.0" + +[prune] + go-tests = true + unused-packages = true diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/govendor/case1/initial/main.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/govendor/case1/initial/main.go new file mode 100644 index 00000000..2b2c7c39 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/govendor/case1/initial/main.go @@ -0,0 +1,16 @@ +// Copyright 2017 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 main + +import ( + "fmt" + + "github.com/sdboyer/deptestdos" +) + +func main() { + var x deptestdos.Bar + fmt.Println(x) +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/govendor/case1/initial/samples/samples.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/govendor/case1/initial/samples/samples.go new file mode 100644 index 00000000..3e160f22 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/govendor/case1/initial/samples/samples.go @@ -0,0 +1,12 @@ +// Copyright 2016 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 samples + +import dt "github.com/carolynvs/go-dep-test" + +func Sample1() int { + var x = dt.Thing + return x +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/govendor/case1/testcase.json b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/govendor/case1/testcase.json new file mode 100644 index 00000000..e1197654 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/govendor/case1/testcase.json @@ -0,0 +1,14 @@ +{ + "commands": [ + ["init", "-no-examples", "-gopath"] + ], + "error-expected": "", + "gopath-initial": { + "github.com/sdboyer/deptest": "3f4c3bea144e112a69bbe5d8d01c1b09a544253f", + "github.com/sdboyer/deptestdos": "5c607206be5decd28e6263ffffdcee067266015e" + }, + "vendor-final": [ + "github.com/sdboyer/deptest", + "github.com/sdboyer/deptestdos" + ] +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/gvt/case1/final/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/gvt/case1/final/Gopkg.lock new file mode 100644 index 00000000..1eb5e5e8 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/gvt/case1/final/Gopkg.lock @@ -0,0 +1,28 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "3f4c3bea144e112a69bbe5d8d01c1b09a544253f" + source = "https://github.com/carolynvs/deptest" + version = "v0.8.1" + +[[projects]] + name = "github.com/sdboyer/deptestdos" + packages = ["."] + revision = "5c607206be5decd28e6263ffffdcee067266015e" + version = "v2.0.0" + +[[projects]] + branch = "v2" + name = "gopkg.in/yaml.v2" + packages = ["."] + revision = "f7716cbe52baa25d2e9b0d0da546fcf909fc16b4" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "d1681978cbca0e845950451461e0d69b58c5e896d9fd10ec5c159a4db3175161" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/gvt/case1/final/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/gvt/case1/final/Gopkg.toml new file mode 100644 index 00000000..de6c9bd2 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/gvt/case1/final/Gopkg.toml @@ -0,0 +1,16 @@ + +[[constraint]] + name = "github.com/sdboyer/deptest" + source = "https://github.com/carolynvs/deptest" + +[[constraint]] + name = "github.com/sdboyer/deptestdos" + version = "2.0.0" + +[[constraint]] + branch = "v2" + name = "gopkg.in/yaml.v2" + +[prune] + go-tests = true + unused-packages = true diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/gvt/case1/initial/main.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/gvt/case1/initial/main.go new file mode 100644 index 00000000..6d893af2 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/gvt/case1/initial/main.go @@ -0,0 +1,20 @@ +// Copyright 2017 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 main + +import ( + "fmt" + + "github.com/sdboyer/deptest" + "github.com/sdboyer/deptestdos" + "gopkg.in/yaml.v2" +) + +func main() { + var a deptestdos.Bar + var b yaml.MapItem + var c deptest.Foo + fmt.Println(a, b, c) +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/gvt/case1/testcase.json b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/gvt/case1/testcase.json new file mode 100644 index 00000000..017dc4cd --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/gvt/case1/testcase.json @@ -0,0 +1,13 @@ +{ + "commands": [ + ["init", "-no-examples"] + ], + "error-expected": "", + "gopath-initial": { + "github.com/sdboyer/deptest": "3f4c3bea144e112a69bbe5d8d01c1b09a544253f" + }, + "vendor-final": [ + "github.com/sdboyer/deptest", + "github.com/sdboyer/deptestdos" + ] +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/manifest-exists/final/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/manifest-exists/final/Gopkg.toml new file mode 100644 index 00000000..e69de29b diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/manifest-exists/initial/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/manifest-exists/initial/Gopkg.toml new file mode 100644 index 00000000..e69de29b diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/manifest-exists/testcase.json b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/manifest-exists/testcase.json new file mode 100644 index 00000000..29996118 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/manifest-exists/testcase.json @@ -0,0 +1,7 @@ +{ + "commands": [ + ["init"] + ], + "error-expected": "init aborted: manifest already exists", + "vendor-final": [] +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/relative_path/final/project_dir/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/relative_path/final/project_dir/Gopkg.lock new file mode 100644 index 00000000..f9f6c4c7 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/relative_path/final/project_dir/Gopkg.lock @@ -0,0 +1,14 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + +memo = "af9a783a5430dabcaaf44683c09e2b729e1c0d61f13bfdf6677c4fd0b41387ca" + +[[projects]] + branch = "master" + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "3f4c3bea144e112a69bbe5d8d01c1b09a544253f" + +[[projects]] + name = "github.com/sdboyer/deptestdos" + packages = ["."] + revision = "a0196baa11ea047dd65037287451d36b861b00ea" diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/relative_path/final/project_dir/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/relative_path/final/project_dir/Gopkg.toml new file mode 100644 index 00000000..20aa1ae8 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/relative_path/final/project_dir/Gopkg.toml @@ -0,0 +1,8 @@ + +[[constraint]] + branch = "master" + name = "github.com/sdboyer/deptest" + +[prune] + go-tests = true + unused-packages = true diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/relative_path/initial/project_dir/foo/bar.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/relative_path/initial/project_dir/foo/bar.go new file mode 100644 index 00000000..c1ed69fc --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/relative_path/initial/project_dir/foo/bar.go @@ -0,0 +1,13 @@ +// Copyright 2017 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 foo + +import "github.com/sdboyer/deptest" + +func Foo() deptest.Foo { + var y deptest.Foo + + return y +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/relative_path/initial/project_dir/main.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/relative_path/initial/project_dir/main.go new file mode 100644 index 00000000..150e0bd3 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/relative_path/initial/project_dir/main.go @@ -0,0 +1,18 @@ +// Copyright 2017 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 main + +import ( + "fmt" + + "github.com/sdboyer/deptestdos" +) + +func main() { + var x deptestdos.Bar + y := foo.FooFunc() + + fmt.Println(x, y) +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/relative_path/testcase.json b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/relative_path/testcase.json new file mode 100644 index 00000000..6fa477b5 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/relative_path/testcase.json @@ -0,0 +1,7 @@ +{ + "commands": [ + ["init", "-skip-tools", "project_dir"] + ], + "error-expected": "", + "init-path": "project_dir" +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/skip-hidden/final/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/skip-hidden/final/Gopkg.lock new file mode 100644 index 00000000..c7f497e7 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/skip-hidden/final/Gopkg.lock @@ -0,0 +1,15 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "ff2948a2ac8f538c4ecd55962e919d1e13e74baf" + version = "v1.0.0" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "14b07b05e0f01051b03887ab2bf80b516bc5510ea92f75f76c894b1745d8850c" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/skip-hidden/final/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/skip-hidden/final/Gopkg.toml new file mode 100644 index 00000000..51a3481d --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/skip-hidden/final/Gopkg.toml @@ -0,0 +1,8 @@ + +[[constraint]] + name = "github.com/sdboyer/deptest" + version = "1.0.0" + +[prune] + go-tests = true + unused-packages = true diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/skip-hidden/initial/.foo/main.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/skip-hidden/initial/.foo/main.go new file mode 100644 index 00000000..83a4dfcd --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/skip-hidden/initial/.foo/main.go @@ -0,0 +1,19 @@ +// Copyright 2017 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 main + +import ( + "fmt" + + "github.com/golang/notexist/foo" + "github.com/sdboyer/deptestdos" +) + +func main() { + var x deptestdos.Bar + y := foo.FooFunc() + + fmt.Println(x, y) +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/skip-hidden/initial/_foo/main.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/skip-hidden/initial/_foo/main.go new file mode 100644 index 00000000..83a4dfcd --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/skip-hidden/initial/_foo/main.go @@ -0,0 +1,19 @@ +// Copyright 2017 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 main + +import ( + "fmt" + + "github.com/golang/notexist/foo" + "github.com/sdboyer/deptestdos" +) + +func main() { + var x deptestdos.Bar + y := foo.FooFunc() + + fmt.Println(x, y) +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/skip-hidden/initial/lib.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/skip-hidden/initial/lib.go new file mode 100644 index 00000000..c1ed69fc --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/skip-hidden/initial/lib.go @@ -0,0 +1,13 @@ +// Copyright 2017 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 foo + +import "github.com/sdboyer/deptest" + +func Foo() deptest.Foo { + var y deptest.Foo + + return y +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/skip-hidden/initial/testdata/main.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/skip-hidden/initial/testdata/main.go new file mode 100644 index 00000000..83a4dfcd --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/skip-hidden/initial/testdata/main.go @@ -0,0 +1,19 @@ +// Copyright 2017 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 main + +import ( + "fmt" + + "github.com/golang/notexist/foo" + "github.com/sdboyer/deptestdos" +) + +func main() { + var x deptestdos.Bar + y := foo.FooFunc() + + fmt.Println(x, y) +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/skip-hidden/testcase.json b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/skip-hidden/testcase.json new file mode 100644 index 00000000..0283a883 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/skip-hidden/testcase.json @@ -0,0 +1,9 @@ +{ + "commands": [ + ["init", "-no-examples", "-skip-tools"] + ], + "error-expected": "", + "vendor-final": [ + "github.com/sdboyer/deptest" + ] +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/usage/with_h_flag/testcase.json b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/usage/with_h_flag/testcase.json new file mode 100644 index 00000000..b954a482 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/usage/with_h_flag/testcase.json @@ -0,0 +1,6 @@ +{ + "commands": [ + ["init", "-h"] + ], + "error-expected": "Usage: dep init [root]" +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/usage/with_not_defined_flag/testcase.json b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/usage/with_not_defined_flag/testcase.json new file mode 100644 index 00000000..3d3591e9 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/usage/with_not_defined_flag/testcase.json @@ -0,0 +1,6 @@ +{ + "commands": [ + ["init", "-not-defined-flag"] + ], + "error-expected": "flag provided but not defined: -not-defined-flag\nUsage: dep init [root]" +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/vndr/case1/final/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/vndr/case1/final/Gopkg.lock new file mode 100644 index 00000000..ac445c05 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/vndr/case1/final/Gopkg.lock @@ -0,0 +1,21 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "3f4c3bea144e112a69bbe5d8d01c1b09a544253f" + version = "v0.8.1" + +[[projects]] + name = "github.com/sdboyer/deptestdos" + packages = ["."] + revision = "5c607206be5decd28e6263ffffdcee067266015e" + version = "v2.0.0" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "1ed417a0bec57ffe988fae1cba8f3d49994fb893394d61844e0b3c96d69573fe" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/vndr/case1/final/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/vndr/case1/final/Gopkg.toml new file mode 100644 index 00000000..e3e66aac --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/vndr/case1/final/Gopkg.toml @@ -0,0 +1,8 @@ + +[[constraint]] + name = "github.com/sdboyer/deptestdos" + version = "2.0.0" + +[prune] + go-tests = true + unused-packages = true diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/vndr/case1/initial/main.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/vndr/case1/initial/main.go new file mode 100644 index 00000000..2b2c7c39 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/vndr/case1/initial/main.go @@ -0,0 +1,16 @@ +// Copyright 2017 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 main + +import ( + "fmt" + + "github.com/sdboyer/deptestdos" +) + +func main() { + var x deptestdos.Bar + fmt.Println(x) +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/vndr/case1/initial/vendor.conf b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/vndr/case1/initial/vendor.conf new file mode 100644 index 00000000..d91f18b3 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/vndr/case1/initial/vendor.conf @@ -0,0 +1,3 @@ +# Comment on its own line +github.com/sdboyer/deptest 3f4c3bea144e112a69bbe5d8d01c1b09a544253f https://github.com/sdboyer/deptest.git +github.com/sdboyer/deptestdos v2.0.0 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/vndr/case1/testcase.json b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/vndr/case1/testcase.json new file mode 100644 index 00000000..017dc4cd --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/init/vndr/case1/testcase.json @@ -0,0 +1,13 @@ +{ + "commands": [ + ["init", "-no-examples"] + ], + "error-expected": "", + "gopath-initial": { + "github.com/sdboyer/deptest": "3f4c3bea144e112a69bbe5d8d01c1b09a544253f" + }, + "vendor-final": [ + "github.com/sdboyer/deptest", + "github.com/sdboyer/deptestdos" + ] +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/dot/final/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/dot/final/Gopkg.lock new file mode 100644 index 00000000..77278d07 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/dot/final/Gopkg.lock @@ -0,0 +1,21 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "ff2948a2ac8f538c4ecd55962e919d1e13e74baf" + version = "v0.8.0" + +[[projects]] + name = "github.com/sdboyer/deptestdos" + packages = ["."] + revision = "5c607206be5decd28e6263ffffdcee067266015e" + version = "v2.0.0" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "1b381263a360eafafe3ef7f9be626672668d17250a3c9a8debd169d1b5e2eebb" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/dot/final/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/dot/final/Gopkg.toml new file mode 100644 index 00000000..94deb714 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/dot/final/Gopkg.toml @@ -0,0 +1,3 @@ +[[constraint]] + name = "github.com/sdboyer/deptest" + version = "^0.8.0" diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/dot/initial/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/dot/initial/Gopkg.lock new file mode 100644 index 00000000..04268862 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/dot/initial/Gopkg.lock @@ -0,0 +1,13 @@ +memo = "9a5243dd3fa20feeaa20398e7283d6c566532e2af1aae279a010df34793761c5" + +[[projects]] + name = "github.com/sdboyer/deptest" + version = "v0.8.0" + revision = "ff2948a2ac8f538c4ecd55962e919d1e13e74baf" + packages = ["."] + +[[projects]] + name = "github.com/sdboyer/deptestdos" + version = "v2.0.0" + revision = "5c607206be5decd28e6263ffffdcee067266015e" + packages = ["."] diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/dot/initial/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/dot/initial/Gopkg.toml new file mode 100644 index 00000000..94deb714 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/dot/initial/Gopkg.toml @@ -0,0 +1,3 @@ +[[constraint]] + name = "github.com/sdboyer/deptest" + version = "^0.8.0" diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/dot/initial/main.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/dot/initial/main.go new file mode 100644 index 00000000..2eae5b51 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/dot/initial/main.go @@ -0,0 +1,18 @@ +// Copyright 2016 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 main + +import ( + "github.com/sdboyer/deptest" + "github.com/sdboyer/deptestdos" +) + +func main() { + err := nil + if err != nil { + deptest.Map["yo yo!"] + } + deptestdos.diMeLo("whatev") +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/dot/stdout.txt b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/dot/stdout.txt new file mode 100644 index 00000000..2dbc7914 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/dot/stdout.txt @@ -0,0 +1,9 @@ +digraph { + node [shape=box]; + 388407825 [label="github.com/golang/notexist"]; + 2304687900 [label="github.com/sdboyer/deptest\nv0.8.0"]; + 2659405890 [label="github.com/sdboyer/deptestdos\nv2.0.0"]; + 388407825 -> 2304687900; + 388407825 -> 2659405890; + 2659405890 -> 2304687900; +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/dot/testcase.json b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/dot/testcase.json new file mode 100644 index 00000000..9634c398 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/dot/testcase.json @@ -0,0 +1,11 @@ +{ + "commands": [ + ["ensure"], + ["status", "-dot"] + ], + "error-expected": "", + "vendor-final": [ + "github.com/sdboyer/deptest", + "github.com/sdboyer/deptestdos" + ] +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/json/final/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/json/final/Gopkg.lock new file mode 100644 index 00000000..77278d07 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/json/final/Gopkg.lock @@ -0,0 +1,21 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "ff2948a2ac8f538c4ecd55962e919d1e13e74baf" + version = "v0.8.0" + +[[projects]] + name = "github.com/sdboyer/deptestdos" + packages = ["."] + revision = "5c607206be5decd28e6263ffffdcee067266015e" + version = "v2.0.0" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "1b381263a360eafafe3ef7f9be626672668d17250a3c9a8debd169d1b5e2eebb" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/json/final/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/json/final/Gopkg.toml new file mode 100644 index 00000000..94deb714 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/json/final/Gopkg.toml @@ -0,0 +1,3 @@ +[[constraint]] + name = "github.com/sdboyer/deptest" + version = "^0.8.0" diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/json/initial/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/json/initial/Gopkg.lock new file mode 100644 index 00000000..04268862 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/json/initial/Gopkg.lock @@ -0,0 +1,13 @@ +memo = "9a5243dd3fa20feeaa20398e7283d6c566532e2af1aae279a010df34793761c5" + +[[projects]] + name = "github.com/sdboyer/deptest" + version = "v0.8.0" + revision = "ff2948a2ac8f538c4ecd55962e919d1e13e74baf" + packages = ["."] + +[[projects]] + name = "github.com/sdboyer/deptestdos" + version = "v2.0.0" + revision = "5c607206be5decd28e6263ffffdcee067266015e" + packages = ["."] diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/json/initial/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/json/initial/Gopkg.toml new file mode 100644 index 00000000..94deb714 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/json/initial/Gopkg.toml @@ -0,0 +1,3 @@ +[[constraint]] + name = "github.com/sdboyer/deptest" + version = "^0.8.0" diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/json/initial/main.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/json/initial/main.go new file mode 100644 index 00000000..2eae5b51 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/json/initial/main.go @@ -0,0 +1,18 @@ +// Copyright 2016 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 main + +import ( + "github.com/sdboyer/deptest" + "github.com/sdboyer/deptestdos" +) + +func main() { + err := nil + if err != nil { + deptest.Map["yo yo!"] + } + deptestdos.diMeLo("whatev") +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/json/stdout.txt b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/json/stdout.txt new file mode 100644 index 00000000..3b907c18 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/json/stdout.txt @@ -0,0 +1 @@ +[{"ProjectRoot":"github.com/sdboyer/deptest","Constraint":"^0.8.0","Version":"v0.8.0","Revision":"ff2948a2ac8f538c4ecd55962e919d1e13e74baf","Latest":"v0.8.1","PackageCount":1},{"ProjectRoot":"github.com/sdboyer/deptestdos","Constraint":"v2.0.0","Version":"v2.0.0","Revision":"5c607206be5decd28e6263ffffdcee067266015e","Latest":"v2.0.0","PackageCount":1}] diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/json/testcase.json b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/json/testcase.json new file mode 100644 index 00000000..9e1a0643 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/json/testcase.json @@ -0,0 +1,11 @@ +{ + "commands": [ + ["ensure"], + ["status", "-json"] + ], + "error-expected": "", + "vendor-final": [ + "github.com/sdboyer/deptest", + "github.com/sdboyer/deptestdos" + ] +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/table/final/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/table/final/Gopkg.lock new file mode 100644 index 00000000..77278d07 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/table/final/Gopkg.lock @@ -0,0 +1,21 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "ff2948a2ac8f538c4ecd55962e919d1e13e74baf" + version = "v0.8.0" + +[[projects]] + name = "github.com/sdboyer/deptestdos" + packages = ["."] + revision = "5c607206be5decd28e6263ffffdcee067266015e" + version = "v2.0.0" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "1b381263a360eafafe3ef7f9be626672668d17250a3c9a8debd169d1b5e2eebb" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/table/final/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/table/final/Gopkg.toml new file mode 100644 index 00000000..94deb714 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/table/final/Gopkg.toml @@ -0,0 +1,3 @@ +[[constraint]] + name = "github.com/sdboyer/deptest" + version = "^0.8.0" diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/table/initial/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/table/initial/Gopkg.lock new file mode 100644 index 00000000..04268862 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/table/initial/Gopkg.lock @@ -0,0 +1,13 @@ +memo = "9a5243dd3fa20feeaa20398e7283d6c566532e2af1aae279a010df34793761c5" + +[[projects]] + name = "github.com/sdboyer/deptest" + version = "v0.8.0" + revision = "ff2948a2ac8f538c4ecd55962e919d1e13e74baf" + packages = ["."] + +[[projects]] + name = "github.com/sdboyer/deptestdos" + version = "v2.0.0" + revision = "5c607206be5decd28e6263ffffdcee067266015e" + packages = ["."] diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/table/initial/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/table/initial/Gopkg.toml new file mode 100644 index 00000000..94deb714 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/table/initial/Gopkg.toml @@ -0,0 +1,3 @@ +[[constraint]] + name = "github.com/sdboyer/deptest" + version = "^0.8.0" diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/table/initial/main.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/table/initial/main.go new file mode 100644 index 00000000..2eae5b51 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/table/initial/main.go @@ -0,0 +1,18 @@ +// Copyright 2016 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 main + +import ( + "github.com/sdboyer/deptest" + "github.com/sdboyer/deptestdos" +) + +func main() { + err := nil + if err != nil { + deptest.Map["yo yo!"] + } + deptestdos.diMeLo("whatev") +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/table/stdout.txt b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/table/stdout.txt new file mode 100644 index 00000000..46de9f00 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/table/stdout.txt @@ -0,0 +1,3 @@ +PROJECT CONSTRAINT VERSION REVISION LATEST PKGS USED +github.com/sdboyer/deptest ^0.8.0 v0.8.0 ff2948a v0.8.1 1 +github.com/sdboyer/deptestdos v2.0.0 v2.0.0 5c60720 v2.0.0 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/table/testcase.json b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/table/testcase.json new file mode 100644 index 00000000..e1f1eade --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/table/testcase.json @@ -0,0 +1,11 @@ +{ + "commands": [ + ["ensure"], + ["status"] + ], + "error-expected": "", + "vendor-final": [ + "github.com/sdboyer/deptest", + "github.com/sdboyer/deptestdos" + ] +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/template/final/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/template/final/Gopkg.lock new file mode 100644 index 00000000..77278d07 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/template/final/Gopkg.lock @@ -0,0 +1,21 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "ff2948a2ac8f538c4ecd55962e919d1e13e74baf" + version = "v0.8.0" + +[[projects]] + name = "github.com/sdboyer/deptestdos" + packages = ["."] + revision = "5c607206be5decd28e6263ffffdcee067266015e" + version = "v2.0.0" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "1b381263a360eafafe3ef7f9be626672668d17250a3c9a8debd169d1b5e2eebb" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/template/final/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/template/final/Gopkg.toml new file mode 100644 index 00000000..94deb714 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/template/final/Gopkg.toml @@ -0,0 +1,3 @@ +[[constraint]] + name = "github.com/sdboyer/deptest" + version = "^0.8.0" diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/template/initial/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/template/initial/Gopkg.lock new file mode 100644 index 00000000..04268862 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/template/initial/Gopkg.lock @@ -0,0 +1,13 @@ +memo = "9a5243dd3fa20feeaa20398e7283d6c566532e2af1aae279a010df34793761c5" + +[[projects]] + name = "github.com/sdboyer/deptest" + version = "v0.8.0" + revision = "ff2948a2ac8f538c4ecd55962e919d1e13e74baf" + packages = ["."] + +[[projects]] + name = "github.com/sdboyer/deptestdos" + version = "v2.0.0" + revision = "5c607206be5decd28e6263ffffdcee067266015e" + packages = ["."] diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/template/initial/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/template/initial/Gopkg.toml new file mode 100644 index 00000000..94deb714 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/template/initial/Gopkg.toml @@ -0,0 +1,3 @@ +[[constraint]] + name = "github.com/sdboyer/deptest" + version = "^0.8.0" diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/template/initial/main.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/template/initial/main.go new file mode 100644 index 00000000..2eae5b51 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/template/initial/main.go @@ -0,0 +1,18 @@ +// Copyright 2016 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 main + +import ( + "github.com/sdboyer/deptest" + "github.com/sdboyer/deptestdos" +) + +func main() { + err := nil + if err != nil { + deptest.Map["yo yo!"] + } + deptestdos.diMeLo("whatev") +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/template/stdout.txt b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/template/stdout.txt new file mode 100644 index 00000000..c27320c8 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/template/stdout.txt @@ -0,0 +1,2 @@ +PROJECT: github.com/sdboyer/deptest, VERSION: v0.8.0 +PROJECT: github.com/sdboyer/deptestdos, VERSION: v2.0.0 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/template/testcase.json b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/template/testcase.json new file mode 100644 index 00000000..c208fbf6 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/case1/template/testcase.json @@ -0,0 +1,11 @@ +{ + "commands": [ + ["ensure"], + ["status", "-f=PROJECT: {{.ProjectRoot}}, VERSION: {{.Version}}\n"] + ], + "error-expected": "", + "vendor-final": [ + "github.com/sdboyer/deptest", + "github.com/sdboyer/deptestdos" + ] +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/ignore_lock_mismatch/final/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/ignore_lock_mismatch/final/Gopkg.lock new file mode 100644 index 00000000..bef2d009 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/ignore_lock_mismatch/final/Gopkg.lock @@ -0,0 +1,9 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "ab4fef131ee828e96ba67d31a7d690bd5f2f42040c6766b1b12fe856f87e0ff7" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/ignore_lock_mismatch/final/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/ignore_lock_mismatch/final/Gopkg.toml new file mode 100644 index 00000000..418ac251 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/ignore_lock_mismatch/final/Gopkg.toml @@ -0,0 +1,2 @@ +ignored = ["github.com/sdboyer/deptestdos"] + diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/ignore_lock_mismatch/initial/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/ignore_lock_mismatch/initial/Gopkg.lock new file mode 100644 index 00000000..bef2d009 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/ignore_lock_mismatch/initial/Gopkg.lock @@ -0,0 +1,9 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "ab4fef131ee828e96ba67d31a7d690bd5f2f42040c6766b1b12fe856f87e0ff7" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/ignore_lock_mismatch/initial/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/ignore_lock_mismatch/initial/Gopkg.toml new file mode 100644 index 00000000..418ac251 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/ignore_lock_mismatch/initial/Gopkg.toml @@ -0,0 +1,2 @@ +ignored = ["github.com/sdboyer/deptestdos"] + diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/ignore_lock_mismatch/initial/main.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/ignore_lock_mismatch/initial/main.go new file mode 100644 index 00000000..6fa04548 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/ignore_lock_mismatch/initial/main.go @@ -0,0 +1,12 @@ +// Copyright 2017 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 main + +import ( + _ "github.com/sdboyer/deptestdos" +) + +func main() { +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/ignore_lock_mismatch/testcase.json b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/ignore_lock_mismatch/testcase.json new file mode 100644 index 00000000..dc1776d5 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/ignore_lock_mismatch/testcase.json @@ -0,0 +1,7 @@ +{ + "commands": [ + ["status"] + ], + "error-expected": "This happens when Gopkg.toml is modified", + "vendor-final": [] +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/missing_pkgs_lock_mismatch/final/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/missing_pkgs_lock_mismatch/final/Gopkg.lock new file mode 100644 index 00000000..bef2d009 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/missing_pkgs_lock_mismatch/final/Gopkg.lock @@ -0,0 +1,9 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "ab4fef131ee828e96ba67d31a7d690bd5f2f42040c6766b1b12fe856f87e0ff7" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/missing_pkgs_lock_mismatch/final/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/missing_pkgs_lock_mismatch/final/Gopkg.toml new file mode 100644 index 00000000..e69de29b diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/missing_pkgs_lock_mismatch/initial/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/missing_pkgs_lock_mismatch/initial/Gopkg.lock new file mode 100644 index 00000000..bef2d009 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/missing_pkgs_lock_mismatch/initial/Gopkg.lock @@ -0,0 +1,9 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "ab4fef131ee828e96ba67d31a7d690bd5f2f42040c6766b1b12fe856f87e0ff7" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/missing_pkgs_lock_mismatch/initial/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/missing_pkgs_lock_mismatch/initial/Gopkg.toml new file mode 100644 index 00000000..e69de29b diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/missing_pkgs_lock_mismatch/initial/main.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/missing_pkgs_lock_mismatch/initial/main.go new file mode 100644 index 00000000..6fa04548 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/missing_pkgs_lock_mismatch/initial/main.go @@ -0,0 +1,12 @@ +// Copyright 2017 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 main + +import ( + _ "github.com/sdboyer/deptestdos" +) + +func main() { +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/missing_pkgs_lock_mismatch/testcase.json b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/missing_pkgs_lock_mismatch/testcase.json new file mode 100644 index 00000000..a1f75319 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/missing_pkgs_lock_mismatch/testcase.json @@ -0,0 +1,7 @@ +{ + "commands": [ + ["status"] + ], + "error-expected": "due to the following packages missing from the lock", + "vendor-final": [] +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/override_constraint/final/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/override_constraint/final/Gopkg.lock new file mode 100644 index 00000000..f987a579 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/override_constraint/final/Gopkg.lock @@ -0,0 +1,21 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "3f4c3bea144e112a69bbe5d8d01c1b09a544253f" + version = "v0.8.1" + +[[projects]] + name = "github.com/sdboyer/deptestdos" + packages = ["."] + revision = "5c607206be5decd28e6263ffffdcee067266015e" + version = "v2.0.0" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "1c4444f47ab5d5c484634d1a0c95d99beb879a37337bc0d7aecbd97cf79b6cb1" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/override_constraint/final/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/override_constraint/final/Gopkg.toml new file mode 100644 index 00000000..a6122254 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/override_constraint/final/Gopkg.toml @@ -0,0 +1,3 @@ +[[override]] + name = "github.com/sdboyer/deptest" + version = "=0.8.1" diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/override_constraint/initial/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/override_constraint/initial/Gopkg.lock new file mode 100644 index 00000000..f987a579 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/override_constraint/initial/Gopkg.lock @@ -0,0 +1,21 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "3f4c3bea144e112a69bbe5d8d01c1b09a544253f" + version = "v0.8.1" + +[[projects]] + name = "github.com/sdboyer/deptestdos" + packages = ["."] + revision = "5c607206be5decd28e6263ffffdcee067266015e" + version = "v2.0.0" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "1c4444f47ab5d5c484634d1a0c95d99beb879a37337bc0d7aecbd97cf79b6cb1" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/override_constraint/initial/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/override_constraint/initial/Gopkg.toml new file mode 100644 index 00000000..a6122254 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/override_constraint/initial/Gopkg.toml @@ -0,0 +1,3 @@ +[[override]] + name = "github.com/sdboyer/deptest" + version = "=0.8.1" diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/override_constraint/initial/main.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/override_constraint/initial/main.go new file mode 100644 index 00000000..6ebfee78 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/override_constraint/initial/main.go @@ -0,0 +1,12 @@ +// Copyright 2016 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 main + +import ( + _ "github.com/sdboyer/deptestdos" +) + +func main() { +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/override_constraint/stdout.txt b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/override_constraint/stdout.txt new file mode 100644 index 00000000..ba05bfcf --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/override_constraint/stdout.txt @@ -0,0 +1,3 @@ +PROJECT CONSTRAINT VERSION REVISION LATEST PKGS USED +github.com/sdboyer/deptest v0.8.1 (override) v0.8.1 3f4c3be v0.8.1 1 +github.com/sdboyer/deptestdos v2.0.0 v2.0.0 5c60720 v2.0.0 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/override_constraint/testcase.json b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/override_constraint/testcase.json new file mode 100644 index 00000000..e1f1eade --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/override_constraint/testcase.json @@ -0,0 +1,11 @@ +{ + "commands": [ + ["ensure"], + ["status"] + ], + "error-expected": "", + "vendor-final": [ + "github.com/sdboyer/deptest", + "github.com/sdboyer/deptestdos" + ] +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/revision_constraint/final/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/revision_constraint/final/Gopkg.lock new file mode 100644 index 00000000..204b9908 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/revision_constraint/final/Gopkg.lock @@ -0,0 +1,20 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "ff2948a2ac8f538c4ecd55962e919d1e13e74baf" + version = "v1.0.0" + +[[projects]] + name = "github.com/sdboyer/deptestdos" + packages = ["."] + revision = "a0196baa11ea047dd65037287451d36b861b00ea" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "a64abd431f23d6fbc8d83aef311d33ab12b3a6c74a46c271e89c2542c98bbb9a" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/revision_constraint/final/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/revision_constraint/final/Gopkg.toml new file mode 100644 index 00000000..1dbd51fc --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/revision_constraint/final/Gopkg.toml @@ -0,0 +1,3 @@ +[[constraint]] + name = "github.com/sdboyer/deptestdos" + revision = "a0196baa11ea047dd65037287451d36b861b00ea" diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/revision_constraint/initial/Gopkg.lock b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/revision_constraint/initial/Gopkg.lock new file mode 100644 index 00000000..204b9908 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/revision_constraint/initial/Gopkg.lock @@ -0,0 +1,20 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "ff2948a2ac8f538c4ecd55962e919d1e13e74baf" + version = "v1.0.0" + +[[projects]] + name = "github.com/sdboyer/deptestdos" + packages = ["."] + revision = "a0196baa11ea047dd65037287451d36b861b00ea" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "a64abd431f23d6fbc8d83aef311d33ab12b3a6c74a46c271e89c2542c98bbb9a" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/revision_constraint/initial/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/revision_constraint/initial/Gopkg.toml new file mode 100644 index 00000000..1dbd51fc --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/revision_constraint/initial/Gopkg.toml @@ -0,0 +1,3 @@ +[[constraint]] + name = "github.com/sdboyer/deptestdos" + revision = "a0196baa11ea047dd65037287451d36b861b00ea" diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/revision_constraint/initial/main.go b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/revision_constraint/initial/main.go new file mode 100644 index 00000000..6ebfee78 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/revision_constraint/initial/main.go @@ -0,0 +1,12 @@ +// Copyright 2016 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 main + +import ( + _ "github.com/sdboyer/deptestdos" +) + +func main() { +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/revision_constraint/stdout.txt b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/revision_constraint/stdout.txt new file mode 100644 index 00000000..12f30604 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/revision_constraint/stdout.txt @@ -0,0 +1,3 @@ +PROJECT CONSTRAINT VERSION REVISION LATEST PKGS USED +github.com/sdboyer/deptest v1.0.0 v1.0.0 ff2948a v1.0.0 1 +github.com/sdboyer/deptestdos a0196ba a0196ba 1 diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/revision_constraint/testcase.json b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/revision_constraint/testcase.json new file mode 100644 index 00000000..e1f1eade --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/revision_constraint/testcase.json @@ -0,0 +1,11 @@ +{ + "commands": [ + ["ensure"], + ["status"] + ], + "error-expected": "", + "vendor-final": [ + "github.com/sdboyer/deptest", + "github.com/sdboyer/deptestdos" + ] +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/without_lock/final/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/without_lock/final/Gopkg.toml new file mode 100644 index 00000000..e69de29b diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/without_lock/initial/Gopkg.toml b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/without_lock/initial/Gopkg.toml new file mode 100644 index 00000000..e69de29b diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/without_lock/testcase.json b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/without_lock/testcase.json new file mode 100644 index 00000000..5de81128 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/harness_tests/status/without_lock/testcase.json @@ -0,0 +1,6 @@ +{ + "commands": [ + ["status"] + ], + "error-expected": "no Gopkg.lock found. Run `dep ensure` to generate lock file" +} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/init/directdeps/main.go b/vendor/github.com/golang/dep/cmd/dep/testdata/init/directdeps/main.go new file mode 100644 index 00000000..3f8bc698 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/init/directdeps/main.go @@ -0,0 +1,9 @@ +// Copyright 2016 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 main + +import _ "github.com/carolynvs/deptest-subpkg/subby" + +func main() {} diff --git a/vendor/github.com/golang/dep/cmd/dep/testdata/status/collect_constraints/main.go b/vendor/github.com/golang/dep/cmd/dep/testdata/status/collect_constraints/main.go new file mode 100644 index 00000000..a53da1fd --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/testdata/status/collect_constraints/main.go @@ -0,0 +1,14 @@ +// Copyright 2017 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 main + +import ( + _ "github.com/boltdb/bolt" + _ "github.com/sdboyer/dep-test" + _ "github.com/sdboyer/deptest" + _ "github.com/sdboyer/deptestdos" +) + +type FooBar int diff --git a/vendor/github.com/golang/dep/cmd/dep/version.go b/vendor/github.com/golang/dep/cmd/dep/version.go new file mode 100644 index 00000000..d7a3d330 --- /dev/null +++ b/vendor/github.com/golang/dep/cmd/dep/version.go @@ -0,0 +1,45 @@ +// Copyright 2016 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 main + +import ( + "flag" + "runtime" + + "github.com/golang/dep" +) + +var ( + version = "devel" + buildDate string + commitHash string +) + +const versionHelp = `Show the dep version information` + +func (cmd *versionCommand) Name() string { return "version" } +func (cmd *versionCommand) Args() string { + return "" +} +func (cmd *versionCommand) ShortHelp() string { return versionHelp } +func (cmd *versionCommand) LongHelp() string { return versionHelp } +func (cmd *versionCommand) Hidden() bool { return false } + +func (cmd *versionCommand) Register(fs *flag.FlagSet) {} + +type versionCommand struct{} + +func (cmd *versionCommand) Run(ctx *dep.Ctx, args []string) error { + ctx.Out.Printf(`dep: + version : %s + build date : %s + git hash : %s + go version : %s + go compiler : %s + platform : %s/%s +`, version, buildDate, commitHash, + runtime.Version(), runtime.Compiler, runtime.GOOS, runtime.GOARCH) + return nil +} diff --git a/vendor/github.com/golang/dep/context.go b/vendor/github.com/golang/dep/context.go new file mode 100644 index 00000000..475efb37 --- /dev/null +++ b/vendor/github.com/golang/dep/context.go @@ -0,0 +1,297 @@ +// Copyright 2017 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 dep + +import ( + "log" + "os" + "path/filepath" + "runtime" + + "github.com/golang/dep/gps" + "github.com/golang/dep/internal/fs" + "github.com/pkg/errors" +) + +// Ctx defines the supporting context of dep. +// +// A properly initialized Ctx has a GOPATH containing the project root and non-nil Loggers. +// +// ctx := &dep.Ctx{ +// WorkingDir: GOPATH + "/src/project/root", +// GOPATH: GOPATH, +// Out: log.New(os.Stdout, "", 0), +// Err: log.New(os.Stderr, "", 0), +// } +// +// Ctx.DetectProjectGOPATH() helps with setting the containing GOPATH. +// +// ctx.GOPATH, err := Ctx.DetectProjectGOPATH(project) +// if err != nil { +// // Could not determine which GOPATH to use for the project. +// } +// +type Ctx struct { + WorkingDir string // Where to execute. + GOPATH string // Selected Go path, containing WorkingDir. + GOPATHs []string // Other Go paths. + Out, Err *log.Logger // Required loggers. + Verbose bool // Enables more verbose logging. + DisableLocking bool // When set, no lock file will be created to protect against simultaneous dep processes. + Cachedir string // Cache directory loaded from environment. +} + +// SetPaths sets the WorkingDir and GOPATHs fields. If GOPATHs is empty, then +// the GOPATH environment variable (or the default GOPATH) is used instead. +func (c *Ctx) SetPaths(wd string, GOPATHs ...string) error { + if wd == "" { + return errors.New("cannot set Ctx.WorkingDir to an empty path") + } + c.WorkingDir = wd + + if len(GOPATHs) == 0 { + GOPATH := os.Getenv("GOPATH") + if GOPATH == "" { + GOPATH = defaultGOPATH() + } + GOPATHs = filepath.SplitList(GOPATH) + } + + c.GOPATHs = append(c.GOPATHs, GOPATHs...) + + return nil +} + +// defaultGOPATH gets the default GOPATH that was added in 1.8 +// copied from go/build/build.go +func defaultGOPATH() string { + env := "HOME" + if runtime.GOOS == "windows" { + env = "USERPROFILE" + } else if runtime.GOOS == "plan9" { + env = "home" + } + if home := os.Getenv(env); home != "" { + def := filepath.Join(home, "go") + if def == runtime.GOROOT() { + // Don't set the default GOPATH to GOROOT, + // as that will trigger warnings from the go tool. + return "" + } + return def + } + return "" +} + +// SourceManager produces an instance of gps's built-in SourceManager +// initialized to log to the receiver's logger. +func (c *Ctx) SourceManager() (*gps.SourceMgr, error) { + cachedir := c.Cachedir + if cachedir == "" { + // When `DEPCACHEDIR` isn't set in the env, use the default - `$GOPATH/pkg/dep`. + cachedir = filepath.Join(c.GOPATH, "pkg", "dep") + // Create the default cachedir if it does not exist. + if err := os.MkdirAll(cachedir, 0777); err != nil { + return nil, errors.Wrap(err, "failed to create default cache directory") + } + } + + return gps.NewSourceManager(gps.SourceManagerConfig{ + Cachedir: cachedir, + Logger: c.Out, + DisableLocking: c.DisableLocking, + }) +} + +// LoadProject starts from the current working directory and searches up the +// directory tree for a project root. The search stops when a file with the name +// ManifestName (Gopkg.toml, by default) is located. +// +// The Project contains the parsed manifest as well as a parsed lock file, if +// present. The import path is calculated as the remaining path segment +// below Ctx.GOPATH/src. +func (c *Ctx) LoadProject() (*Project, error) { + root, err := findProjectRoot(c.WorkingDir) + if err != nil { + return nil, err + } + + err = checkGopkgFilenames(root) + if err != nil { + return nil, err + } + + p := new(Project) + + if err = p.SetRoot(root); err != nil { + return nil, err + } + + c.GOPATH, err = c.DetectProjectGOPATH(p) + if err != nil { + return nil, err + } + + ip, err := c.ImportForAbs(p.AbsRoot) + if err != nil { + return nil, errors.Wrap(err, "root project import") + } + p.ImportRoot = gps.ProjectRoot(ip) + + mp := filepath.Join(p.AbsRoot, ManifestName) + mf, err := os.Open(mp) + if err != nil { + if os.IsNotExist(err) { + // TODO: list possible solutions? (dep init, cd $project) + return nil, errors.Errorf("no %v found in project root %v", ManifestName, p.AbsRoot) + } + // Unable to read the manifest file + return nil, err + } + defer mf.Close() + + var warns []error + p.Manifest, warns, err = readManifest(mf) + for _, warn := range warns { + c.Err.Printf("dep: WARNING: %v\n", warn) + } + if err != nil { + return nil, errors.Wrapf(err, "error while parsing %s", mp) + } + + lp := filepath.Join(p.AbsRoot, LockName) + lf, err := os.Open(lp) + if err != nil { + if os.IsNotExist(err) { + // It's fine for the lock not to exist + return p, nil + } + // But if a lock does exist and we can't open it, that's a problem + return nil, errors.Wrapf(err, "could not open %s", lp) + } + defer lf.Close() + + p.Lock, err = readLock(lf) + if err != nil { + return nil, errors.Wrapf(err, "error while parsing %s", lp) + } + + return p, nil +} + +// DetectProjectGOPATH attempt to find the GOPATH containing the project. +// +// If p.AbsRoot is not a symlink and is within a GOPATH, the GOPATH containing p.AbsRoot is returned. +// If p.AbsRoot is a symlink and is not within any known GOPATH, the GOPATH containing p.ResolvedAbsRoot is returned. +// +// p.AbsRoot is assumed to be a symlink if it is not the same as p.ResolvedAbsRoot. +// +// DetectProjectGOPATH will return an error in the following cases: +// +// If p.AbsRoot is not a symlink and is not within any known GOPATH. +// If neither p.AbsRoot nor p.ResolvedAbsRoot are within a known GOPATH. +// If both p.AbsRoot and p.ResolvedAbsRoot are within the same GOPATH. +// If p.AbsRoot and p.ResolvedAbsRoot are each within a different GOPATH. +func (c *Ctx) DetectProjectGOPATH(p *Project) (string, error) { + if p.AbsRoot == "" || p.ResolvedAbsRoot == "" { + return "", errors.New("project AbsRoot and ResolvedAbsRoot must be set to detect GOPATH") + } + + pGOPATH, perr := c.detectGOPATH(p.AbsRoot) + + // If p.AbsRoot is a not symlink, attempt to detect GOPATH for p.AbsRoot only. + if equal, _ := fs.EquivalentPaths(p.AbsRoot, p.ResolvedAbsRoot); equal { + return pGOPATH, perr + } + + rGOPATH, rerr := c.detectGOPATH(p.ResolvedAbsRoot) + + // If detectGOPATH() failed for both p.AbsRoot and p.ResolvedAbsRoot, then both are not within any known GOPATHs. + if perr != nil && rerr != nil { + return "", errors.Errorf("both %s and %s are not within any known GOPATH", p.AbsRoot, p.ResolvedAbsRoot) + } + + // If pGOPATH equals rGOPATH, then both are within the same GOPATH. + if equal, _ := fs.EquivalentPaths(pGOPATH, rGOPATH); equal { + return "", errors.Errorf("both %s and %s are in the same GOPATH %s", p.AbsRoot, p.ResolvedAbsRoot, pGOPATH) + } + + if pGOPATH != "" && rGOPATH != "" { + return "", errors.Errorf("%s and %s are both in different GOPATHs", p.AbsRoot, p.ResolvedAbsRoot) + } + + // Otherwise, either the p.AbsRoot or p.ResolvedAbsRoot is within a GOPATH. + if pGOPATH == "" { + return rGOPATH, nil + } + + return pGOPATH, nil +} + +// detectGOPATH detects the GOPATH for a given path from ctx.GOPATHs. +func (c *Ctx) detectGOPATH(path string) (string, error) { + for _, gp := range c.GOPATHs { + isPrefix, err := fs.HasFilepathPrefix(path, gp) + if err != nil { + return "", errors.Wrap(err, "failed to detect GOPATH") + } + if isPrefix { + return gp, nil + } + } + return "", errors.Errorf("%s is not within a known GOPATH/src", path) +} + +// ImportForAbs returns the import path for an absolute project path by trimming the +// `$GOPATH/src/` prefix. Returns an error for paths equal to, or without this prefix. +func (c *Ctx) ImportForAbs(path string) (string, error) { + srcprefix := filepath.Join(c.GOPATH, "src") + string(filepath.Separator) + isPrefix, err := fs.HasFilepathPrefix(path, srcprefix) + if err != nil { + return "", errors.Wrap(err, "failed to find import path") + } + if isPrefix { + if len(path) <= len(srcprefix) { + return "", errors.New("dep does not currently support using GOPATH/src as the project root") + } + + // filepath.ToSlash because we're dealing with an import path now, + // not an fs path + return filepath.ToSlash(path[len(srcprefix):]), nil + } + + return "", errors.Errorf("%s is not within any GOPATH/src", path) +} + +// AbsForImport returns the absolute path for the project root +// including the $GOPATH. This will not work with stdlib packages and the +// package directory needs to exist. +func (c *Ctx) AbsForImport(path string) (string, error) { + posspath := filepath.Join(c.GOPATH, "src", path) + dirOK, err := fs.IsDir(posspath) + if err != nil { + return "", errors.Wrapf(err, "checking if %s is a directory", posspath) + } + if !dirOK { + return "", errors.Errorf("%s does not exist", posspath) + } + return posspath, nil +} + +// ValidateParams ensure that solving can be completed with the specified params. +func (c *Ctx) ValidateParams(sm gps.SourceManager, params gps.SolveParameters) error { + err := gps.ValidateParams(params, sm) + if err != nil { + if deduceErrs, ok := err.(gps.DeductionErrs); ok { + c.Err.Println("The following errors occurred while deducing packages:") + for ip, dErr := range deduceErrs { + c.Err.Printf(" * \"%s\": %s", ip, dErr) + } + c.Err.Println() + } + } + + return errors.Wrap(err, "validateParams") +} diff --git a/vendor/github.com/golang/dep/context_test.go b/vendor/github.com/golang/dep/context_test.go new file mode 100644 index 00000000..d673cc84 --- /dev/null +++ b/vendor/github.com/golang/dep/context_test.go @@ -0,0 +1,529 @@ +// Copyright 2017 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 dep + +import ( + "fmt" + "io/ioutil" + "log" + "os" + "path/filepath" + "runtime" + "strings" + "testing" + "unicode" + + "github.com/golang/dep/internal/test" +) + +func discardLogger() *log.Logger { + return log.New(ioutil.Discard, "", 0) +} + +func TestCtx_ProjectImport(t *testing.T) { + h := test.NewHelper(t) + defer h.Cleanup() + + h.TempDir("src") + + h.Setenv("GOPATH", h.Path(".")) + depCtx := &Ctx{GOPATH: h.Path(".")} + + importPaths := []string{ + "github.com/pkg/errors", + "my/silly/thing", + } + + for _, want := range importPaths { + fullpath := filepath.Join(depCtx.GOPATH, "src", want) + h.TempDir(filepath.Join("src", want)) + got, err := depCtx.ImportForAbs(fullpath) + if err != nil { + t.Fatal(err) + } + if got != want { + t.Fatalf("expected %s, got %s", want, got) + } + } + + // test where it should return an error when directly within $GOPATH/src + got, err := depCtx.ImportForAbs(filepath.Join(depCtx.GOPATH, "src")) + if err == nil || !strings.Contains(err.Error(), "GOPATH/src") { + t.Fatalf("should have gotten an error for use directly in GOPATH/src, but got %s", got) + } + + // test where it should return an error + got, err = depCtx.ImportForAbs("tra/la/la/la") + if err == nil { + t.Fatalf("should have gotten an error but did not for tra/la/la/la: %s", got) + } +} + +func TestAbsoluteProjectRoot(t *testing.T) { + h := test.NewHelper(t) + defer h.Cleanup() + + h.TempDir("src") + h.Setenv("GOPATH", h.Path(".")) + depCtx := &Ctx{GOPATH: h.Path(".")} + + importPaths := map[string]bool{ + "github.com/pkg/errors": true, + "my/silly/thing": false, + } + + for i, create := range importPaths { + if create { + h.TempDir(filepath.Join("src", i)) + } + } + + for i, ok := range importPaths { + got, err := depCtx.AbsForImport(i) + if ok { + h.Must(err) + want := h.Path(filepath.Join("src", i)) + if got != want { + t.Fatalf("expected %s, got %q", want, got) + } + continue + } + + if err == nil { + t.Fatalf("expected %s to fail", i) + } + } + + // test that a file fails + h.TempFile("src/thing/thing.go", "hello world") + _, err := depCtx.AbsForImport("thing/thing.go") + if err == nil { + t.Fatal("error should not be nil for a file found") + } +} + +func TestLoadProject(t *testing.T) { + h := test.NewHelper(t) + defer h.Cleanup() + + h.TempDir(filepath.Join("src", "test1", "sub")) + h.TempFile(filepath.Join("src", "test1", ManifestName), "") + h.TempFile(filepath.Join("src", "test1", LockName), `memo = "cdafe8641b28cd16fe025df278b0a49b9416859345d8b6ba0ace0272b74925ee"`) + h.TempDir(filepath.Join("src", "test2", "sub")) + h.TempFile(filepath.Join("src", "test2", ManifestName), "") + + var testcases = []struct { + name string + lock bool + wd string + }{ + {"direct", true, filepath.Join("src", "test1")}, + {"ascending", true, filepath.Join("src", "test1", "sub")}, + {"without lock", false, filepath.Join("src", "test2")}, + {"ascending without lock", false, filepath.Join("src", "test2", "sub")}, + } + + for _, tc := range testcases { + t.Run(tc.name, func(t *testing.T) { + ctx := &Ctx{ + Out: discardLogger(), + Err: discardLogger(), + } + + err := ctx.SetPaths(h.Path(tc.wd), h.Path(".")) + if err != nil { + t.Fatalf("%+v", err) + } + + p, err := ctx.LoadProject() + switch { + case err != nil: + t.Fatalf("%s: LoadProject failed: %+v", tc.wd, err) + case p.Manifest == nil: + t.Fatalf("%s: Manifest file didn't load", tc.wd) + case tc.lock && p.Lock == nil: + t.Fatalf("%s: Lock file didn't load", tc.wd) + case !tc.lock && p.Lock != nil: + t.Fatalf("%s: Non-existent Lock file loaded", tc.wd) + } + }) + } +} + +func TestLoadProjectNotFoundErrors(t *testing.T) { + tg := test.NewHelper(t) + defer tg.Cleanup() + + tg.TempDir("src") + tg.TempDir("src/test1") + tg.TempDir("src/test1/sub") + tg.Setenv("GOPATH", tg.Path(".")) + + var testcases = []struct { + lock bool + start string + path string + }{ + {true, filepath.Join("src", "test1"), ""}, //direct + {true, filepath.Join("src", "test1", "sub"), ""}, //ascending + } + + for _, testcase := range testcases { + ctx := &Ctx{GOPATHs: []string{tg.Path(".")}, WorkingDir: tg.Path(testcase.start)} + + _, err := ctx.LoadProject() + if err == nil { + t.Errorf("%s: should have returned 'No Manifest Found' error", testcase.start) + } + } +} + +func TestLoadProjectManifestParseError(t *testing.T) { + tg := test.NewHelper(t) + defer tg.Cleanup() + + tg.TempDir("src") + tg.TempDir("src/test1") + tg.TempFile(filepath.Join("src/test1", ManifestName), `[[constraint]]`) + tg.TempFile(filepath.Join("src/test1", LockName), `memo = "cdafe8641b28cd16fe025df278b0a49b9416859345d8b6ba0ace0272b74925ee"\n\n[[projects]]`) + tg.Setenv("GOPATH", tg.Path(".")) + + path := filepath.Join("src", "test1") + tg.Cd(tg.Path(path)) + + wd, err := os.Getwd() + if err != nil { + t.Fatal("failed to get working directory", err) + } + + ctx := &Ctx{ + GOPATH: tg.Path("."), + WorkingDir: wd, + Out: discardLogger(), + Err: discardLogger(), + } + + _, err = ctx.LoadProject() + if err == nil { + t.Fatal("should have returned 'Manifest Syntax' error") + } +} + +func TestLoadProjectLockParseError(t *testing.T) { + tg := test.NewHelper(t) + defer tg.Cleanup() + + tg.TempDir("src") + tg.TempDir("src/test1") + tg.TempFile(filepath.Join("src/test1", ManifestName), `[[constraint]]`) + tg.TempFile(filepath.Join("src/test1", LockName), `memo = "cdafe8641b28cd16fe025df278b0a49b9416859345d8b6ba0ace0272b74925ee"\n\n[[projects]]`) + tg.Setenv("GOPATH", tg.Path(".")) + + path := filepath.Join("src", "test1") + tg.Cd(tg.Path(path)) + + wd, err := os.Getwd() + if err != nil { + t.Fatal("failed to get working directory", err) + } + + ctx := &Ctx{ + GOPATH: tg.Path("."), + WorkingDir: wd, + Out: discardLogger(), + Err: discardLogger(), + } + + _, err = ctx.LoadProject() + if err == nil { + t.Fatal("should have returned 'Lock Syntax' error") + } +} + +func TestLoadProjectNoSrcDir(t *testing.T) { + tg := test.NewHelper(t) + defer tg.Cleanup() + + tg.TempDir("test1") + tg.TempFile(filepath.Join("test1", ManifestName), `[[constraint]]`) + tg.TempFile(filepath.Join("test1", LockName), `memo = "cdafe8641b28cd16fe025df278b0a49b9416859345d8b6ba0ace0272b74925ee"\n\n[[projects]]`) + tg.Setenv("GOPATH", tg.Path(".")) + + ctx := &Ctx{GOPATH: tg.Path(".")} + path := filepath.Join("test1") + tg.Cd(tg.Path(path)) + + f, _ := os.OpenFile(filepath.Join(ctx.GOPATH, "src", "test1", LockName), os.O_WRONLY, os.ModePerm) + defer f.Close() + + _, err := ctx.LoadProject() + if err == nil { + t.Fatal("should have returned 'Split Absolute Root' error (no 'src' dir present)") + } +} + +func TestLoadProjectGopkgFilenames(t *testing.T) { + // We are trying to skip this test on file systems which are case-sensiive. We could + // have used `fs.IsCaseSensitiveFilesystem` for this check. However, the code we are + // testing also relies on `fs.IsCaseSensitiveFilesystem`. So a bug in + // `fs.IsCaseSensitiveFilesystem` could prevent this test from being run. This is the + // only scenario where we prefer the OS heuristic over doing the actual work of + // validating filesystem case sensitivity via `fs.IsCaseSensitiveFilesystem`. + if runtime.GOOS != "windows" && runtime.GOOS != "darwin" { + t.Skip("skip this test on non-Windows, non-macOS") + } + + // Here we test that a manifest filename with incorrect case throws an error. Similar + // error will also be thrown for the lock file as well which has been tested in + // `project_test.go#TestCheckGopkgFilenames`. So not repeating here. + + h := test.NewHelper(t) + defer h.Cleanup() + + invalidMfName := strings.ToLower(ManifestName) + + wd := filepath.Join("src", "test") + h.TempFile(filepath.Join(wd, invalidMfName), "") + + ctx := &Ctx{ + Out: discardLogger(), + Err: discardLogger(), + } + + err := ctx.SetPaths(h.Path(wd), h.Path(".")) + if err != nil { + t.Fatalf("%+v", err) + } + + _, err = ctx.LoadProject() + + if err == nil { + t.Fatal("should have returned 'Manifest Filename' error") + } + + expectedErrMsg := fmt.Sprintf( + "manifest filename %q does not match %q", + invalidMfName, ManifestName, + ) + + if err.Error() != expectedErrMsg { + t.Fatalf("unexpected error: %+v", err) + } +} + +// TestCaseInsentitive is test for Windows. This should work even though set +// difference letter cases in GOPATH. +func TestCaseInsentitiveGOPATH(t *testing.T) { + if runtime.GOOS != "windows" { + t.Skip("skip this test on non-Windows") + } + + h := test.NewHelper(t) + defer h.Cleanup() + + h.TempDir("src") + h.TempDir("src/test1") + h.TempFile(filepath.Join("src/test1", ManifestName), ` + [[constraint]] + name = "github.com/foo/bar" + branch = "master"`) + + // Shuffle letter case + rs := []rune(strings.ToLower(h.Path("."))) + for i, r := range rs { + if unicode.IsLower(r) { + rs[i] = unicode.ToUpper(r) + } else { + rs[i] = unicode.ToLower(r) + } + } + gopath := string(rs) + h.Setenv("GOPATH", gopath) + wd := h.Path("src/test1") + + depCtx := &Ctx{} + if err := depCtx.SetPaths(wd, gopath); err != nil { + t.Fatal(err) + } + if _, err := depCtx.LoadProject(); err != nil { + t.Fatal(err) + } + + ip := "github.com/pkg/errors" + fullpath := filepath.Join(depCtx.GOPATH, "src", ip) + h.TempDir(filepath.Join("src", ip)) + pr, err := depCtx.ImportForAbs(fullpath) + if err != nil { + t.Fatal(err) + } + if pr != ip { + t.Fatalf("expected %s, got %s", ip, pr) + } +} + +func TestDetectProjectGOPATH(t *testing.T) { + h := test.NewHelper(t) + defer h.Cleanup() + + h.TempDir(filepath.Join("sym", "symlink")) + h.TempDir(filepath.Join("go", "src", "sym", "path")) + h.TempDir(filepath.Join("go", "src", "real", "path")) + h.TempDir(filepath.Join("go-two", "src", "real", "path")) + h.TempDir(filepath.Join("go-two", "src", "sym")) + + ctx := &Ctx{ + GOPATHs: []string{h.Path("go"), h.Path("go-two")}, + } + + testcases := []struct { + name string + root string + resolvedRoot string + GOPATH string + expectErr bool + }{ + { + name: "project-with-no-AbsRoot", + root: "", + resolvedRoot: filepath.Join(ctx.GOPATHs[0], "src", "real", "path"), + expectErr: true, + }, + { + name: "project-with-no-ResolvedAbsRoot", + root: filepath.Join(ctx.GOPATHs[0], "src", "real", "path"), + resolvedRoot: "", + expectErr: true, + }, + { + name: "AbsRoot-is-not-within-any-GOPATH", + root: filepath.Join(h.Path("."), "src", "real", "path"), + resolvedRoot: filepath.Join(h.Path("."), "src", "real", "path"), + expectErr: true, + }, + { + name: "neither-AbsRoot-nor-ResolvedAbsRoot-are-in-any-GOPATH", + root: filepath.Join(h.Path("."), "src", "sym", "path"), + resolvedRoot: filepath.Join(h.Path("."), "src", "real", "path"), + expectErr: true, + }, + { + name: "both-AbsRoot-and-ResolvedAbsRoot-are-in-the-same-GOPATH", + root: filepath.Join(ctx.GOPATHs[0], "src", "sym", "path"), + resolvedRoot: filepath.Join(ctx.GOPATHs[0], "src", "real", "path"), + expectErr: true, + }, + { + name: "AbsRoot-and-ResolvedAbsRoot-are-each-within-a-different-GOPATH", + root: filepath.Join(ctx.GOPATHs[0], "src", "sym", "path"), + resolvedRoot: filepath.Join(ctx.GOPATHs[1], "src", "real", "path"), + expectErr: true, + }, + { + name: "AbsRoot-is-not-a-symlink", + root: filepath.Join(ctx.GOPATHs[0], "src", "real", "path"), + resolvedRoot: filepath.Join(ctx.GOPATHs[0], "src", "real", "path"), + GOPATH: ctx.GOPATHs[0], + }, + { + name: "AbsRoot-is-a-symlink-to-ResolvedAbsRoot", + root: filepath.Join(h.Path("."), "sym", "symlink"), + resolvedRoot: filepath.Join(ctx.GOPATHs[0], "src", "real", "path"), + GOPATH: ctx.GOPATHs[0], + }, + } + + for _, tc := range testcases { + t.Run(tc.name, func(t *testing.T) { + project := &Project{ + AbsRoot: tc.root, + ResolvedAbsRoot: tc.resolvedRoot, + } + + GOPATH, err := ctx.DetectProjectGOPATH(project) + if !tc.expectErr && err != nil { + t.Fatalf("%+v", err) + } else if tc.expectErr && err == nil { + t.Fatalf("expected an error, got nil and gopath %s", GOPATH) + } + if GOPATH != tc.GOPATH { + t.Errorf("expected GOPATH %s, got %s", tc.GOPATH, GOPATH) + } + }) + } +} + +func TestDetectGOPATH(t *testing.T) { + th := test.NewHelper(t) + defer th.Cleanup() + + th.TempDir(filepath.Join("code", "src", "github.com", "username", "package")) + th.TempDir(filepath.Join("go", "src", "github.com", "username", "package")) + th.TempDir(filepath.Join("gotwo", "src", "github.com", "username", "package")) + + ctx := &Ctx{GOPATHs: []string{ + th.Path("go"), + th.Path("gotwo"), + }} + + testcases := []struct { + GOPATH string + path string + err bool + }{ + {th.Path("go"), th.Path(filepath.Join("go", "src", "github.com", "username", "package")), false}, + {th.Path("go"), th.Path(filepath.Join("go", "src", "github.com", "username", "package")), false}, + {th.Path("gotwo"), th.Path(filepath.Join("gotwo", "src", "github.com", "username", "package")), false}, + {"", th.Path(filepath.Join("code", "src", "github.com", "username", "package")), true}, + } + + for _, tc := range testcases { + GOPATH, err := ctx.detectGOPATH(tc.path) + if tc.err && err == nil { + t.Error("expected error but got none") + } + if GOPATH != tc.GOPATH { + t.Errorf("expected GOPATH to be %s, got %s", GOPATH, tc.GOPATH) + } + } +} + +func TestDepCachedir(t *testing.T) { + h := test.NewHelper(t) + defer h.Cleanup() + + h.TempDir("cache") + // Create the directory for default cachedir location. + h.TempDir(filepath.Join("go", "pkg", "dep")) + + testCachedir := h.Path("cache") + gopath := h.Path("go") + discardLgr := discardLogger() + + cases := []struct { + cachedir string + wantCachedir string + }{ + // If `Cachedir` is not set in the context, it should use `$GOPATH/pkg/dep`. + {cachedir: "", wantCachedir: h.Path(filepath.Join("go", "pkg", "dep"))}, + // If `Cachedir` is set in the context, it should use that. + {cachedir: testCachedir, wantCachedir: testCachedir}, + } + + for _, c := range cases { + ctx := &Ctx{ + GOPATH: gopath, + Cachedir: c.cachedir, + Out: discardLgr, + Err: discardLgr, + } + sm, err := ctx.SourceManager() + h.Must(err) + defer sm.Release() + + if sm.Cachedir() != c.wantCachedir { + t.Errorf("expected cachedir to be %s, got %s", c.wantCachedir, sm.Cachedir()) + } + } +} diff --git a/vendor/github.com/golang/dep/doc.go b/vendor/github.com/golang/dep/doc.go new file mode 100644 index 00000000..63226ce4 --- /dev/null +++ b/vendor/github.com/golang/dep/doc.go @@ -0,0 +1,6 @@ +// Copyright 2017 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 dep is a prototype dependency management library. +package dep diff --git a/vendor/github.com/golang/dep/docs/FAQ.md b/vendor/github.com/golang/dep/docs/FAQ.md new file mode 100644 index 00000000..ffa47c8c --- /dev/null +++ b/vendor/github.com/golang/dep/docs/FAQ.md @@ -0,0 +1,491 @@ +--- +title: FAQ +--- + +The FAQ predated the introduction of the rest of the documentation. If something in here conflicts with other guides or reference documents, it's probably here that it's wrong - please file a PR! + +## Concepts +* [Does `dep` replace `go get`?](#does-dep-replace-go-get) +* [Why is it `dep ensure` instead of `dep install`?](#why-is-it-dep-ensure-instead-of-dep-install) +* [What is a direct or transitive dependency?](#what-is-a-direct-or-transitive-dependency) + +## Configuration +* [What is the difference between Gopkg.toml (the "manifest") and Gopkg.lock (the "lock")?](#what-is-the-difference-between-gopkgtoml-the-manifest-and-gopkglock-the-lock) +* [How do I constrain a transitive dependency's version?](#how-do-i-constrain-a-transitive-dependencys-version) +* [Can I put the manifest and lock in the vendor directory?](#can-i-put-the-manifest-and-lock-in-the-vendor-directory) +* [How do I get `dep` to authenticate to a `git` repo?](#how-do-i-get-dep-to-authenticate-to-a-git-repo) +* [How do I get `dep` to consume private `git` repos using a Github Token?](#how-do-i-get-dep-to-consume-private-git-repos-using-a-github-token) + +## Behavior +* [How does `dep` decide what version of a dependency to use?](#how-does-dep-decide-what-version-of-a-dependency-to-use) +* [What external tools are supported?](#what-external-tools-are-supported) +* [Why is `dep` ignoring a version constraint in the manifest?](#why-is-dep-ignoring-a-version-constraint-in-the-manifest) +* [Why did `dep` use a different revision for package X instead of the revision in the lock file?](#why-did-dep-use-a-different-revision-for-package-x-instead-of-the-revision-in-the-lock-file) +* [Why is `dep` slow?](#why-is-dep-slow) +* [How does `dep` handle symbolic links?](#how-does-dep-handle-symbolic-links) +* [Does `dep` support relative imports?](#does-dep-support-relative-imports) +* [How do I make `dep` resolve dependencies from my `GOPATH`?](#how-do-i-make-dep-resolve-dependencies-from-my-gopath) +* [Will `dep` let me use git submodules to store dependencies in `vendor`?](#will-dep-let-me-use-git-submodules-to-store-dependencies-in-vendor) + +## Best Practices +* [Should I commit my vendor directory?](#should-i-commit-my-vendor-directory) +* [How do I roll releases that `dep` will be able to use?](#how-do-i-roll-releases-that-dep-will-be-able-to-use) +* [What semver version should I use?](#what-semver-version-should-i-use) +* [Is it OK to make backwards-incompatible changes now?](#is-it-ok-to-make-backwards-incompatible-changes-now) +* [My dependers don't use `dep` yet. What should I do?](#my-dependers-dont-use-dep-yet-what-should-i-do) +* [How do I configure a dependency that doesn't tag its releases?](#how-do-i-configure-a-dependency-that-doesnt-tag-its-releases) +* [How do I use `dep` with Docker?](#how-do-i-use-dep-with-docker) +* [How do I use `dep` in CI?](#how-do-i-use-dep-in-ci) + +## Concepts +### Does `dep` replace `go get`? + +No. `dep` and `go get` serve mostly different purposes. + +Here are some suggestions for when you could use `dep` or `go get`: +> I would say that dep doesn't replace go get, but they both can do similar things. Here's how I use them: +> +> `go get`: I want to download the source code for a go project so that I can work on it myself, or to install a tool. This clones the repo under GOPATH for all to use. +> +> `dep ensure`: I have imported a new dependency in my code and want to download the dependency so I can start using it. My workflow is "add the import to the code, and then run dep ensure so that the manifest/lock/vendor are updated". This clones the repo under my project's vendor directory, and remembers the revision used so that everyone who works on my project is guaranteed to be using the same version of dependencies. +> +> [@carolynvs in #376](https://github.com/golang/dep/issues/376#issuecomment-293964655) + +> The long term vision is a sane, overall-consistent go tool. My general take is that `go get` +> is for people consuming Go code, and dep-family commands are for people developing it. +> +> [@sdboyer in #376](https://github.com/golang/dep/issues/376#issuecomment-294045873) + +### Why is it `dep ensure` instead of `dep install`? + +> Yeah, we went round and round on names. [A lot](https://gist.github.com/jessfraz/315db91b272441f510e81e449f675a8b). +> +> The idea of "ensure" is roughly, "ensure that all my local states - code tree, manifest, lock, and vendor - are in sync with each other." When arguments are passed, it becomes "ensure this argument is satisfied, along with synchronization between all my local states." +> +> We opted for this approach because we came to the conclusion that allowing the tool to perform partial work/exit in intermediate states ended up creating a tool that had more commands, had far more possible valid exit and input states, and was generally full of footguns. In this approach, the user has most of the same ultimate control, but exercises it differently (by modifying the code/manifest and re-running dep ensure). +> +> [@sdboyer in #371](https://github.com/golang/dep/issues/371#issuecomment-293246832) + +### What is a direct or transitive dependency? +* Direct dependencies are dependencies that are imported directly by your project: they appear in at least one import statement from your project. +* Transitive dependencies are the dependencies of your dependencies. Necessary to compile but are not directly used by your code. + +## Configuration +### What is the difference between `Gopkg.toml` (the "manifest") and `Gopkg.lock` (the "lock")? + +> The manifest describes user intent, and the lock describes computed outputs. There's flexibility in manifests that isn't present in locks..., as the "branch": "master" constraint will match whatever revision master HAPPENS to be at right now, whereas the lock is nailed down to a specific revision. +> +> This flexibility is important because it allows us to provide easy commands (e.g. `dep ensure -update`) that can manage an update process for you, within the constraints you specify, AND because it allows your project, when imported by someone else, to collaboratively specify the constraints for your own dependencies. +> +> [@sdboyer in #281](https://github.com/golang/dep/issues/281#issuecomment-284118314) + +## How do I constrain a transitive dependency's version? +First, if you're wondering about this because you're trying to keep the version +of the transitive dependency from changing, then you're working against `dep`'s +design. The lock file, `Gopkg.lock`, will keep the selected version of the +transitive dependency stable, unless you explicitly request an upgrade or it's +impossible to find a solution without changing that version. + +If that isn't your use case and you still need to constrain a transitive +dependency, you have a couple of options: + +1. Make the transitive dependency a direct one, either with a dummy import or an entry in the `required` list in `Gopkg.toml`. +2. Use an override. + +Overrides are a sledgehammer, and should only be used as a last resort. While +constraints and overrides are declared in the same way in `Gopkg.toml`, they +behave differently: + +* Constraints: + 1. Can be declared by any project's manifest, yours or a dependency + 2. Apply only to direct dependencies of the project declaring the constraint + 3. Must not conflict with the `constraint` entries declared in any other project's manifest +* Overrides: + 1. Are only utilized from the current/your project's manifest + 2. Apply globally, to direct and transitive dependencies + 3. Supersede constraints declared in all manifests, yours or a dependency's + +Overrides are also discussed with some visuals in [the gps docs](https://github.com/sdboyer/gps/wiki/gps-for-Implementors#overrides). + +## Can I put the manifest and lock in the vendor directory? +No. + +> Placing these files inside `vendor/` would concretely bind us to `vendor/` in the long term. +> We prefer to treat the `vendor/` as an implementation detail. +> +> [@sdboyer on go package management list](https://groups.google.com/d/msg/go-package-management/et1qFUjrkP4/LQFCHP4WBQAJ) + +## How do I get dep to authenticate to a git repo? + +`dep` currently uses the `git` command under the hood, so configuring the credentials +for each repository you wish to authenticate to will allow `dep` to use an +authenticated repository. + +First, configure `git` to use the credentials option for the specific repository. + +For example, if you use gitlab, and you wish to access `https://gitlab.example.com/example/package.git`, +then you would want to use the following configuration: + +``` +$ git config --global credential.https://gitlab.example.com.example yourusername +``` + +In the example the hostname `gitlab.example.com.example` string seems incorrect, but +it's actually the hostname plus the name of the repo you are accessing which is `username`. +The trailing 'yourusername' is the username you would use for the actual authentication. + +You also need to configure `git` with the authentication provider you wish to use. You can get +a list of providers, with the command: + +``` +$ git help -a | grep credential- + credential-cache remote-fd + credential-cache--daemon remote-ftp + credential-osxkeychain remote-ftps + credential-store remote-http +``` + +You would then choose an appropriate provider. For example, to use the osxkeychain, you +would use the following: + +``` +git config --global credential.helper osxkeychain +``` + +If you need to do this for a CI system, then you may want to use the "store" provider. +Please see the documentation on how to configure that: https://git-scm.com/docs/git-credential-store + +After configuring `git`, you may need to use `git` manually once to have it store the +credentials. Once you've checked out the repo manually, it will then use the stored +credentials. This at least appears to be the behavior for the osxkeychain provider. + +### How do I get dep to consume private git repos using a Github Token? + +Another alternative to make `dep` work with private repos is to use a [Personal Github +Token](https://help.github.com/articles/creating-a-personal-access-token-for-the-command-line/) +and configure it inside the [`.netrc` file](https://www.gnu.org/software/inetutils/manual/html_node/The-_002enetrc-file.html) +as the following example: +``` +machine github.com +    login [YOUR_GITHUB_USERNAME] + password [YOUR_GITHUB_TOKEN] +``` + +Once you have set that up, dep will automatically use that Token to authenticate to the repositories. + +## Behavior +### How does `dep` decide what version of a dependency to use? + +The full algorithm is complex, but the most important thing to understand is +that `dep` tries versions in a [certain +order](https://godoc.org/github.com/golang/dep/gps#SortForUpgrade), +checking to see a version is acceptable according to specified constraints. + +- All semver versions come first, and sort mostly according to the semver 2.0 + spec, with one exception: + - Semver versions with a prerelease are sorted after *all* non-prerelease + semver. Within this subset they are sorted first by their numerical + component, then lexicographically by their prerelease version. +- The default branch(es) are next; the semantics of what "default branch" means + are specific to the underlying source type, but this is generally what you'd + get from a `go get`. +- All other branches come next, sorted lexicographically. +- All non-semver versions (tags) are next, sorted lexicographically. +- Revisions, if any, are last, sorted lexicographically. Revisions do not + typically appear in version lists, so the only invariant we maintain is + determinism - deeper semantics, like chronology or topology, do not matter. + +So, given a slice of the following versions: + +- Branch: `master` `devel` +- Semver tags: `v1.0.0` `v1.1.0` `v1.1.0-alpha1` +- Non-semver tags: `footag` +- Revision: `f6e74e8d` + +Sorting for upgrade will result in the following slice. + +`[v1.1.0 v1.0.0 v1.1.0-alpha1 master devel footag f6e74e8d]` + +There are a number of factors that can eliminate a version from consideration, +the simplest of which is that it doesn't match a constraint. But if you're +trying to figure out why `dep` is doing what it does, understanding that its +basic action is to attempt versions in this order should help you to reason +about what's going on. + +## What external tools are supported? +During `dep init` configuration from other dependency managers is detected +and imported, unless `-skip-tools` is specified. + +The following tools are supported: `glide`, `godep`, `vndr`, `govend`, `gb`, `gvt`, `govendor` and `glock`. + +See [#186](https://github.com/golang/dep/issues/186#issuecomment-306363441) for +how to add support for another tool. + +## Why is `dep` ignoring a version constraint in the manifest? +Only your project's directly imported dependencies are affected by a `constraint` entry +in the manifest. Transitive dependencies are unaffected. See [How do I constrain a transitive dependency's version](#how-do-i-constrain-a-transitive-dependencys-version)? + +## Why did `dep` use a different revision for package X instead of the revision in the lock file? +Sometimes the revision specified in the lock file is no longer valid. There are a few +ways this can occur: + +* When you generated the lock file, you had an unpushed commit in your local copy of package X's repository in your `GOPATH`. (This case will be going away soon) +* After generating the lock file, new commits were force pushed to package X's repository, causing the commit revision in your lock file to no longer exist. + +To troubleshoot, you can revert dep's changes to your lock, and then run `dep ensure -v -n`. +This retries the command in dry-run mode with verbose logs enabled. Check the output +for a warning like the one below, indicating that a commit in the lock is no longer valid. + +``` +Unable to update checked out version: fatal: reference is not a tree: 4dfc6a8a7e15229398c0a018b6d7a078cccae9c8 +``` + +> The lock file represents a set of precise, typically immutable versions for the entire transitive closure of dependencies for a project. But "the project" can be, and is, decomposed into just a bunch of arguments to an algorithm. When those inputs change, the lock may need to change as well. +> +> Under most circumstances, if those arguments don't change, then the lock remains fine and correct. You've hit one of the few cases where that guarantee doesn't apply. The fact that you ran dep ensure and it DID a solve is a product of some arguments changing; that solving failed because this particular commit had become stale is a separate problem. +> +> [@sdboyer in #405](https://github.com/golang/dep/issues/405#issuecomment-295998489) + +## Why is `dep` slow? + +There are two things that really slow `dep` down. One is unavoidable; for the other, we have a plan. + +The unavoidable part is the initial clone. `dep` relies on a cache of local +repositories (stored under `$GOPATH/pkg/dep`), which is populated on demand. +Unfortunately, the first `dep` run, especially for a large project, may take a +while, as all dependencies are cloned into the cache. + +Fortunately, this is just an _initial_ clone - pay it once, and you're done. +The problem repeats itself a bit when you're running `dep` for the first time +in a while and there's new changesets to fetch, but even then, these costs are +only paid once per changeset. + +The other part is the work of retrieving information about dependencies. There are three parts to this: + +1. Getting an up-to-date list of versions from the upstream source +2. Reading the `Gopkg.toml` for a particular version out of the local cache +3. Parsing the tree of packages for import statements at a particular version + +The first requires one or more network calls; the second two usually mean +something like a `git checkout`, and the third is a filesystem walk, plus +loading and parsing `.go` files. All of these are expensive operations. + +Fortunately, we can cache the second and third. And that cache can be permanent +when keyed on an immutable identifier for the version - like a git commit SHA1 +hash. The first is a bit trickier, but there are reasonable staleness tradeoffs +we can consider to avoid the network entirely. There's an issue to [implement +persistent caching](https://github.com/golang/dep/issues/431) that's the +gateway to all of these improvements. + +There's another major performance issue that's much harder - the process of picking versions itself is an NP-complete problem in `dep`'s current design. This is a much trickier problem 😜 + +## How does `dep` handle symbolic links? + +> because we're not crazy people who delight in inviting chaos into our lives, we need to work within one `GOPATH` at a time. +> -[@sdboyer in #247](https://github.com/golang/dep/pull/247#issuecomment-284181879) + +Out of convenience, one might create a symlink to a directory within their `GOPATH/src`, e.g. `ln -s ~/go/src/github.com/user/awesome-project ~/Code/awesome-project`. + +When `dep` is invoked with a project root that is a symlink, it will be resolved according to the following rules: + +- If the symlink is outside `GOPATH` and links to a directory within a `GOPATH`, or vice versa, then `dep` will choose whichever path is within `GOPATH`. +- If the symlink is within a `GOPATH` and the resolved path is within a *different* `GOPATH`, then an error is thrown. +- If both the symlink and the resolved path are in the same `GOPATH`, then an error is thrown. +- If neither the symlink nor the resolved path are in a `GOPATH`, then an error is thrown. + +This is the only symbolic link support that `dep` really intends to provide. In keeping with the general practices of the `go` tool, `dep` tends to either ignore symlinks (when walking) or copy the symlink itself, depending on the filesystem operation being performed. + +## Does `dep` support relative imports? + +No. +> dep simply doesn't allow relative imports. this is one of the few places where we restrict a case that the toolchain itself allows. we disallow them only because: +> +> * the toolchain already frowns heavily on them
+> * it's worse for our case, as we start venturing into [dot dot hell](http://doc.cat-v.org/plan_9/4th_edition/papers/lexnames) territory when trying to prove that the import does not escape the tree of the project +> +> [@sdboyer in #899](https://github.com/golang/dep/issues/899#issuecomment-317904001) + +For a refresher on Go's recommended workspace organization, see the ["How To Write Go Code"](https://golang.org/doc/code.html) article in the Go docs. Organizing your code this way gives you a unique import path for every package. + +## How do I make `dep` resolve dependencies from my `GOPATH`? + +`dep init` provides an option to scan the `GOPATH` for dependencies by doing +`dep init -gopath`, which falls back to network mode when the packages are not +found in `GOPATH`. `dep ensure` doesn't work with projects in `GOPATH`. + +## Will `dep` let me use git submodules to store dependencies in `vendor`? + +No, with just one tiny exception: `dep` preserves `/vendor/.git`, if it exists. This was added at [cockroachdb](https://github.com/cockroachdb/cockroach)'s request, who rely on it to keep `vendor` from bloating their primary repository. + +The reasons why git submodules will not be a part of dep are best expressed as a pro/con list: + +**Pros** + +* git submodules provide a well-structured way of nesting repositories within repositories. + +**Cons** + +* The nesting that git submodules perform is no more powerful or expressive than what dep already does, but dep does it both more generally (for bzr and hg) and more domain-specifically (e.g. elimination of nested vendor directories). +* Incorporating git submodules in any way would new fork new paths in the logic to handle the submodule cases, meaning nontrivial complexity increases. +* dep does not currently know or care if the project it operates on is under version control. Relying on submodules would entail that dep start paying attention to that. That it would only be conditionally does not make it better - again, more forking paths in the logic, more complexity. +* Incorporating submodules in a way that is at all visible to the user (and why else would you do it?) makes dep's workflows both more complicated and less predictable: _sometimes_ submodule-related actions are expected; _sometimes_ submodule-derived workflows are sufficient. +* Nesting one repository within another implies that changes could, potentially, be made directly in that subrepository. This is directly contrary to dep's foundational principle that `vendor` is dead code, and directly modifying anything in there is an error. + +## Best Practices +### Should I commit my vendor directory? + +It's up to you: + +**Pros** + +- It's the only way to get truly reproducible builds, as it guards against upstream renames, + deletes and commit history overwrites. +- You don't need an extra `dep ensure` step to sync `vendor/` with Gopkg.lock after most operations, + such as `go get`, cloning, getting latest, merging, etc. + +**Cons** + +- Your repo will be bigger, potentially a lot bigger, + though [`prune`](Gopkg.toml.md#prune) can help minimize this problem. +- PR diffs will include changes for files under `vendor/` when Gopkg.lock is modified, + however files in `vendor/` are [hidden by default](https://github.com/github/linguist/blob/v5.2.0/lib/linguist/generated.rb#L328) on Github. + +## How do I roll releases that `dep` will be able to use? + +In short: make sure you've committed your `Gopkg.toml` and `Gopkg.lock`, then +just create a tag in your version control system and push it to the canonical +location. `dep` is designed to work automatically with this sort of metadata +from `git`, `bzr`, and `hg`. + +It's strongly preferred that you use [semver](http://semver.org)-compliant tag +names. We hope to develop documentation soon that describes this more precisely, +but in the meantime, the [npm](https://docs.npmjs.com/misc/semver) docs match +our patterns pretty well. + +## What semver version should I use? + +This can be a nuanced question, and the community is going to have to work out +some accepted standards for how semver should be applied to Go projects. At the +highest level, though, these are the rules: + +* Below `v1.0.0`, anything goes. Use these releases to figure out what you want + your API to be. +* Above `v1.0.0`, the general Go best practices continue to apply - don't make + backwards-incompatible changes - exported identifiers can be added to, but + not changed or removed. +* If you must make a backwards-incompatible change, then bump the major version. + +It's important to note that having a `v1.0.0` does not preclude you from having +alpha/beta/etc releases. The semver spec allows for [prerelease +versions](http://semver.org/#spec-item-9), and `dep` is careful to _not_ allow +such versions unless `Gopkg.toml` contains a range constraint that explicitly +includes prereleases: if there exists a version `v1.0.1-alpha4`, then the +constraint `>=1.0.0` will not match it, but `>=1.0.1-alpha1` will. + +Some work has been done towards [a tool +to](https://github.com/bradleyfalzon/apicompat) that will analyze and compare +your code with the last release, and suggest the next version you should use. + +## Is it OK to make backwards-incompatible changes now? + +Yes. But. + +`dep` will make it possible for the Go ecosystem to handle +backwards-incompatible changes more gracefully. However, `dep` is not some +magical panacea. Version and dependency management is hard, and dependency hell +is real. The longstanding community wisdom about avoiding breaking changes +remains important. Any `v1.0.0` release should be accompanied by a plan for how +to avoid future breaking API changes. + +One good strategy may be to add to your API instead of changing it, deprecating +old versions as you progress. Then, when the time is right, you can roll a new +major version and clean out a bunch of deprecated symbols all at once. + +Note that providing an incremental migration path across breaking changes (i.e., +shims) is tricky, and something we [don't have a good answer for +yet](https://groups.google.com/forum/#!topic/go-package-management/fp2uBMf6kq4). + +## My dependers don't use `dep` yet. What should I do? + +For the most part, you needn't do anything differently. + +The only possible issue is if your project is ever consumed as a library. If +so, then you may want to be wary about committing your `vendor/` directory, as +it can [cause +problems](https://groups.google.com/d/msg/golang-nuts/AnMr9NL6dtc/UnyUUKcMCAAJ). +If your dependers are using `dep`, this is not a concern, as `dep` takes care of +stripping out nested `vendor` directories. + +## How do I configure a dependency that doesn't tag its releases? + +Add a constraint to `Gopkg.toml` that specifies `branch: "master"` (or whichever branch you need) in the `[[constraint]]` for that dependency. `dep ensure` will determine the current revision of your dependency's master branch, and place it in `Gopkg.lock` for you. See also: [What is the difference between Gopkg.toml and Gopkg.lock?](#what-is-the-difference-between-gopkgtoml-the-manifest-and-gopkglock-the-lock) + +## How do I use `dep` with Docker? + +`dep ensure -vendor-only` creates the vendor folder from a valid `Gopkg.toml` and `Gopkg.lock` without checking for Go code. +This is especially useful for builds inside docker utilizing cache layers. + +Sample dockerfile: + +```Dockerfile +FROM golang:1.9 AS builder + +RUN curl -fsSL -o /usr/local/bin/dep https://github.com/golang/dep/releases/download/vX.X.X/dep-linux-amd64 && chmod +x /usr/local/bin/dep + +RUN mkdir -p /go/src/github.com/*** +WORKDIR /go/src/github.com/*** + +COPY Gopkg.toml Gopkg.lock ./ +# copies the Gopkg.toml and Gopkg.lock to WORKDIR + +RUN dep ensure -vendor-only +# install the dependencies without checking for go code + +... +``` + +## How do I use `dep` in CI? + +Since `dep` is expected to change until `v1.0.0` is released, it is recommended to rely on a released version. +You can find the latest binary from the [releases](https://github.com/golang/dep/releases) page. + +Sample configuration for Travis CI: + +```yml +# ... + +env: + - DEP_VERSION="X.X.X" + +before_install: + # Download the binary to bin folder in $GOPATH + - curl -L -s https://github.com/golang/dep/releases/download/v${DEP_VERSION}/dep-linux-amd64 -o $GOPATH/bin/dep + # Make the binary executable + - chmod +x $GOPATH/bin/dep + +install: + - dep ensure +``` + +Caching can also be enabled but there are a couple of caveats you should be aware of: + +> Until recently, we have had intermittent cache corruption that would have been super annoying if it was breaking Travis build too. +> +> Also according to https://docs.travis-ci.com/user/caching/#Things-not-to-cache, they don't recommend it for larger caches. +> +> https://docs.travis-ci.com/user/caching/#How-does-the-caching-work%3F +> +> > Note that this makes our cache not network-local, it's still bound to network bandwidth and DNS resolutions for S3. +> > That impacts what you can and should store in the cache. If you store archives larger than a few hundred megabytes in the cache, it's unlikely that you'll see a big speed improvement. +> +> [@carolynvs in #1293](https://github.com/golang/dep/pull/1293#issuecomment-342969292) + +If you are sure you want to enable caching on travis, it can be done by adding `$GOPATH/pkg/dep`, the default location for `dep` cache, to the cached directories: + +```yml +# ... + +cache: + directories: + - $GOPATH/pkg/dep +``` diff --git a/vendor/github.com/golang/dep/docs/Gopkg.lock.md b/vendor/github.com/golang/dep/docs/Gopkg.lock.md new file mode 100644 index 00000000..c68fdc01 --- /dev/null +++ b/vendor/github.com/golang/dep/docs/Gopkg.lock.md @@ -0,0 +1,86 @@ +--- +title: Gopkg.lock +--- + +The `Gopkg.lock` file is generated by `dep ensure` and `dep init`. It is the output of [the solving function](ensure-mechanics.md#functional-flow): a transitively complete snapshot of a project's dependency graph, expressed as a series of `[[project]]` stanzas. That means: + +* Every package a project needs to compile +* Plus any [`required`](Gopkg.toml.md#required) packages +* Less any [`ignored`](Gopkg.toml.md#ignored) packages + +`Gopkg.lock` also contains some metadata about the algorithm used to arrive at the final graph, under `[solve-meta]`. + +`Gopkg.lock` always includes a `revision` for all listed dependencies, as the semantics of `revision` guarantee them to be immutable. Thus, the `Gopkg.lock` acts as a reproducible build list - as long as the upstream remains available, all dependencies can be precisely reproduced. + +`Gopkg.lock` is autogenerated; editing it manually is generally an antipattern. If there is a goal you can only achieve by hand-editing `Gopkg.lock`, it is at least a feature request, and likely a bug. + +## `[[project]]` + +The dependency graph is expressed as a series of `[[project]]` stanzas, each representing a single dependency project. A given project can only appear once in the list, and the version information expressed about them encompasses all contained packages - it is not possible to have multiple packages from a single project at different versions. + +These are all the properties that can appear in a `[[project]]` stanza, and whether or not they are guaranteed to be present/must be present for a stanza to be valid. + +| **Property** | **Always present?** | +| ------------ | ------------------- | +| `name` | Y | +| `packages` | Y | +| `source` | N | +| `revision` | Y | +| `version` | N | +| `branch` | N | + +### `name` + +The project to which the stanza applies, as identified by its [project root](glossary.md#project-root). + +### `source` + +If present, it indicates the upstream source from which the project should be retrieved. It has the same properties as [`source` in `Gopkg.toml`](Gopkg.toml.md#source). + +### `packages` + +A complete list of directories from within the source that dep determined to be necessary for the build. + +In general, this is the set of packages that were found to be participants in the package import graph, through at least one but as many as all of the following mechanisms: + +* Being in the current project's [`required`](Gopkg.toml.md#required) list +* Being imported by a package from either the current project or a different dependency +* Being imported by a package from within this project that, directly or transitively, is imported by a package from a different project + +### Version information: `revision`, `version`, and `branch` + +In order to provide reproducible builds, it is an absolute requirement that every project stanza contain a `revision`, no matter what kinds of constraints were encountered in `Gopkg.toml` files. It is further possible that exactly one of either `version` or `branch` will _additionally_ be present. + +When one of the other two are present, the `revision` is understood to be the underlying, immutable identifier that corresponded to that `version` or `branch` _at the time when the `Gopkg.lock` was written_. + +## `[solve-meta]` + +Metadata contained in this section tells us about the algorithm that was used to generate the `Gopkg.lock` file. These are very coarse indicators, primarily used to trigger a re-evaluation of the lock when it might have become invalid, as well as warn a team when its members are using algorithms with potentially subtly different effects. + +More details on "analyzer" and "solver" follow, but the versioning principle is the same: algorithmic changes that result in a decrease to the set of acceptable solutions for at least one input set generally require a version bump, while changes that increase the size of that set do not. However, this is not a formal definition; we leave room for judgment calls on small changes and bug fixes, and we bump at most once per release. + +By bumping versions only on solution set contractions, but not expansions, it allows us to avoid having to bump constantly (which could make using dep across teams awkward), while still making it likely that when the solver and version numbers match between `Gopkg.lock` and a running version of dep, what's recorded in the file is acceptable by the running version's rules. + +### `analyzer-name` and `analyzer-version` + +The analyzer is an internal dep component responsible for interpreting the contents of `Gopkg.toml` files, as well as metadata files from any tools dep knows about: `glide.yaml`, `vendor.json`, etc. + +The analyzer is named because the dep needs to identify itself to its engine, gps (`github.com/golang/dep/gps`); gps knows nothing about dep. The analyzer version is bumped when something in the analyzer's logic begins treating data that it already accepted in a significantly different way, or stops accepting a particular class of data. It is _not_ changed when support for entirely new types of data are added. + +For example, if dep's analyzer stopped supporting automated conversions from glide, then that would not require bumping the analyzer version, as doing so makes _more_ solutions possible. Adding support for converting from a new tool, or changing the interpretation of `version` fields in `Gopkg.toml` so that it was only allowed to specify minimum versions, would entail a version bump. + +### `solver-name` and `solver-version` + +The solver is the algorithm behind [the solving function](ensure-mechanics.md#functional-flow). It selects all the versions that ultimately appear in `Gopkg.lock` by finding a combination that satisfies all the rules, including those from `Gopkg.toml` (fed to the solver by the analyzer). + +The solver is named because, like the analyzer, it is pluggable; an alternative algorithm could be written that applies different rules to achieve the same goal. The one dep uses, "gps-cdcl", is named after [the general class of SAT solving algorithm it most resembles](https://en.wikipedia.org/wiki/Conflict-Driven_Clause_Learning), though the algorithm is actually a specialized, domain-specific [SMT solver](https://en.wikipedia.org/wiki/Satisfiability_modulo_theories). + +The same general principles of version-bumping apply to the solver version: if the solver starts enforcing [Go 1.4 import path comments](https://golang.org/cmd/go/#hdr-Import_path_checking), that entails a bump, because it can only narrow the solution set. If it were to later relax that requirement, it would not require a bump, as that can only expand the solution set. + +### `inputs-digest` + +A SHA256 hash digest of all the [inputs to the solving function](ensure-mechanics.md#functional-flow). Those inputs can be shown directly with the hidden command `dep hash-inputs`, allowing this value to be generated directly: + +``` +dep hash-inputs | tr -d “\n” | shasum -a256 +``` \ No newline at end of file diff --git a/vendor/github.com/golang/dep/docs/Gopkg.toml.md b/vendor/github.com/golang/dep/docs/Gopkg.toml.md new file mode 100644 index 00000000..84ff9d3f --- /dev/null +++ b/vendor/github.com/golang/dep/docs/Gopkg.toml.md @@ -0,0 +1,255 @@ +--- +title: Gopkg.toml +--- + +The `Gopkg.toml` file is initially generated by `dep init`, and is primarily hand-edited. It contains several types of rule declarations that govern dep's behavior: + +* _Dependency rules:_ [`constraints`](#constraint) and [`overrides`](#override) allow the user to specify which versions of dependencies are acceptable, and where they should be retrieved from. +* _Package graph rules:_ [`required`](#required) and [`ignored`](#ignored) allow the user to manipulate the import graph by including or excluding import paths, respectively. +* [`metadata`](#metadata) are a user-defined maps of key-value pairs that dep will ignore. They provide a data sidecar for tools building on top of dep. +* [`prune`](#prune) settings determine what files and directories can be deemed unnecessary, and thus automatically removed from `vendor/`. + +Note that because TOML does not adhere to a tree structure, the `required` and `ignored` fields must be declared before any `[[constraint]]` or `[[override]]`. + +There is a full [example](#example) `Gopkg.toml` file at the bottom of this document. `dep init` will also, by default, generate a `Gopkg.toml` containing some example values, for guidance. + +## Dependency rules: `[[constraint]]` and `[[override]]` + +Most of the rule declarations in a `Gopkg.toml` will be either `[[constraint]]` or `[[override]]` stanzas. Both of these types of stanzas allow exactly the same types of values, but dep interprets them differently. Each allows the following values: + +* `name` - the import path corresponding to the [source root](glossary.md#source-root) of a dependency (generally: where the VCS root is) +* At most one [version rule](#version-rules) +* An optional [`source` rule](#source) +* [`metadata`](#metadata) that is specific to the `name`'d project + +A full example (invalid, actually, as it has more than one version rule, for illustrative purposes) of either one of these stanzas looks like this: + +```toml +[[constraint]] + # Required: the root import path of the project being constrained. + name = "github.com/user/project" + # Recommended: the version constraint to enforce for the project. + # Note that only one of "branch", "version" or "revision" can be specified. + version = "1.0.0" + branch = "master" + revision = "abc123" + + # Optional: an alternate location (URL or import path) for the project's source. + source = "https://github.com/myfork/package.git" + + # Optional: metadata about the constraint or override that could be used by other independent systems + [metadata] + key1 = "value that convey data to other systems" + system1-data = "value that is used by a system" + system2-data = "value that is used by another system" +``` + +### `[[constraint]]` + +A `[[constraint]]` stanza defines rules for how a [direct dependency](glossary.md#direct-dependency) must be incorporated into the dependency graph. Dep respects these declarations from the current project's `Gopkg.toml`, as well as the `Gopkg.toml` files found in any dependencies. + +**Use this for:** having a [direct dependency](FAQ.md#what-is-a-direct-or-transitive-dependency) use a specific branch, version range, revision, or alternate source (such as a fork). + +### `[[override]]` + +An `[[override]]` stanza differs from a `[[constraint]]` in that it applies to all dependencies, [direct](glossary.md#direct-dependency) and [transitive](glossary.md#transitive-dependency), and supersedes all other `[[constraint]]` declarations for that project. However, only overrides from the current project's `Gopkg.toml` are incorporated. + +**Use this for:** Overrides are primarily intended as a way of eliminating disagreements between multiple irreconcilable `[[constraint]]` declarations on a single dependency. However, they will also be your primary recourse if you need to [constrain a transitive dependency's version?](FAQ.md#how-do-i-constrain-a-transitive-dependencys-version) + +Overrides should be used cautiously and temporarily, when possible. + +### `source` + +A `source` rule can specify an alternate location from which the `name`'d project should be retrieved. It is primarily useful for temporarily specifying a fork for a repository. + +`source` rules are generally brittle and should only be used when there is no other recourse. Using them to try to circumvent network reachability issues is typically an antipattern. + +### Version rules + +Version rules can be used in either `[[constraint]]` or `[[override]]` stanzas. There are three types of version rules - `version`, `branch`, and `revision`. At most one of the three types can be specified. + +#### `version` + +`version` is a property of `constraint`s and `override`s. It is used to specify version constraint of a specific dependency. It can be used to target an arbitrary VCS tag, or a semantic version, or a range of semantic versions. + +Specifying semantic version ranges can be done using the following operators: + +* `=`: equal +* `!=`: not equal +* `>`: greater than +* `<`: less than +* `>=`: greater than or equal to +* `<=`: less than or equal to +* `-`: literal range. Eg: 1.2 - 1.4.5 is equivalent to >= 1.2, <= 1.4.5 +* `~`: minor range. Eg: ~1.2.3 is equivalent to >= 1.2.3, < 1.3.0 +* `^`: major range. Eg: ^1.2.3 is equivalent to >= 1.2.3, < 2.0.0 +* `[xX*]`: wildcard. Eg: 1.2.x is equivalent to >= 1.2.0, < 1.3.0 + +You might, for example, include a rule that specifies `version = "=2.0.0"` to pin a dependency to version 2.0.0, or constrain to minor releases with: `version = "~2.1.0"`. Refer to the [semver library](https://github.com/Masterminds/semver) documentation for more info. + +**Note**: When you specify a version *without an operator*, `dep` automatically uses the `^` operator by default. `dep ensure` will interpret the given version as the min-boundary of a range, for example: + +* `1.2.3` becomes the range `>=1.2.3, <2.0.0` +* `0.2.3` becomes the range `>=0.2.3, <0.3.0` +* `0.0.3` becomes the range `>=0.0.3, <0.1.0` + +`~` and `=` operators can be used with the versions. When a version is specified without any operator, `dep` automatically adds a caret operator, `^`. The caret operator pins the left-most non-zero digit in the version. For example: +``` +^1.2.3 means 1.2.3 <= X < 2.0.0 +^0.2.3 means 0.2.3 <= X < 0.3.0 +^0.0.3 means 0.0.3 <= X < 0.1.0 +``` + +To pin a version of direct dependency in manifest, prefix the version with `=`. For example: +```toml +[[constraint]] + name = "github.com/pkg/errors" + version = "=0.8.0" +``` + +#### `branch` + +Using a `branch` constraint will cause dep to use the named branch (e.g., `branch = "master"`) for a particular dependency. The revision at the tip of the branch will be recorded into `Gopkg.lock`, and almost always remain the same until a change is requested, via `dep ensure -update`. + +In general, you should prefer semantic versions to branches, when a project has made them available. + +#### `revision` + +A `revision` is the underlying immutable identifier - like a git commit SHA1. While it is allowed to constrain to a `revision`, doing so is almost always an antipattern. + +Usually, folks are inclined to pin to a revision because they feel it will somehow improve their project's reproducibility. That is not a good reason. `Gopkg.lock` provides reproducibility. Only use `revision` if you have a good reason to believe that _no_ other version of that dependency _could_ work. + +## Package graph rules: `required` and `ignored` + +As part of normal operation, dep analyzes import statements in Go code. These import statements connect packages together, ultimately forming a graph. The `required` and `ignored` rules manipulate that graph, in ways that are roughly dual to each other: `required` adds import paths to the graph, and `ignored` removes them. + +### `required` + +`required` lists a set of packages (not projects) that must be included in Gopkg.lock. This list is merged with the set of packages imported by the current project. +```toml +required = ["github.com/user/thing/cmd/thing"] +``` + +**Use this for:** linters, generators, and other development tools that + +* Are needed by your project +* Aren't `import`ed by your project, [directly or transitively](FAQ.md#what-is-a-direct-or-transitive-dependency) +* You don't want to put them in your `GOPATH`, and/or you want to lock the version + +Please note that this only pulls in the sources of these dependencies. It does not install or compile them. So, if you need the tool to be installed you should still run the following (manually or from a `Makefile`) after each `dep ensure`: + +```bash +cd vendor/pkg/to/install +go install . +``` + +This only works reliably if this is the only project to install these executables. This is not enough if you want to be able to run a different version of the same executable depending on the project you're working. In that case you have to use a different `GOBIN` for each project, by doing something like this before running the above commands: + +```bash +export GOBIN=$PWD/bin +export PATH=$GOBIN:$PATH +``` + +You might also try [virtualgo](https://github.com/GetStream/vg), which installs dependencies in the `required` list automatically in a project specific `GOBIN`. + + +### `ignored` +`ignored` lists a set of packages (not projects) that are ignored when dep statically analyzes source code. Ignored packages can be in this project, or in a dependency. + +```toml +ignored = ["github.com/user/project/badpkg"] +``` + +Use `*` to define a package prefix to be ignored. This will cause any lexical wildcard match to be ignored, including the literal string prior to the `*`. + +```toml +ignored = ["github.com/user/project/badpkg*"] +``` + +**Use this for:** preventing a package, and any of that package's unique dependencies, from being incorporated in `Gopkg.lock`. + +## `metadata` +`metadata` can exist at the root as well as under `constraint` and `override` declarations. + +`metadata` declarations are ignored by dep and are meant for usage by other independent systems. + +The root `metadata` declaration defines information about the project itself, while a `metadata` declaration under a `[[constraint]]` or an `[[override]]` defines metadata about that rule, for the `name`d project. +```toml +[metadata] +key1 = "value that convey data to other systems" +system1-data = "value that is used by a system" +system2-data = "value that is used by another system" +``` + +## `prune` + +`prune` defines the global and per-project prune options for dependencies. The options determine which files are discarded when writing the `vendor/` tree. + +The following are the current available options: +* `unused-packages` indicates that files from directories that do not appear in the package import graph should be pruned. +* `non-go` prunes files that are not used by Go. +* `go-tests` prunes Go test files. + +Out of an abundance of caution, dep non-optionally preserves files that may have legal significance. + +Pruning is disabled by default. It can be enabled by setting them to `true` at the root level. +```toml +[prune] + non-go = true +``` + +The same prune options can be defined per-project. An addtional `name` field is required and, as with should represent a project and not a package. + + +```toml +[prune] + non-go = true + + [[prune.project]] + name = "github.com/project/name" + go-tests = true + non-go = false +``` +# Example + +A sample `Gopkg.toml` with most elements present: + +```toml +required = ["github.com/user/thing/cmd/thing"] + +ignored = [ + "github.com/user/project/pkgX", + "bitbucket.org/user/project/pkgA/pkgY" +] + +[metadata] +codename = "foo" + +[prune] + non-go = true + + [[prune.project]] + name = "github.com/project/name" + go-tests = true + non-go = false + +[[constraint]] + name = "github.com/user/project" + version = "1.0.0" + + [metadata] + property1 = "value1" + property2 = 10 + +[[constraint]] + name = "github.com/user/project2" + branch = "dev" + source = "github.com/myfork/project2" + +[[override]] + name = "github.com/x/y" + version = "2.4.0" + + [metadata] + propertyX = "valueX" +``` diff --git a/vendor/github.com/golang/dep/docs/assets/DigbyFlat.png b/vendor/github.com/golang/dep/docs/assets/DigbyFlat.png new file mode 100644 index 0000000000000000000000000000000000000000..e05dcf38f0c792a8b4078898278b117992076e98 GIT binary patch literal 393796 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

RenznUBCUrvwDW2^-W{~}MrvGvRenz=Oztbg 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

m!pvRhqX* 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 \ No newline at end of file diff --git a/vendor/github.com/golang/dep/docs/assets/DigbyFlatScene2.png b/vendor/github.com/golang/dep/docs/assets/DigbyFlatScene2.png new file mode 100644 index 0000000000000000000000000000000000000000..62e2af686a6ad9ac1f48c4fab3cb92460ee9cddf GIT binary patch literal 550791 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%0Ai6*ubs3wD}nv z79cHHXbE_7rbBlMNbnzp*Jo7|;d!!M>wO16$*xe1jJ-Ppr-4$%7u3uC8*4`ZCXN%P z6*B_~!2nsyj(T8dn+m3a0>u+jQXT?_zZIA8C8Dt}Oe{c6gFcgsQc1Vx7bhhlOSGg=58vgC7)>0vlocK+f$^rBN|93 zgiQ6&8e{(P&XA#EK1`_^yZ_vbebPBgi}kTz5Fp%Jd7TH|6NLmm|ED>!tmqgp*rV{D zd>TPx$iB--{oSp)^!jIQb_?&Iz>7wIhgnztXzA#KRKnX(-}BdMS0v7E067piwUe!P zAtSyfp*pNHj--fl-O@j0pF(7qAkQn{8ODVw0yqee_64pH%qWV4Fa04)YzzB6ZVETG zBrur;od1XtS^yHf*g+gn9|W&$znta{E#SJ$!v`$>;)S0>bF3olg3x5Jt1LDZzkgM(Y)7s?G zE(~*qJ54-Js~fu_q=RFrc|U$;<5lQ82sMS2Cs|E^*7{bx{ttivk!E&wDzUz2hftSr zDEz7Md#K|OApNz=+~C51ioV|5^5C;`9p7IaKltR%4q;^KCB!rFe76c4R!CxbTL``w zSU9sAF*y5+=oaQAw*8QWmc9mLqpjYglc4!Cr

l@`>^^y(G92y(McNiq@P^6JzdPP3q)7iFVZ{+N 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 c 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%0ANh=?Q zG6mB0gMACBC8*h-eW!jkX}-sVK^_w4N`ZmsDC@Ea_-0S3JQwqy_vnU z4C7d=okDrLmgo@J?g1vy0d#R4o4Dv?5ag-(5{_m|95!!8P>aWO*$e^JQ_?V|%V zoNKtW$_S(s97R38JJ)d74*3sUb2RxtcD!PL9&|;WKQ=IdzL*cEE&3@b4vM~#z?6O* zh^(h;3$%Acj$7Td`~~Zim^dcHD+!7OjQoXxo=wyE!c%M|o<9ulNWaXwblFdteYW?v z!~GABQk}37<{M&*TQlcL=i7O+%GoIg_2#cyRPI)tv`^bK8oG*DFb;$DzmHg3L9Ij5 z`0{U+*~|oYKI$Q4Kz00k_P~&<|71t@f>4=>j?ISk>f_}L1y2Ar+Ai~zT8w@ty-k-I zXosrX_=e!iq8b6(2hVffQc`7qX%Clk^0doU-aIwIA#M@;Kwe-pWVpdsIWPk$<;t|Y z?erOmF(kH8qhi##mz}B%CAa1NaCq;XG+c#=Uw;J7z2c?I$B_5|5i+45`~X!Q02ALt z;L2KwK!-rWPu-|mj@B9=4&^#W1+Mn8!=)*JV3)+Y;G?zc{uecXGb9APE=PHDeb?sA zJj|mBZhbUTU4%=9pO*7%;Lg0gzvSdaw{C(ynxzL23Cn`o|Jo= zT?PnG;m9JqKh1f~VCDOlh%kF#a?wa3u(=-Y-Zi=%eZ|Q=W?6sl#|ut)3yX}#W7x1) zrg=Fz{em_&w7no`UEjzYA(tlM_CUb=0VI(7|HEE0X(;iwJH9z zP|IG?peLc7fbslh7CIARI}%~A$YOe$$3}8=qHC-%ORag!fO$;<2CPUFv*Aj5N%JJV z>)$K@?jH`5CSP+6(D+q|-ptBoKf2wgL*iBHSA9i5x7woWUWoK^{+8iu&6r-#TA(dz zIjTLn3u{steFj?#ogksnY9@nr1{uXb%%Yw1Ac=`(yy+4d#m;O|*ixqX@5p1~r*IlP zR#kP>SND&&9+F1%`Lo_rHMQ54zH6j4tCTp0h)5Wl$qO{JTTQpnUPx}v z@=9(xU;QzuSY&t!=Q4UPN3Ujg72G56P*%a;tO9OPq60tjjJE1$G)j1y^jkqylxD^@ z;`3RfSJN<8uXDws%)jBC(GzU1pz)XIWK`&;AI1z4xkGbOb2Ep0QS z=6&nq0l4?m$0yDGf!2WHmaMzn)Urwo_Y$B(M%`egm-PnJtKHqwh&Amk?xdG3qhU2J zEtQGZ_oepk3vjSuiSm$pQBza5{rK_2_u@tfJG)3&81~KX@d5vmYx9LgFmmI+DZpY< zSoyVkt}fQLZ{`E0T}iKFD24WzE?zEBdHMV(HRC3ji8DR}%l$Awr}(K#-4}C+L@0SV zqtx^2Pi@wdT6SID`o=$`Vhh%-Hs!C3K`mqPCt2e^%_6<=9@4-8(=JhWVQVAIt6fOF284WZI5N`~w@Pqwp`y~q-`gBl|3AoqK z9`!ZErAz8OB8noMi6HV`axRAV1F4Vw+a_SlfgBdljf_#y@H$<}?yHdRQJ(?{=)S-o zY0Er8i&2~H=4EFjPWKb~s~D4O{S01acGsh$qYXw&+uLOmj+U7R7v`lsZo2*3yRkj? z5=I!3Q`%C$u{M;*YC3{=h;D-M0SMByyJ*8%%|3}{7UxCb;q-Ss7d&;uj>q%GllC<$ zl&R+~@&dx(`!|sjm-2X7c^1fH;S45XHcaTgUH0q}SbUN+>%8uQO*TTZa{rW#TMh!_ zIzui+zkbZTel>oYo@wu1cR?45#@)MjjVR;USXq4_`{$tHng##BcCnil5^nyMVynXv8Nshxl#p_su*rziqVQNAsk)tQW#p3y*2BjXeHLpzNF-x)d>VNf;rHTYa; zw>EF{#|~7Hp}oV;PlvqwpJe+(UTP=`C}KuE z`MbY#>IigcTMx!C$~MkPq$V)UFCHi8O$35Y3OdYsg;u~DTToenE6LPo5%IY)C|lQm z?CkfNek-~4+5>GFq%JkgSF$u2a)nZwm9WgL{C*U8I;?7qXLNL0_n~@zzc{`BD{Nx} zU%GDq+SaP>v9WDF4|j z$c;yR{T>&@n!=meK|!%oQ~=3^H&EF){#LdR)B9M;x-5D&UhKL^R79;xx1XjiZgX>U zeJlAanc&xeV4Q;hCEyUS&-wq*JZPcd>xE4Y-uU+HoPS`y?Rr6nlF2PK);1bMBl*$rsD`% zJNs!DP#rs1q^W@G2FwcgytgjVx><}%Oe|L=8!#=wUHYRxUE zVU5jDI`#ewacNrxE##bwq;X6gJR~@K%TB`NW6t%{E=t9g_@iHq&o<74g{i>sv2W0+ z6jiyx*FjL#+41~r6U^Bn-U$@Y{cyo8s-%`J|M`mtq{)7*ZEeJyY_?>$97P-{YB?3r z*9m$&1^-n^5!(1d+zH06ARaDYG;kVnkxgJ0NCwURZ5Rn`FpP?Y=)ifulkhI;^_%rw zh79#rn{(iB71iqpGK{$H3m{;xxS3fAB47WgM6HDbAv(UssUos%N@AaXBnQ_|yfv*|&LlSS!J`88IXvup(7+L9_8yetM1Qc?o~ zdMOBSvItXZCB8?&olnXxLkA#CY=SUhhxb4lhUf5dg9C-cC%?C*=&4@i-VOU2QX3Uz z4_^6|w1H3r4)Sr|WZjR(^L-6}k?kLE+yKB*$VY#rEMOKc-R{)pY>FUy3fNqTD*XJ- zJ1^I-f=&y)IHh{*<1F_@^_9XgA+?#AnK_4d1NBQkg6{^07)Sz|Z>8aowyNa;eY*Im z+@C=zVurQhnE&vMF?J|Hruhzf;?ShQaLx9biROj6wnB_eMy#YFpyCv-WZv=Bf|EA; zVJ#M-pPJ|iCIri9p2Nq0CfIuTG3A0**hW(>_%jEE5-kiJ zW*Pa~@jbU}41qw%NVg~!mz8zoD`H>i>?$*lCA=YjNAicbQQX*pEG; zkDX3!(W<5f@SQ3}39nx5LTD69ydR~^=%HZ|#${(`AESkbUc@_I-Gdzh#?!R10}<%d z^Dfx+Rw(o3NzroC)&-DXHll}4uOLq65X1g@DUc?7(i1%3HcTMK<6xT(z0S&~}p z!1HYs+AD&C6I1i#nV~o^v9L%>xBO)AFUcF^C?78oqP-0hfX>B_PBqq!==;rlKXV6@ z>&;5+M6oa4xwLrJk;7Ifds8`%K8?P^%w6?AS*iA0bacwlebdx468=u8SvbMi7{nQV zv-{+q!qrFW-vqp|%`PMjCuX`O*2cR1ou|%y(-3CMrg}faf?&su$Uq`%>ris)Wke0q zeZG!w@8Y=tOz#dPbH<}IA>o0}+xSbj=_-SuObg_xxfjWM9P5;!;FXO~dvFJX-jFNU zr0Z@n%F2bDx#In4Z~^seKosyaXlPX7n5wF~(rg(SZRk}e3QwOtwKKt{10gZiJehef z@7Z0pGPvaPViwG%g$B452+SOdBpOK;8T!*zcC|G(f6Ly2hMa%6^4JwqE!6&m8Mtw+YkcZ5mTp51ht|FC|5>N1N;t}9EwfzT)`ijZ=c ztOOnUgpqKt*XDeZe6um#1Fk1D>GfA?j@VGb<>DNg0d@Y8MmAC(C|8|B( z-RtA0lLMf*1DlBPgB44e0OVO8x(cAQZ`7L^>sp2BF2)#V=_1c&50LEB?qNq42*%3* z54Bs3PQ;H~5*-9g0sD1Wr z2kcHlS#hW)U>OwxD>m&=%Nei{p#18_QvSqLL=2wig*z_Tp7L6?ooZo+hoQ^(tiJHD znR(pLkw35Y4^|QjLd+c-mclZZck-X5CFJSk5~Z}Z_L1e8o^!_uOrjktx4o4+dJF*` zunP*Hb)7MSo`s*E)DIo~E0v^{qi3^k#5W3JxG%IaqPUC{@!;zNpmi39ni$4#1Q zFr1DU#UTEP^E7V&dr;GH5qSmggEM>&pp+CeCpf*Pq4Td(OVZyqhkh&QR&(aRSJds4 z!kO8zyhvq;gsCjJ02NsQB3(cO%xpbzW86-jD63kJ4UbZQeq=KvBg1%$%ofpo>;az` z4m(q8YyE9EXo7uK6w@?qV}~U4X?XS;<^w?fl$e+pn!&D;eMBvXckkbGaCu__EL(Ro z@!rG1m^G2yu(U@w%JaWSdtt4>0uQgedy(8J(t#n3{?;Emq8Be-7*(9a6W@EL$GD;+ zgL)BteJNV`Gbp{0)_zJ-+N5I-l};_nrGWL`rTy6SoI@lXc(GsKnMoohCnry0BY@g9 zfl~B62i+z+;M7lmh`mZKq+6CN0hI&N7W*4UA_-$`hgxj$Rd@V1cw zKO#cFJO5lOcMY_*eNVhAct`#dv+q@SQPW%aLP(%2MtLJwJ6EFLXv0hW~goEnMb52iZKC&356v-oL@Z4m4re!S4yGBqSvDD5_A(d-v|u zd+K=-?|W$4SDySITet}koR)L8uttdL;(s3lnv(Gd`m>Ddm`*d%v#9|{&Z4gonMx2j zv>9%NUe`@XgmasA2xz!dpmO2LL3H&XDG_i_q$QXF2x_PFhh47pw#xyCJSYafC|DgL z#y4TXBbgBr@XMmo)%=ZO#&aLIq0dfLM(6&Hm*m#gFAD_Zj6Y|XZ1})b4|b@}Fj>=1 zhUf#ZLQp^9r$aRqu6&Sny2nd`12ZOlKz}Rxm0RwL^?C;V!olI8fJ==YoYwYme=cjv zO_Z6rqpoMf{xFK_;AffbYEe-XPB(mcG&Hqb4WHM|81xK`@}*&*-~6>o#H64 z)21sja#VCxKkwl;ZG9Kk0QubKC|a(ULh-+9$N`6HoF%YXj38%KchqPag?ta_-6~H54#aN4Gar6D zV|%!1bSVu*RsV^Pu|Kqf2Ez4k&b6Vyji1>(6YFO(wxP7_af=1-784qhr1Rr^n zJ{7S)@jbO~*E_!+JUhQZv(n*Ls}S8 zr9(nOBj=nz8E=4oiEWL2t%p)laxi|7AZTUR=J*)mYNR&;>HVf%=v-|pvZps(h(r}( zdU$ZKT+hWnKpN-gd7i4WtVm(NJd>RroEri04bKvm9;|I(Wg-yCM@qS~fXt51md8D9 zp6vOs9a~?bVt&c;yxn>jIn2j1TtcK`iuO?@UV%`s!d~`eMtX5#m8Xhe8Ru_$mW2NEuBXuER9B%7beDsul(-BE_``0rAquZ?Q49aS+QuEiraRwUEr*|(L zNWL%V4Dk$e{POwpn#t{3k0Knr>Lw!{EWEq+K2?teqgu@J)D#l9rX2*PovNm{T;Z>z zQQ^@imNIa4s5)u{Q2o861vy~6Bo19wOaXXeAKiS`F zORj(2{3%&wY`kWFLy4-XtWGa9RF%9uASW=ViuX^r>!K;6SzS{-6M?My)6AcHVGXpu z8A)NFzm$}g0T+|Ko%XXC4xFrN3QlDXK2Il?O(zUADBA;ud`Sx@`4*cfHR?~Qmln|*u5gLgU0Y$)wMbDXU})T;WYo<( z`FUHBmEdKoiqi@4tM}ds(Ef1$8Qv>_%^3F({l%NvCVg*6lFdbA!@hne1TW>R zqU(ZszD{e^S}l1r>MEp_Pzd|PbL)7X9F34BsT078{{H>@ozC?gS@zX+S#*))n|cVg zO=NyP>nhQe`hoF|wRJ(Q=Uenh}aP8ieq@}ZZH6i&~(i0bXH?*sPU4lPyH zs}4elsl<};RYnP40epXU0S;fBqOa2%Hm_>uE5`TBy~Vg^O|WY!w_OiEpT;2rWO|Ul zO_n$a7 zzwL^(AiImz;|@uqrD|vcM;PcKtYew33SRhPZtH=mZ`ri4W~F@Wy1BWvG3!0{#t$K| zKH|eO@HUxc`wwbH$X3(mU?HbAS?p386tq6m9xb^-VORmGE~ihe9VBRo`I&%h6o^Ou%2k|4>0;-Uy!{ z@@~y0rb5}zI^@pb#Qa@z_|-=d^3O=|@tDA6JbF3^bdElY%X{u~?ffwW3>V={Qtk z%K-8W!=;w@@R~El+O4dm936=PEYXi6pbuOmId%=n#e(C#lFattl-ZH`mSs^)jLr4H z>!^v_t5G^%*z|t1L(Xg9Fmvx#`GjcNJndIUy;;~0wYuG=(03C?CE{DP7OGnw$Fj{8 z9n~O6^iSl5~V2I1CiAEd6WxICj1dRiOgVrEzm}zf5=ZD(yag zs;jGOYEk@rY4DJwIyNLT#~m#+v{y+56>`hVn+?lmPr0$*y%c8Pq7vLwzhIUs^^E6Z zWK1IN_(e)azret!3bT1zH*54JS@XY^!V0m~L#(}Jy4r=dpLCe97|<9TD-IJzd~ai=I^JZ<D4D`Z{PXld&=khR@5Sa7bM?04ieC~+Xj3BNIg7K-2@cagcXIf9q_|AV-V>X@ zVD?P%8s_4nqN9_uk~@xyhZRkm(S;|YM+jcjNGDF4cHVq+nOfYV+lu%EEivP#8jU>K z>QA43g6#;x@!fkv-^rjAmE_M-S!$YbICxGRAB;-6I4$y6VG7WsH-VM&(41u^e{D`q z2%%JV;qbdwSsIl)Fnb#IX&lQBN6Kzo<>hwn~`6LS}z9<)74`3xqpsPXX*G^S2}ctsBp}HZrfh} zk{pW!96DlI{c4hmiVDoBXZmi1z z4)@I@;f7N)u=v~B-scnpcL_^-m_Z1iEG0jGHU7+`L~CRCxs%1H8rxDKIT@MZ^(5X8 zk08taK>MR)@5#t0oEw`ZQ}FB#0x(R*isxJOi{st)n+03Q(fuPyI%2pDwIS+Q2(ko< zmk9_M5{4)-2}r1iHu0TpW1`WUwqzTZc2=%S8!*0dUsV}5*Cw6X&5}<9VluU<+pVMIi+7q0EfYjkEm&8N z2ZcpvtcS?JO~v9OH$xv9D?0Ao9&jnM$ZnnOtU_*E^Qu`+1&P8_^Q$P*f6RgBRb*~a z&E!6{qo)w%X6`zP?hgcVH@tOF9nJDn1nm_KRwhKeXaW-`h;0NCO|7gH11Z<_GG>C-@IAL%&(Q%=z0@;^*8P&PM73hf}>-_v{S&TxwSR&%VWFR z8=e`zjc1|S1i?|RwAKGsYPnmv74}z7&Vss?Z;q4Lbvq?@FN62? zu;^6LCtCB@vci_*;qv<2%C}+!?2eM`%uF=2r)v2htMd|^6$<2F%1?wVkMCB(%n!C>-I{{Oa$Sf`K+V?EY+^)k}#%`L7 zh@e<^5=cB=ZW@U8f>N9C^Eos*K@ab2$j9rgo4&v6hNvh%)*tk|n&~^cyX zq)Rh?VGIdeu`;o?^OfZMr)F>3?d;wAfNz5b^l&-y=C4bkZ;%(J62lb7JQ0T%oy{y$ zL}w}M2a`t%jS2mNRVpge5T8qmNzk6%yVtNGT0t+O-&MSR>_QVb$z4O^TI0OtXpP9>mNnR*x}dGlg|MrF!}(2e>5 zn`6`of}aKYwp8Kl-ch0J7H`kM0CAb+;-5bf&p+#KI9bR4L~f;)mh$AAdvm^g`4WXj zc6NGxvBA=THylHeO+`*FX>N{fX1+v3Y3*8}YUeVsRu}i~D1UV2fqJZ9FEe7$Gp<;& z&Xl$}A&0Tsh?S>4O60_3IL&|PMwRZ`WamI#Nm6|kb;1(|o#RB>$gemLZUK4)l#bec zbe%5q*W61)q@eKNK-q1DI&?#NS{SVi7MIMVknfJO#Vb8T?Np+c_Tq&Cf4w(AxoG`T zeTC3o<>hKTaPe}}@b(@h(Cpk}TQzSQQRT_!Bxp(O`P4R|T56u34JovshJo>r=WEpg zqKN{bg-UI=yshuud$8inL)#J6AY0jh)Gsb16{^71$1z-#pt&A)O{WrPjWMNl-$o

1YvmGAgzoY`oFxtUpacfqafBgorJ=#HZUpzDZdOKaMK@g`Ag zeFFpjfBv|0)z!Trn@@~h*=!rWtE5c35cf&H82?TGyNCBh>C=d%5q8Z3ysJj9kwu)6aHZ5&L(L^lDy&A+?&m`I&8MZezLwP- z9C+@x+`48*fI_UMih$V{w{WDa#xtysJs$z$4m)f2M|ioic)6UtP@KS#JC=yQ@X`{y zq*Xr&rycW_!2#6m7C#~>JGg_e0dDUyl7suRFV#b>(kdw}%}g(Jg;HZx_Hm8y>ekW8 zaHZqDkr9gQvD)C^t6W^mfgWB`ql0-nrY~QLd)F!To*W)|np#?lD|EiN)W+&Lx#w0B zKPDqd>x$ZeQKS1ouW}k(*oQEhQr|sf@-lm@w}O*(XWyXn=0;Ka=U~wx>*TS}MA6As z$^fRTkPG|zwJ1gV(=3W}EC`()nZUX#{mDoRYb#=CX_O&Y0{xW)OBmaj2;zlBijoKC z$0;P8P_p!;gKuAr9$JMtJMI}mz1l6K6n{o_^!CVsO=rC3tHkj+@vxlrp@F|$+}f70 zN~3c3+9h2diNuTRJ;ghl{dg7{O@{6h)N%jICP#M=6GhmyalH?_+=#nkW?Y;U)*K(w z$FD2T*zolef3mW6<`6>AWb_3c9_Fndcw~?Ah~q!j*GHK03Fm_OG+H_!U#o9#ADueN zm|;ALls{gto?Hv)b7k&jMZ70;dpN!wazo+=yY$F(3k4xg7B-`G$(Cnf-1Ek=)l(ro zp?wqSWaL|Cw5mM;job%Z*Z!A^-3|qSCuxaz36iZ_O|5f9Z#zu=n=8Ra(J>1LBce42 zhnd}y9M!r!ctca@ey_IQ)TR1Xe@nJBW^kEZQIy?-wJdc&@mz1z_AE!9lu~ zhitpt{=|#~*KHL;O1ay)G#N$MZ0G;1`sY+J_A;~WV03+SJ*d-b6ZX~*VwS(mD6r}I zii5Ght?NKp%XAter~7wNQ*_y_zS`4z&c=3HRe*m?u6&7YPfLXD8k@Lyp^G{+)JfHA zp?^U5Rb^#mT%I>98)y}3U)cgmWg`$H*dY1SBzJU0v3oD+@#6^~Cj~;|{hJriTa7fjQQ8>BE^8K*e;u#VA;`Bstci zs;CI~9+8M*e^@15j1n$X&#*mH1!gHDJd(3~?6oxu->!Rr`LL3pzT`1%v9blr#Ot6c zV_L*>MV3;jrr_G-A(>JxP4Jsn!4q3>rXA&%wg>ob+J(JL+h6AVG#}%)KYj9%|3HrV z$)kc4A(1VS&+MnY#x9~)xLe)34*12t$obNU;bR1*Vu|C^o|9cUDj>PpBT1WfNuLNU zfvA;~Ov<>sSN$o?gQHE*iK}_ONXF{O!`wV1Rb2+goW>H}rY0x%n_N>r31S2s0j+R~ zNOslL5F+mm>>rUg4tg7Nywf9&c=PLTogKcJQNMk(5?xgYV3}`P%HHUI=qH!uai8t- zQIj5&qg>ckEivb>=nhmSaUy>cG!Lba*`soAH0qu0nfFmMuYbKL?Pd%U3ExgPHUGWs zsjN6VN4h5VR14VzFRgmj=`E)3e)8EGn-$p~Pg{L*;0qfz<2P3EQJd~A7bqGcU1DEU zPu&=$TYYn?Vnf)s-2J{9mVXvvo3QuFW$v7wd+=+$h2{+_#%*iANEANcMxo~gIkU&= zvIhsgsVQ?ta}EN^+DD!PiS)Es7ngTi%k#^|b`ONzwR*Y>Bnt~F6WScB#gRZ@&R7$pL!ro_ftwguxtkz*qA=u^!&=% zIpmRO++KfR@G_jZ)2W+xVpVFzxt1r7fEo?8l92sxPFhD3neKjTYR$&=;AK#WgyT=~ zB7t%g={1a7;s=k5JnGEytvH0-e6WeoedJ^LuW-E9nl&kIQ_^W&Z+Q$CLxzH%34I7~ z|BC@fT9X+|K>NF&HbMllYRbx4@#`Lvl77oahbLaerKR=LeD{$@agTn32KPWAlm`)E zR5sc(Y^pxM1If*l{M8H4=AUEe{^!r1g69F-C;1>;0)`5w+w`S2(*HrYjd z%?A7A9@~oK(4APb(h!zyTDy2S2|4o*1c7Z&xKwfGKj(KSw%6Jp9~i%v6|umC}r${ zebsoh!2x;{`q>vs*sS-zq>KGvrv>=X%iI-F%~3k08+Pqy7?T%q@g&bmtElKE4P%07 z@ODc`Wp@S;J0e__PTFhxk4A7hDo5$j0sGyrfThcjxXx!|n zzOI}LOxPCb_68aA?ydN`IoT|mZdiiUx{t|g!An_c($be+J+87?KhE}4#82~P$2803#2fT!Ybm$RFjR&tF6_u13?osC8A&Ya~PX#t*uiw z6cL^~Z$54uRKw2Yv#C$1%pr~NFbunLD4pUW#)o13P?zM&w<3PMlclnaj*fz}ylcds zN$JR46ly})$;-+^-oT=e=AK|kH0)g2rGEFd&xpNS;435#EeSToC|W_%4qqT-;bk7) z>Qs*9l~JILLrbcY68d}N3I#F5j4jv?6h}>*7D^ax07@_uZ_P|lky%|7hHXoAN)ec`4Mj4eM*l%{lPyiQ_{QJk z;TG*ElANscb47(F_vn+qo0SGD^$$`JUkYqjm@lfkd5Xzo|JA>G#a4<%Xbm(c8$PRj zFR?$I+&IY|$Oc^tVQ#{Jj4G8!3zGZuqQcREZgn;r`+C&<+V zMyc>giS`ZV{V~7hERd+|{itj-@v-`qjiZyyyp!6wPbDg-YoUgRGasT?MuAQ#pVR~v zH5@IU(qGv3mt}mlOPpKzRg^&t$>y(08s~=u9@y9Q$St24`MO0j?Bo7!_e=t>>35=> z{U3hRdQVyoZ_H^2ds$PSChC7B${_gvw(5jT4RyoL=^a2M!T>|!?kT`BtJa&mq)g;= zaX7za14WXy*9pcvtxImVeg>W5#L_zDyRHRLcr`m5qj0R%#7kB$}I>E9=*>(0)7uArC~&s=0fld=z-njax9m z6bK~1e%Rdc@$n26-b~EiQ(_K?88P0nYMSjTy1yLg<;uF506~0zS5$tRC;9v77C&#b zZP)mu(GU~~y29Am@#DKM%!{+~2}5l_jHwvW>f9ZW*^|)j3n{6u_ LbKWKyrtpY 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�xZ?4V zo|(r>b4Y%iLbsC$ae7}0jofLmCsEKuC07D^>-%$I%p39e_@tMg1*PG6Yu;61(FoAE z9=R01-QL8K?G3|enQs#{PX6JSeXs~O7Ias*3jMfh#U-t@T{I1+YCv|N}%roC+-+qS$ zf+DOZw2dA%cRb28FyGXCco7ci)P!gczFVdxN1NEFrXAu-2Y+v}3;_@qplighj*1>x zoHsL9_{_64zt_{3q1h*8D4gV7^Rp%}rvyD62x@bDUvT_JYHum&G93kGi)m5p@!Om< ze&^$s;I;C#z0vZdAVSGhHif8lJ>CNd1MQt%AIC9j-{i~xV3X8OzkYEWS?IvYkku*D zd*-x7MWrnE{JDnjPYHmTE3HNIn%n+3Q9}+1vd^_O$$mHxgj`<5d-|$&yZK=3^7&>C z0Y>8L*0;cquPWWYzzM~yboGzE%p5Tad7K}}*eqB*X?kJ_UX@>%HA)&hVO{ge{*Dv> z5Q*1u;N7Cv5aQm1fXRaxg>w71`L1yR3T>#%0Gy(^XxbF_Tjc!*e(dz82WmEr)?d`h ze8a@TDWl9+fNmq<$Y6)*HLXOXX(_>%KrDBlZs{01CME{z^xYR_ojSj|Dczi$_`!6T zXCTkrYVdBpU&)WnNm;q?ZS{azWWT2?!0<5VYC_3-Ax>QLpU(EaLR)Iu3*`(o$%41X~5I(&3F)|(fP*J_^01oPk80b>odAY*B*ry8Gd|Ko9&pN*)M z{@}d)B1s1_Iygn%fahcA>4yq5eA*^8^aE(JJiJBfmn_(c`DeQxyj8q!YRU*u4A3IO zGhmkeUosm|aE0DmYb~<&fzbAHge32!1`1eivOYHobjxA9QaT3S{W0m;@>||#e5891 zewkl*P5D#%O`7PK11qxe8N2QW&`kE16)`kFT?Eh9J5z>3ARh2r1)==K7jP3x+$8`k zpO6BxdUGuF61JdnNYlNh6t-g*t$y@Je=)m?$ySmY{Z4`F0thhHa`tMP7=Ou$K70_y zli-Xbunvf_Hw zVp>K4DwJ)2C$hu^L!n#nuC)HtVDv!Fsv?lv6_8rYs%+wA=St|IXuub!!>)FK1t0v@ z#oo*vS-o9h9&>oAP7j57+^rh-XnbE>QOru!#$uIug$=F~Naa9TpvLfch_;Zs3Lf2| z#yAa*C_?xb7~9ZuJC|Jk&RNZGAb&W$MB9i_@gFNOWaSb0=Joj@*FEGr%MRFmJr@y$ zkUH`f++|i>C~m{VFd@SCBW#@j5ZSw_eNFoidfC^5TC5Fgu3hh{PVsnmj5Jm3dFHQm zcon4*qoShbMYh(DPU{_8w!GOmDtqBk)vt0La6>o|&=bHqXipzWb65K)dQMLm31)zgs^S_vgE4e5Npi^NeQO&?b#i40pjF{*btMph| zs`rf2QrmrD|CugSul~B~G(dGE8xs%|%Hn6SPon1r{2fJ_AYz}4QgbMCcRfuj1{4V} zeTE87W)v`rZ-K=L_==^TFTrHDpf*5qBt}`mwc-qJn7clEtNJ4X^O`ax{BcllB~SNR zJ$JRos_MX0ej@KrcT#Y&_$Jqg(&N*5Y3JV8pTX(v5As?R6cp^q5`IiHWh>Cgi_Z3d zH5YmeAU&f%7=g*WHcMkH-$NM6P%1YP=cLH93$ArYy5GAnAKB_v^o&bhORIm6flW@!VAK=4+1!>sbAOym?wd z*fwWOCvO0+f`8UBhezhzRRgn6nUl@H)Ff5}JWxWqf{AYM9@z}VX;M=wYBst+%kz^4 z6teR{Bn28)K=04#AnU)YA4TZ;sF;|;l2;v7%4@nN^9^1b-0bZ48S)ZtgA-yOe!m3v z5%4zoa*E}qHj)W;S@mtWet8E|NPmVL-a!_4#>~M^qY!>6YJ7>BkL_)hCtihC1&?uj zrQU@t!>b>4RW7VxGCs1*kFC%Iw|wBwIc5K2j?&UnxVVN|(F^*eU`V*9q(m4KlOR2U z=k|c<0WM$T*~r%yEpSKxDUSv}e1P&Edbhw!k_~M?Tcy>oVV=lw`!4={1%G0p+_j09 z;9NR)ZAw7q7l2+Lnb<@g^-TMV1sFh5RQs!vo4%N6gB7QM6_-8EyM1ne8$(=!#Q$ej z#tM3DZ{H~pp%*zMdCYBCje2zOPXD_6P(Kx|wy0fOg~_RXcw$X-ZW=YpE@Ghq1ypvV zqlo#?MlHc1oKhC+f7WrW?r#sY=&s1qwSF+IH(MqRhl7bq>+3O=n~GL=z>|^805(g; z@zN+?BWiG20yzagTxVyVU4>k^3RsI$Dl6TNJ9;t{eA*1;jzmv@ttpd7QTif<#!g0; z(d&Y()h<~IyPgNc_HocoN|swnmwz#EfZ;l?bn(3R(EWSW3BR`LBLH?8*!P-F)CVBA zrpC1)w0mUp|27K61Fs>XFS1Wsry%`aC*nfN{n?@sXj@bJ^m1IdU8DbBjWtd@0UwH! zmYJCN0$^%ashm)FEAVK6%8*Uu5e7+gb)ZjGAHq1yX#gMwOvf_reHn_2vy$)b%P!Aj3}ZUJbefEl5wcqIzT!>PvGcE`vO ze*Cl`iI=S!Rh@C2<-4iL7f}1ZYv;d0mIVJ_U=u_Rxjfl&3Yf$7lfD3n@wUXj6Jtu( z$c3^q)6JO0Y7rfHNh+^cMxM!0)Z4buoa&U04 zaeC0DD-6&xbBUY|P1y{o*=t+{mk7hr;KK|;Xt*j0ILb&YHJcT)NqAgU#q4b?>kUR- zvU#Mej0%81wvBGtW_g!C=7V90#;ITx?1Tr-0Zohd`RsV!DtX?k@Zd>R8|aewRO&_! zzT3v@+%QexFa5;Py-$&m{s`?Y?(7*>^hs%ll^zTLJ(jONj_8*izYWwrM<|2?Ad+Ig z0b&_pG;QHE?!Jt~y01%VvHA$)ua$T91cFh(SW5?X1hOd;qdlX>>jbljVEmuan)8$9 zhyDeaWM_1a(8Mr|hvrYZM3Hrqf(p5g37_CbE$-pQC})RB_DXr_mc-A)R{BKO?@uWe zqwDqDuh)oW_qq(k^r`L6nXm|j1SEHT`c>B1n1^{1m|gDjZbg61&BSH6V?^iWA-cqq zLSqS>eDke*7Jvz8=Au-J(&xelCV)ifT0k@MPy20p)=2G(sVlT9YK`8{wLj(OG|)9T zeenGG^H1(L3694DgVlz))cU;K+)2Rc6u78mZ-dhn6#JZ;SoC(Bv2B*+eI@QiMLIK1 zv;~4u?X|-r3sj7pZ^Dqml^(K7ce;uW0#jr0muW+97x^v*{h>G1LTX~A9Nk^}G5(%b#_#-I3# z6=0NlYYuq`f8cm=1xxByfYhyYS9{r?t!=7cErgPoEQgdTii>ezZlpEkBM}7G#sr79{)P2cv+AHsh@U_|ME5$?+AI`^G~D7a1REcHBARYmuyOWHrW+Ckw2Q+mjOGpz4`_`0yI zQpSG72|)Uc{_T$%r$$X3ss;5Q*_J8#dJ}rijeYcrgs34hP0cyMsW-L_L)UC0_yWN4%y}@{j$$Hn1$- zc?*WVNYNslg%IY5lN}fCQ!~GlN`aN8sAJjD7t#_IIxc8@LE*5jG(7msts^o~k1{+i zubIY4xfwhfEdHSUfDN)$aee%e*YY+yQp;F9w<`CcTVQA-e4Bd=G)Nm53H{E9ssKzw|EmN*N3Iw`WozVHZd^M z{!2Md7gk*!VDBcbMpbUn*J_wrqRJ6|te3Yf^qAU%`09@g7PQ6ck6zCAQ&Nz0=MVO! z_R<{oaz9I`B)*bKZ`;JO^E2PrNcj4YoYh94K1jt6X4Kfm!2t#uCWx6KiH&VK5@Foe zf+#@5MUL8lodCLQl*!5E>5rzzh?XfW?nopJz10+Fxg!5-IF9SZPof6{%j{6@q3U;A zldXNx_BwI-{Zn|Ysp&FEAw;XQauVTKz?7jm_lDt$(MvlZ1ouGLqL-qbuH<~xvvdhD z&Mip`V-5NCb3(xP|9lj}8z*Y{`7q#WJu`L*!>!Igpal|_1Wm?<7aLNx@Bir@Qwxy* z(hI{T4~pY`#(Mk2-&1>y=LZl#K0_V4HppI*N{p^!KLrg+WgAUcO~-x1U|>Dp$9svVG$YaAxu1!jT|M^_Y>m>y&>)j}6N8Xe20kgV*o5fiaTW@CsTn=8SsUz9 zh6GiP@u%7_^!?%DfAC-b@^(aSjuLWD$jd80GLkTEF)N0m55L)@6Y1g}(!;iYq@h7S z5?xnU7pI0XfBi-t%yTfIR@h*}E|)0*D>v_id}n3>m1IM_hENppPQkB#x7hC-2sLcI zh5N|?*wIE)`mU=p&A&txo21SEEouc-7g8#QKFkn@o^!2AKH?9-OABn9IAP>E{pB$e zrjRPaa}CVwfo^jL_qq7N2nf6mgj(o0EiU6u1$4Ifb>;oR_e9WRj+Ot`{3O~s@r3ga zpo7@&Y#pBKxbq4~5a;K(6b=qnDZ<=f&TCMRMN8qZD^Q%v0xVHib-CNa@a z_fZ1FL;b0JZLnB?TfOt&NWQ+Tp|Py_W`K7%R*SwMHP(B7x3;me-W|<44`w?nba2E!C2&qBG&svy3q}O|m)^Q)e$ep8aAPZPp z1K!|4imaxz)huA=M5Ze+NHJji#~Z}R?O^XXxw=tPT+>eYis3@?yoj=HM(mZwCK3$_NuII8_rE_=UHd=@Tul`G)?` zW2d;dftuYLo7wUM>~Rkd*1{z+>EHt3989+dF!cwPY=vc(osM<8se{UwUxSPp85=}| z3;pPM@#TFXDOo-zLedZ%tR(0dSVRRArda(`pYK5t@S;;v9}xNR4tW_V!KWP_4b>Yxo4nR%mlP~R9=)Q zPxTeQ@ee?r?+p&)E<2>4Vz*0zsM*+H8(mAm>QVZMJj*6l&TtCmwsdcI+K2)Czx;|L z=_R7#b0FN1nF1%GMYw4meZPXd&_{k4+4)>}?$iHsoC(<;5PrOc1dY#MQ}U=W&D()$ zk~R;cmR4tPG`J|{sbrz~K~F7<{r|Ab8s#%pLn7h>D?T_iwHpk4_B))PaFqkw4%9i# zoc>K+1~}v^Ry()aBzk;#6>eQ40=rQhjba+4$kF1?Ru<$|3V(Dw%5Ek5Qdg}8>8O@h zgy|ijz19MC#v{P)d)B*tq3-}m+YMq(a%U3>5|MnbjnYES#ODY-4h8UzA0mKE2KS|= z{&e6D|01ZaiBdVWa6AKx|3U<%Qk0)qm>;1H3hR%chhIOn#pZSwQM0_Oy&@~}TbW4mArY+?vP`>3Qyd2l9PREoMou;z%)|yeXy^W7KG=Hby9mTY^7 z?Lx%-+P4o-50G@J8BQ_yR{6)~lO0hBWAmJvZppJV3PcjWfGr6i_|r>}ntDxSm@umQk@@?y{;+V?2udc^Agz5bCKJ^ecx zWNv~`PqHn(@NWJ(C1Y6ZRX<-TfqTn;djWi<1!!N7tO&5aJWZi+XFB?3Zyyg$A{jVS zXU4D5BfID;G>P&(KZ6|?RygzRf0{&T^CG8bD`OtEy}Om`M^U$In%L+*P|$=NJm$i1 z#_`mRDvx<&`toYBLpFo@OusBXjn*hiIVyp?R#D@nfvnHyycd3FCoFTAY23LPn}6*^ z{H+V4yYv_(viZAy0_{#hB=LS_BjUxFfA`=x86D7|= zE9OsLu6GufEORX z8Ov31Z+tzBbuy}MYVx)m9h`3av#Iq_S&Jm+gN-JAn_b(3jtBg)tJ?@X!G$Zma*BMU z!er?dif$)3k|~eHcKKRBzPU;7f{}Is@#l#>$` zMwc57>DX|#JsyH^@Iyk{X;GqwS;UYYGhWm3)Jqd?B zCY9{S?xwe=+`U3!l+J$q^ma+(t&+y2v) z>=kVpu)^00mpK|q?I|efEAg0GHrK^gvwY2WL^mg|r_1CSE5DVRd zm+Rg@bE;OTdZh!CZbPN~Ty*V&tM+N-np@75U$tJQQ0Xs*IN8XL2u}af6ob8o z;NVF2#7pe=bwwSWTp#i~NgtwW+1=w3jvrsRzyYri)q15v!B+lb>8-q!{IPHw%qlHu zn+u4jFHsvK$zkkVIFUlF1|7{9;3&M_H$vR?MdaCUMhVJqH z=GMcVJ7aUnH>_U6mVc$j$i&q9-3znGd`uw53gh)tWA#UI3UJUa;zzb8p-zl-4sSgD zeeDMh>mP4hXh%=lnh3-$z|(#@bFA+FqWPles|$Dd848{cJge1DHtKb>H=aeIk?Lvl z)x{1*BO`V(b_)0?h##4bV`3D-onKy@y^J6)t(LAYun7K~U`Mv}%<>f@Tj9OaX!Vid zzTy6)_FH!ap4)a3W8TF1apYanjDBqGGHUJOh@zbQ0seNq1_`jX#o+t2jtfKQH1pT5 zJ}wf3rPR}>r68I1_4Z0|N=@y;M2m?pVfSX#PrZ2Z2hsEhL1XKiK*_!rMCP$ znYx>^3LZO-J{Py8S$JaQ$#Yd%O5Sz4USzj9s-RI;RV{EMM{Hb$jHF)aTqG+eXWZb# z#Lzy_dW;A}AP^X}0UJWG3-|jSQaDY14xvsY$h^6LxYh4bp<}9&^HpzYyYxuZ^_CFs z5B@q|vnyyQ>oSKq$|k3#Ew%@a= z)VrbG*@_#G6eFTU0!6RBryLZc&}jZ`fS}1q!rp4^g`(D9jAKW>)J2u@ra?{3|CXe1 zwT^JL!fhNM>-5>5t5z+mQ_GQk0Td$I<9^zZM7VC%MzCn7X0&)13?G;!q9fwuWSYfe z1h^H_(lD?3Nia>|jwq`x`IVNK{N#1ig8WC|^E9@DzKoP>kJ_FqW}D=&eW<{Q1)=-n zpZax_mwE>t`YcDl?iZ03fJY7G4TzHnP=Ks}e8mP&z)aLwhA`2oXsBf5y6d;wX8r zYlet(g}A5FiE6r=+@jR*vQdAR@~Ut)P47!O}~vy^GpIqeegH50-7d7X41UZp4Prm2f|3El?R1 zI7@#fF>kr&`GYO!8Uo`*RqB|^9mk`{?4K=(bcqukW9S6F9qR*M{kOi2h>5T{iY=e6 z%5xvDpTNpY*cJLb6CJ%VOzH992-h_$C#A91sqp?3N*hrzS|K9X!5(9?ucj5&n3bzeASh~yXmW{X&y1f!9U2m~E1sj5U z!bI*o0+Mw2&#+&cmW+mD~Hdt7OB!?c)u`lzzYh;%O{i zuvr!9bajq({WmhwM36af&&nem<}in6pk}L{{Ky;Z83jt3-}i zPLBFl)8ne`Oyi-3DXXbT7hFK3P%|^jCv`5XSGkrJn`g`UcJKp`g*YsDd=++*5Hj1A z@;;n*;J^OWZGcLty;7Jyc2Wpp4_TJ$Cy!k&EqMMAcO;i)^Tt0ALZYA@dO5e0>KC84 zwlbO*_BbzzzJ@Inayr#-kqO1ZTsU{b(}4NN;`4(EF%fl+3Ulw~*N5n6P?)Wd z@25U2(Chq73*`;HQIHoh89)#Uo^;KSU1>#0VdmymHqX6}1nX*}xC?FE%tEX(Fhxdm zrSf44ybv9{&~ksa62p_vfOI9PL%yA8T9i@AVft@#Q`NTz0zSvcZA;w{Qdr;@f!7<3 zy|(rzzF4yU!A36Jg_o|2zNUf@o93;OnjO<+%TwuAWbD%_pWeZfq37rNek+iNgb`apJh32{=aM}Z?PYu|J3bomWOstMNjXz>jv>u=QoFM z-y|VHrU*7k$ktG~rIQ|I!@9j7_WnMV*9})QUcSV|=P2f~w|1kT!@|H_6kf3OF(eOT zSJ!Wby&XI0f{rOusL@4s+M!pf+B!@Si0l6;m&)Gw{68)s{CqZq-q(2Sn=HngF8yCY zH~P|HGzVCfS(48S?3eFF())|;i;C?&ZA%B^+#us>_^wEL8yMHtft#!qUpObNDw2HQ zT14M78#3c@s?dh>sD^TiyYS-Xe75I*#h1NIziS@>a1gki?POmfVbZg{cns+qjz7SKkHu)>rRx zTpGIX+oG>I0-6?Tb#(#3s%NgPY82mL^&lBh@ub09*I1l5m=r18X~bPVwAk21i?aA{ zwPz{UP2BT;RUbYhoQCi*b5$t=Z$+h^%WX5S;|BQbCUEDCW)88_EbzD&0d}YBvTdZN z9({STcNn8uSeP95{>FQnX*8Do+Vgy2379Dpl+IlT8%t?0Pz-*!qHaub6L*P@$oZJ5SF9crS ztx7EQ9G4Jr{u0x%tV{1xZ9fyaep!evuGY$!Mn@JP8vI<1McSnzd5yk}g_EcvFJL?I zv9S{W9c)3phlek{YkqL?G$~k!3LS&;KYM#JG#>!r`zGlA%gT~JQBvxO))ax%L_a^C zg>l>791Z#8Qii>S1CRMef*O3$s`tCY3x?pMe~Z=;F8E$3DQLBl_e>(|+mWaq;6fTc zU~J@AXjwGb#foDTRePS0p9*TPN^>+WP25jVE5+A8s?Tq3eMQviv?fUheLsQT7Y z`8leVV$Nm&DMk14E1J+R8jJT^xC!@Tc-8;S1*$#Xzpt39KE*0Q3XLAdI5LM(9NJ%%l zS8eq*YCfS3zGRsTx;+2UVVv2Eh37rb0cP2`^=Eo$oMl~=(=q*nk~RS)g*Lj%xX`3& zq)qDIZ7e)l6}T$G<^wTKRot04vOBTCP8#*mL-!HX+>Dauy-#V`;#%-sQ;&#|WZ*vl zi9EsJP3rTKk%*8FNxi*XV%uz}Bf$LpU?%o6paeMXB(Qn+T{WlV-ng*W%?t2l6K-fM z&@MGJ3!(04J{S||Sf2zamuE0{r^lTauMtNsYkCc(8BW%GPxD8Bcp{_zGObL+bsgn} zLbLMtjxpAS_iqQqfO3e;rlg1ielTYe^$>V&a*0$T6ry zTaH4q@^Wc6*p!)yJAA~7AT9eEpdeUAVD+#6Nn*%HWSW|sB3Ek1Hc0Cl&1JV)KE9Np zgk&s$ITv>NDR_)MW`rRlOt4WWa$XR%riAFk2ZDuxhGIkGHXv&^U_SUMpKpP z`l5DdfqiR>1@=8IB(JRxteJhXsENcvNgx$0<#(fk+T%w%eeDpLs77B5dwe`VW~o)d z&M&8@_sBQ|i~`cC(I7(I+$TC4U+F-?8W%!uDHt+?52*y%b;Vu~`(EpZN;hEwzdYFS zmQTf!)ZvEWpr@9n%@kMhwk{$Nk$SdL-23%W0Ou^Egks@IX_uaKZQtCCc8du#S~NjuY%`J$&>HxQPQfy+9| zrZ#XMU!nzZNC%LPQaspB?;%&cuB{=J;r#N%VbwbjST#$D55-4BGt1-RPW`4%v;+Nr zX_+Q>M{_*+$}D^{LMzFjUK%K<$AN&ir+>YM_VMB;b{3hx(5 zQR9Pp5%Baf0ph({g8<*zk5LV7Dlhtr5Vp(wj^7%?ZH9!-lt&zjV#@4J$0_pcU`dd{ z(32o~b77ndBqKV6w6JQtfSo@JLI(7`Q5xftzF+O_ZC%NUOa=%9<_%KPC#&8Ay@eJY zqi*IO2*-X22$X5`UO(LszS>cBmu0;k`6@^a*;K&FjNMStOO;7z0CC4Y$Q zwiNFq2NK9`I)=wY%5vhB$WpjH(2CbekBg6q$@2D&N3vPXPKay6dGwv&f>X>|Cj>(G zsmSTv8Obgu1pAUsLbSY%!c9IaMTL_?1(M@wIi>b$VR{Wy9cND|6hu`rl($G0b+h4) zvl+GA)McpJH1s?jC^8^2xxjK}8X6U%B`5^+VC-BIjsbzE4N zeY3(#So<80o}ddW4|M7O5*kiHim4wRA|vBtQ;2*(yhN(0=E1SNX&2aa|B%*Q=NIL} zQsVF5w~h+4%CtnWsxs^d1fn709;*~ZkcPQ2eSQDN4{nPeL7%b2!{g7oa?wQ1IXhU2Ly_5Z94+Q(d)m4GEvJ77; z1d}h^hIvi|vR|%3y6J=#iWe?d4>6{kRch11Ud!rc)2bDtp==I>{3tok0V3bvPa(98 zdS^g61xc|gDe0b_oyL~NjYo!rv zyikDLt}LL4b&Gmb|0}`3gEH0pJ0y_mz=zP!kUP8)d6b{ck(Bv=Wp3ij|0QmT^#L2o zw?;E$^vH0&fAU8jm2@OWuo=`kHSSxfD_V1EJc4k2IO4X!snkBV+yCB^kbbxSC^6a@ zySN>;+!_#p;nI|G|Fmjj;t=@)hqT zFG{S{`=M9m)*}i7Fc4p+vXn9&cA?f#zpfRHNR|EE=eEr}(JdY<+zL<>iu6q58NJ(P z{aH&}Vcvhs$-Xuqd$L5yCHQF%t=f~kPAvf`D1qhdgYiN}db$a4)+?7@BcIV5_%%ZG zm>80loa#%?xs{^10xqihVUhbIUBq3Cu{Y%_8@lOR;G-d`rWamZO=oWOvuQyxB6vyw zKDz9%^MhgMe|FJcx;Q7F*nmKEPEP77zD&Ar4K1(#5_+o$zXtOXkPAZpf{dPN(I+Us zU%$TSC6)`BDDQp#m3H)kZlvDr)ZeNre4AsND zOE6(cIli!m?S^#@W;+-uF`yX&`WXXK%*gxFO?#FR$*it7d;rbytj{CKpuvL3tyTkN zATiqI^IS;+K!&)M^K2=|nV6AXg?CtxS?eUDuKu_k4=9b1v3b6UWtFP9lK|q{_j#w9 z*MF~QJY)|^k*Bbrd~cX{d?ThrUG2?-pe6}v2ZI=9g!TUIzj}p;P|!fqJSNJ<3b&P% zl=?dJl#GpyVFg2pk#*?RJ|`$xkvYQ#KZiQP$J2Eq?WzYnUTTDm57{;Knm%Yr%vs1% zs{mS)1HRKOhcb-{<%KJ6z=9ygvT3Rmygh$45!NU{VE&}YGy;%Fep@MgX z$nFa^LdN9F>up}wx)hLk2$3m;FPJP4zw&FTRd2^`y5P=dk3(`d?xC0{?ML!TI{F;X>1$-Cg5@tvU4)b24o7S2UtXrJS;A^m&cC zl0ZFXMX&k(S381-|@Mm_q?^J{4<@q=? zlM|zq)$Ep!Pt4-cMIFgs(cJ!fe=Ecb%LhlW=z>Y?IJQwCc1Vok{$KJMwnZ53c`n3$ zjL3mg29V6YWtEx>H+pjJx=!~zZ|lhi+k5vs#gYb$d06fcus`>C+-3Fh_4ZV6qYKxHJZtTLEK{|2=hajVcx^|O2RDr<^+j{Y&YzYsta(9kJvU#l$q*?(PiDx)0q?X{YCwBi-OEAUlfgR z*BW49_|*AJU_n#BZ7w&r_YH33r!r@5Y&5A0=c)9^W^e9U>e_hiV-bfxQYUj)-P-uQ zO1%F=)_ccux&Qy;mk}z3R7BZ{BqJ+X*|Jx%No21`wjv}&_LiMp_NFLB_6iv(JA3c% z<9c!4=X`#@zs{|5yOpQw`FK7a_w~H4?ML6At@KSku$Yr&W3Pf<`a#p4G{fbxE*Ls( z(b$O3Bvu>=D*LEw<<5iVe}3=52R9F4F;K97hzf5rp0Wwv*a6{We7$U|f{=#sOAs~N zf_OgW1T}oU@$3yAUl&e$CfWAJ$><=&mXo2Tg#lR`g)ST zpRy>as-~P{$-3{M`wUc0B(ilXaHcuo7d7a5mKS(|Vx=Qq;!mjR`rzRThM3&TojHY6aG8zR$fSxRvF!B8A03OXApP@Yc6+Q^ua=Iz8ZGTT5%+=q%NF*(Wy8a#U5=C3V z=yFv-x$-Rv`hQCxw8j&7;LOJ0{+TX|i2Xi^iVgfnC7db+Y<5n_GkhlcuB^B3P}1%xf9O@#{IXj9mk8BG$vTyX zy@{r+98$R9#et?mgmsG=x~V(iE>31vmWsMMi|LaP^d&oDV$~ph&&)c(AK0!7<)d8# z1Q<$O9Xib8eqlV?ATx(r?+-m!zF36TIDzxhoe*@($YscEtLr#ABJP2LtnR(yce&*u zHnJ-S6M;bm;^6aF9pSnx<;u4fEBwP zXQ1EK=WSo0(+Xio5Ttg(AkLdRdD?lh12uC(KQc9V7PxbrCU1P4?(S;4%UK2$-Kp*Q zBNg@Gwe~Twle5UCD_Yi{+374Wior;+)?97wmIm7DO6YOQ7{1j!_xN9?1VnkE+C)ks zn)&{@^`!Qy=F5XUJQUas(NYsF>h)4<=2q4mYy8H>&9F>$6u=0!O3?YD7LkSqnFbVC z;Pu1DYqkTdEp8T*b#faiB#Pt9EEU=mUx?~1ed(O%k_HO-1s%joD@J?OW>&x0e9Hn= zj#QD+S%9j1iCZD-(sxQ#IFMb{IkdzyfhPmibcfDk zmU{f_RAAFoV2u4^&KiYVPs+5R5Y(I&Mx%6US8K1Ups3~~q6DA|)FVu+?Aies+UZDL zxsKyZH**Ct8V3*7O(y@|hxM_Yg)Zp3djAX{@U$~g>SJ50<|fqgj}@ct@!2d_DG_8B$(_s ziqP6iL?3Eh|#Qo*9urxqkw1Y7-cpzKdh&nGe#qESYFLMe0=X%V-GUG!VlUi z_AC8DWD~ma#BZMh2~qyXgL)i;#W1s>|1#noL>#&;Qq$A3k_mT-V=+dYlgDCHvY9PC>T$NzkmBBFn}lM>4VeX ziDLO3v&=2@Cr@3dlfZCkX-gAp6~%}?OQUKlJ&F^p!lmX=#fxeRh*$SfHefZeyfL%d zm!$j!Gh#~%$4*BLqtXZ6&Dkqi@Q{M`W=Mbp21M@Xll3f{tr+iBLegajqhTfVUn4^9 z8vRGy771~lC5lyB5!U0}m7!o7o=lry^)Hj4jBJ9fMa^zPvbREO<$|opvBi*a> znrrkxMgh$>!3zta*gh8A9G-`26Nt>;$Top&=t=U`l81=6fYt5n^LoSQqQxhkn;TID zbH5y+R$}KnTg7@U&Us=%5oXcz=QpCM4RHVG=%~u&%c7&lVD+zQ;8b|atMoX*L$H5* zF!sq09ySsnCvjH4w>65PwPr`uLZ?=j!}59wHEtmO?4y@#CzVWS?p;@yE6rD%`WGQ| z!;Yt-sye>z^2cGh%&_jn{WYfk=O@XsvdoV`+^@q_4bEPXwXXbk?++em0^ukV>rBkKw*$#6SkwjJqF&@O|Bg81rP<~?y*70ri)}}9 z3$d%$uBHBpWV(3TVyJ=w4wy_7>k2HVr#sX61fKU*CMKvhB^u&CCfJO$C^8Pd2%(~0 z;o6F>utIN5Gne$$5}#R_D$CeN3-(y%4lF+alB8@%hbcu8BZ>4ql^&}U&McYyoRN8&8 z(xZdL^Od3*QEomq8FhGsIwznaufH%9kBA=@5w15cMw63hhA=+1o(2{aNOvS*r>Db| zrIFeGRaHK))p1(YvmNdrq(TfbJR+iVam8OUMXNMVvbea|+$N}DeDa=>(%Vm;qR~gE zru$=yM%7+A4`I1pqwWTX0Qz-^w%B@*hm#aQ!ZR0UIa z&HqkaI76D~8G?_XVr1_!hK~lLj53wE_t4SHtG6Wn+rja-Z9SUkdfHVT1SQuWu0mH2#N-q>G zz`7}Pavf~nO>s%~PLK1PWbK>&rK$S6hNzP0@l1G&D{6_@t=vS@${890Xt;!24Hz41 z3+uMC=5sWsdd~wSZHVjL3`Is&Ku)mLgvr1ulMM?8T?6f}Vz6r4Xh6GZm7U`b{APGw zCkKv(SGPr2SQv`JTY5)CSMqDA0%F_DX1X(>XK5ch_8eCIhY^G~42sm0%a3MCVu4y0 z=K!{bMwJG>Y#APoFRI#?O<*dn<=f2lG+GJTtvSns_K}g88@58>k$wW%j0HZh?d<$q zD^@#a;Moo+SubP|+e|DQA2330wruc4#|U=5IkO{3&3{|c4rhW#4D@jKk7QA z3F76WpX&wya|U)lUa{LK2TM~*Sg*?e_Aw;RxTQ&bdn0!cW|mgH|23l%h|X!Wg0ZAhUHPSRn1q{rc{B~8hBi|^hy#!b~n?LwlY;SvQq!ho;!Dr znV5j{j|lb&zj|0W8Y$(dWW?~ajtvlc8y*b0u(Qa6=5=19*lFYRjQ+?#cF>^9*nABt zdcks=s(4<~!ZS_#SE14_J~jgG5)~s>-8da!n1Ey6Pvt}A3-8aVW+--nHb{G!mh^Ne3cL_PL^ zP(5UkLPGpP3OwQ5L$6F*U;lxJv%BvV5D=iIrFF-EO8QKPDc1z$B(!wQzRSJe8GXo6 z{+f4)gzV!M24R# zgRbRu95Td>fB2n->~$}8Q*>xAcqRjHFRLO0q|^~a#&(|x?E3CSsP61cXNj3>@3VA%HaiO=y?kHzljDcV%4-Dp>zoQceU!*RLOz5FVm3? z-_=rwo&R1Uh8`=BIv9s2iIH9T!=O==t_>fbFzs_*bEu@KUyZf9`sw=hkl*oGQyifz z>~mP6ifQ}a)D4G2KJjB{1e%vx)6DRwFnxjc(t&5kAmMf@6fxj}PRfpYwN&8M-rH#@ zb(19$+-65xX-LF>1UQ55sH=6DyUonZG&lVb-TrF-FW7Tjdf;@eAZ#HmCp8(E$Y@-77+D(!Jt=$F|Q0R zvU;;;7dsuuN$lpB^0cf;b-D}ydQo^`n+Ry^6t(rw_uX4cAf9;|}i?#P|#e)mrPm0`oDt#%lObFuHu1=z}rUdoQJTJn4rH&rxun=HpGk zp}M6yWL*}FqNWK}V4BFTEx%;byvgTzPt2JMA?LP)2Q~A*kpr{xrANU%AfxE4JkIv7 zWrGlFeD@HrqO(p6l1xEob*}a-fDUMs=dWK=SMC@hq%$CaD2U5cQb?3;+u=Qjr_VI2 zH~@6iS(?}+1oiY{j>+Wj)-s|N+0NV>CyOBuiY|)8;s|h!pLc76s{@>Xhft+8kpD1q z;UrzrW?p<0X)x~#%!LZHGPf`caPr_m&$g_`=6f{t$pP6|nmmxy z|M75;Gp$Fu+Dc763$wE0+Duul@Ws=!39bQfMXX)GzzUE$6kb+lCbLN&14a?Pg+esY z(t3t&MX~2E1-8B`S>R6{!WVwI!@5$>S;$#jl&sVB@XrkgD8qFqLo)!bIa&aKZV}QK z_{ks!crdNy&Jp7EN^6;a9#Fl=thE~Y8D+=N4*YNZV{3+5Ng-!q`(vFz0Qt=$vfnO7 zlm(eNwYFco50mYSq)<-sv zosQ6z<6wIkDOnK%o_hbkZ`6!?wqw`l`urAZ+GwDbqY4M-Vxrz8G4uX>nKP{i#Te}rxla*2(kG41t!_vX=m7Orx`m-of zeatw zRzm#KwkTYxUSH15cb4$>_J(7Mu(!Z07%8(Zu(ydy20{-RfH3OT!rt{Q=w7fIz2#co zDyte0u6#k-`hkz;#xNH|L{BJ6pvNU`uJUwdW#owZ>j;!14*8DEv?gnE;UKo3QTY#@ z0_Ddbq^t6o0r5Wv2k-vGs*&Twz2bcc3#vhe8pWQ072v#-^U8JnnPo)7YQ#tc8dV=J zX^V{5f6{PZ2~}}7H_K#Dz^f2Y6WR?J`|Ja$Gp=~59oko4pbhYNE*^hHehl_!HZps^ z(xd9h8<21c?;&;J=(WV+!|PXBtW)97R~{f=@BkihIBqZTv*c)bc7YYR{`e9KF!FX| zZ^p`#-rz)cYim~sZc+s!b>@SUk!)`X&2!Z$msg=qkA>m5LjJ{&7wPa}LDd*A=vQ^t?#L&;Q3PO+GBHkeU{lOfdawLgGsF`8We{RnIOGjK zryKwNEjHgnZ-F&uw4lAH?Aqf>UClndY_wh>!v&{!(J2Rx3;b-s{moA+`v+(X9~kI^ z3l)uC$YuZt;ab)Fk8MuCrMi4L%_t5N2}I!{pl;KKb59-&14sT<3b}~$E%4m4oMuX< zM@p?r?N53@qH_d}@%_2ObOXXcMu?XeS|p`Xac)-8E_EuiN&oBNJTwshuQ!5_wF5Z1 zGug^Jw;K|22CjU(uB@OZ5rdbH21uraq!tx%9TA1INb8x?e(EaAZ{bTA_wB347UVjr zOBIur&=b-N*GbQ@dA@}in0g`dS8w$5?WHjZlpmM?`_Yws^wLA`Zqn0zkL(ioaz!l4 zWxEiXUZ95LH!%4oVXfkQNL#ROf4h&?lukQTHt7w^~`1IVhFjf6Ty;A?pk<-l8EW-?{N{#CTwR3z`c| z`I0tmak#Jy1SCEEJ?PA!alxfP*o@#4Cr_FYpSc5Ugo1+NzJ0F2-I#29*DIrG}e`0LQE2-^w`(m`pLi&YU~Zla-z>IX5>s(!RI(`=q*h z@iSjqS|5nnvar1TR(uh95F|q3qO~O23%}H@)LIzK?h+8k;3EwKHPx?NDs~^*wM(< zK4Jr9)5dO39$yX^2$2!Ltp@n>6!L`vx{w_`IiY2UL!$a@?N)@%bdnUc3C#ERUeMSX zP2|G5rc*B<26QEDMybAHsQglq<9V=AJNfFYzdpbt35i0uy9dV!vJo-S)Nj$#WK?(P zH<~p#qeNSZDmEMLXqn+5G!y@Lx1|QpA!izei!9Ya6*s)u3OTJ^yoqv!J>gpiAY&pl zFM!83RT~B{>hng!2y74me+#{pVm8Uk#q}=F`s6DG16TkUM%<4~ei`FWUS>Xso4|fM&LRw)_ z>gC#sqq^3j_wxX!(OB-^r^GhSfA8*67uHytkdN7`yBGkJ>b?2R{$#RV8~=6k3FSEa zQ7*Xz{84Ek{V%a0H6*zQ`+ws;Xl29|b zdGX?f&zwPoaaKWr$}OkfQ`^PS0z_95Hl96ucH33tPjka5>hyps^C|_mUZb=1)7#u? zZ5F*JvO{ES{S~cY5HsouZx-GtTwfnKxShXe9cv|QL-c1jefXxl>O!1?CKWPD9#6(! zZ23(kp1=Q03rEfk`RuSRq|S_~4ab%tk*%J7x`@H4$b@~R2D@duPxLgD3JD!8?d^lO zIEMPspc}}jc2EH=9+m-Lj2TJMAsm&HGkm3x+jN#<$u}vcB{uJ#+(D6eZH9HEkog`H!@@cOUoSyLr#3$R}s3`Kwm#?tgys62-+dxc!h!a$1w4rj%)4FWj zIbw_6&0>>RBkPV-o^hq8>uzE{&ArOTM)XaqYvl%4EmLAUS_*%lT5~ABJ2my1@V>J`PT@ix|(D%;zvSF~$Zlh(CYu1JS``4iaVPvUDGAC>?2gHbg2 za{f#U7p=M#BX>7UgA8lTwAkz^5WaKc&dBS@72_)AY08f6g<6iG?B~K-sbyt+XmuD) z*q6geOZM>*zXR_vc`C}`KD@AzUA9U4>2!*cd~76BYrXTs+Oo~tjt&k#Y9iQJm7B@j z;xTJ(usmhHCVOh8=E=8S$FWmlwLccCRHV{K_z`4p5!SxF@%*LL-X#az9}i-B1r%_Q zD=BkWG-tjmkIcFycj7;6%Us{cw*#G#AmvGYFz--yToqjSpn}s#oD@jnn{cnFy%+4n zt7i%Ej^C2&%~_h&KPYbR9di>EeMaT>{$767nYVmIjRasSv9X<$u@kc1WZ&ET!0dAx z0&I-Bg4F}}22EY<^g`fY3Lb;n#aVRt++@nuN*%7&B!i4Pa0wxN31(W8ms?&=5T3r| zroA)#vl+^ers2$)GhF;EssLjkFpi6jh}8vt(uC_B#dF)2E?vsX$)TAd&d$&8bKf{; z+CoulWr5yJS6BDo=B~a{>-j2OK2~zkHn6EFAh^nk7M3NrW}|wJdY106I`0iK7541= zm1M{zreAnoNN^GH^3bZxx|5+$BK`<>E@VP?-Wkg)1&#?ZiCotJqnR$(L!}+RzV7A8 z(2Eev`nyld%qR(_@lEIQCi1yZLvkNj;&=K-)P-x?7~Oac_YyX^fZ^fiwp*P7tXNK? zN>l`N%eM6h9_{bX*FkmJzH8%yL<+AO(e>4#8p)4b?HEjLY3h=hv_re z_{iJD_3pXO*;`Ihu7qjnW|w}!_`rn&Ax_v;bf;&-CGlNx=C;OmGrW8aPQ&}(ekoDp zujFKut@RSBruE8o2v4LPifR33 zb`NJ>v4#8*qq>^UgcTWjHUx#eF?II9GbL@HRKe##ZfBb8gFu6Kz{B@C>+zJbgWGQVFqd|y`8RfqBg-x$VVC{Mc-zG{nV1L)tbV5E+ zNFHJ~-X42CKDfZ*vukReb_&pm8XG^4iJfCp`V13=TA1f~9oj=uvokcZ_05$wKFgNm zbDLO})ZE(O5Jh(|L9a$sH$EQI)ST1J;wNDb8PGkv*i}>_qea$o;UfQL$-cv=71|T} z>gJYA9qy)s0u>${B?624j5&+5yu7@yfP}aB@Y?xM0NbnC`aM7F_ntiy?dh3Q)6~3a zNKc20tqs?Bp&zRr@Tf0+xDG!bA@I&i&=cHQej0oht~q@}H<6uy3X1-T;T~S~;HE-R zqmp?{FNp$1El1(kUqC)b*1)*n>;_t7i0(*mc zzg1`rZS2iq+uf?8jn4fToKrlCe==Nzil%JqurP|JpRR>i)V^@*hA9z^k1Q0K{ zIpeyg*gdfL)5X!r>CqYBwF5)~92^wUA;~|h1f097?aQO0jw72@{TrUzAWE0$*1~0n z2;(!Wj_)!v?>>68@>YLisZmx<-&5rI^9>SCx;rv5FZlWSE%hI|c=(zqP>GEK<~1z% zP@>#8a=^e~As;OyUq~G#HiaOoV$I*qSHJfVD{8b=Q(?})5=l)KAfmY+o$jdTer)?) z50w0=w%kczCyPWn*CXNZy{g<|OiN8?n!xi|#X@wVIX<;NlNc#=JXJfQ*xpA={Dc2p zpR8hAJ4-&Unr6A^ix+a;k`I=4_DTfgmV?~PUTnAK#2&v0{ZNjlm&e>Qi@)rlWOZzrB8+%A602t;L1=z_&H8Va$F)rL|CBO?KuiV z28@`v9$*3ovsCE);UV%S#w$*&i7*(p^qlDxnb%+ItlN&(7Df`by%}KA0hxRaU+C@HY3X zWgRd&nv7o3ynzG=A;}|#_=rERdlBr~emWapjp0=Xn3^~=a=}iodv)_Z40yM4kF$oHaJ#5q4>HgeE&8F=doN`>ejV45%+JzPBS zK06~`x!-%=o~E`4@23dsr%=;&b*kNW`ZmvpwzlgxWJ+IAraf@FXn6nYaYwuT;b+lj z!Lgmnfb+oADl5g@ibH-i3W6$M7q>X)->kxuB&HKnBj|2)Y)O}(Q82>H~&M(*_1bWB2G(&jzit2E2cEBJ(=$t7fJ zT{gnCS;j?1vy0*^I|`Q5N~(*wM2lo&0Ct!u!1VE27Vx6|JlV_?Uc?x4qYMxb3=$|w zFWSa&d*;jB67YI4I5s8ys-?0pQ>@A#!?C=|qCvcjXhvjy`t;00aY#X0S_z(Mc-S=> z0m2t6`btU$JKbAlzv|VN8g%8Bjv<6G(B$TXo@nh*=6Wbb*7hzKqK~uRX>!?}kc6fC z^A-SOHXeceZe=qcBDnG}Rn?vuB2`N^_t{xyyTnXukdFlMJ<$XKG#$BMwFeJ3|AduVi{)m?8VI;|MXuWBEiySkt2wS6sJKFwC_I{$yXV5#BWT0FXHR z%`bW`!sE}M9|HgnFj#_UIB)QaGF&6ksV!Nzwt_Ja%M8w=`dT+9Ua>D8)_aIrX6@$!5F1MF5_RH`7Xs!$ZVm2uTp~XA?5~q%BzJ)L5@Bj|>H& z&=l~9(H9ez8!VxKwP;eQqIaTL`{t&mlxW_Ed*$D@TM}~_5BKWqx{9*jEIG_MRLe={xWSd{1tSb`PRd0_}B6wsWU8MK(=P=1HH@nLVrm^ZBoibM4%ur5#FTcDjMQgUzN=`M0k)DP_beh7 z0X*T(z}c1ys}38cs%w(yXrn=p*TBL4$ZuS|!lnVJ3GD-~Id-1f3_iB1tqt(Pa+~&~ z|9c&pZ~d{~=r-iZz^0Y_HSaBCqqemK%ni%9dw1c{svzCAPYULsdQ=oVTSUiekdS2$ zoKjrca3I?3VI0m>b-@!W#!nckna%EVO|pA@%H1A*wsn!qHr-w z(|mBjhyJTYx>?IF*v2Mw8<$}lugOR;l&9SEiv|+VTYKJ~hJ9*4X#d_7#a&HUuVJNM zk#b5HH{;7Qg2Y&WTS7uY&o=k5AT-#2GY8Wgv-e7LZqd_=LC6F4)duzz5Y+?Ch}>C* z%HKt9ANvmZLY>!No1!A)hlLevdI4pw86rWpgZBpC?Y+7y-51D9DEM1H?JwNthSl!9 zf2{Ayfb3%GCB1A zJV=CV^+b+SbHe>XOH_5-`|Tv8DQ}pW(NWDiBnv7GF$ahcx=TFOmp_9FbN4PWr&sOL zPPQc*RKVESAX))# z*UH)HnMZQ@jR|;}iU8zOW0$vxO?B)@5SybenMNTW0bzjA!k$gB$7Yhz{3M(!ewR)E z>pEq16UgabKw5ds!wyv1Mvm z-g;l`anY+NoZvwG@lYUm3YgF3J&u?gQ`7Su`PsZ#m6fqLPiO5Xy3M4{O&;j|{zYFw zJ|VLyQbZ}_Rt7+9{LlDR=9@Acyo*No2#tM<$LL^*UTsxX9JV0wIP5%hY)kzsHVz>s zBk{7M@Plt?dvAYZ8zEQe8ffW#n?Q8&{v*RmMQVYY`}?86ai`dx2N)zGjLy6P zb#+`?D^B@YiTemKtLX>Cp9keZN$=Jo759@-RLC$Iqx*NdBf2Z&lB;Lrb=}Ts)r@{7 z8bYA$DFE~1Z`_3$D1snjqU%2_51AS)YJ6koIHkXehiCY;=3%o`yL!LrrGC=mlt{Zx zV{4JwA^A7^x;OZ`_TUAaev?qcSX-ed%U^$@U;%pbe<0#I)9aXY?jTYuniwS@w(7u& z*rpRq+kSZ$P8KsyH?Hjf8b2tAPYdBA_EOs`3`QwZ zDO-TN=wXHfa&At;E4Z|`V@WQ%H@55CBlUgkC^Z~{1kJvmRbAZt?`1*W+Jt_wX$zkVuoJ|3R;r0 z`}-16Ux#M|62+Z63M$`E?LtV(|9Vo4&_N~yU4i|h3rU6#I22*TvGZgjd7JmBo*YBm zicMKsJ!ify-Mu8#+k{oeJv%eqGZRTsRNHZ)c^jQXOseN2jaH5F*Lv zUXdZn&0M)FArsQ(K@%5UDqPW`LWda>dr>RTxU+#0ik}`DU%mA(=O+~rjND|ccj;}O zO$FBkSCu~OdhAEx5OR-?8<*sB7}-alawiWm$|7N5x38N2*Zi)AA{#yyj!6mL+TUh; zhuuBJPX$7Ns1dyM@dqz~V299b-0dBrC0qiM6e1|$tFhgI%=8uSh^aUPE za$2PC*F7r~*-%bq6K;R1%e`&XM@9u|>Mk z{hEnRFP85NFl|d3Z@W^AIdHy&Mhyg_2;O%6ZMi_n^iCPg^{>Nt$ zC+iEWA3Z7r#GwWqRUV;>GLFv5^Z2;#I6*efA{5aE^~E+>H0D-tOTjrMG>n&D=G%N( za9;J!D06Y~im%>k+j{ktqWvB*0CCLMW>wLG8b##@(7K3y)KJzBEo+Ya+X*B@t}APG zi<41i`!3g{?bPUCQ|pE7eED*3v8ODc!jU}6r-xIz_pf02`DfiqF@m^7A17TwWtg6Q z5ACmg^ME*=ozZuis$)3q3rhlGLkM4VcXSxeQruvCXr^PrX$besfdF+!#J3n$`vHn~ z7%Wqc0f1l^Eu;Tru^H5zjgMUeBc}ZxYykDlc7{oT=(YW-Q+HfjH8-+Kd4195)S#de z=GW=X%j&FrwLt7s)XJ4h_5uq@_1p%j^3Dl_=G$cRqO^-@XM<_m{Ub2yhpo}Q+FEJ8 zvuV^gGFkg`iTlKAorXUzp|ilezY9Ak9am6haE0u8r&KQW^EoOo_3}kV)laO7V4RO* zC(r+=@IBID-(w;AO@}h9VQkE$f6@H*T6&n#!vVC{Fogc{T(7tBb(;~So18U)#eeTL z_%Z(!qllJ*Zr_``4xmt~t7x7U51E2agY37CPp{bAv6p&u`afbf)8etY$+p=k!-ut> z!Tc~CvkLujZS*Q=rK@e=qiRT>yIrBMH z$R2D~xS0v4;UHxdK$voKhRH(cw!_a3g%2)t?g|fY0Dyd7T_ynH-}K7nGvLo9e=ScB z;#>(?g{iXk^=IP`&=T-Q<5OO3Plp^R5O-dX358jrcou2D;!A*x-oSKmin*I8o}Haw zotdAXP#Qgn0x+r94y%H%TUrcLyt3W)CSbf66$PP>p^w=Wh@@MVK+Z;cM@Q1w7(RqR z8+?(|8k(Ahu68w3c{-pv=mCFrpH;1C%2(y)1ot=h*9dO^tEIZ^3;PAZdU(j_9k&z zvK{XT102eS!-Mj?WU@+_c^*K5p!HsjWPnF!o-=YHmnN zvsw{o;QQf56!d^Z%Y%z}VWHLMn4Q(#(=S8bx!de5j)izmChl+d)rJ6leA*Vdl%8rM z?t1zkZircc?7wY ztE-;Y=QMwMR*->#frMsAH4uqQBvuM#{2=@D-=S zbr+sHw7@AXD%)JYeL!Vgf>&JNl9;=(S4i!#62th%$dnISAxu{E^-o-VJ+-#bfopr@9&j8JPv?>Hlt= zp`^@yQ7WIzNAzwX=ql<+g6g>b1m&m1*lDtnQy`8&=TN-Tj_-Y&2iKOkwzg?~Y&YXMRMN1d~m=gND{mRBP6}!KAO1TytaAWN^NEXYBH&o5M{XUx=a>1vpi+`hsWS z@7~x~NB?da9){2^JPL!#)VUN2l_I<8b|Dnl(YH%;nrA&X4Bf4oE?qpK)A2chN;5re zWwOoB;f(w8*EbY5?HSUXMclhg4sPC*0o(-5#Bll3_NlDBy^{CC^_xq-&kfTPoFUkYB5oT+{N3u+QIahgC8Qq zDwV0%x{6v!k0Cl2z?0fM0S=&m3}uR--;c6;th*g_&RtzM&u-p95zRs6gAr<@KoWW` z%OC8|@E8CMf{^)jJoy?9;zfGIpWykAjoshcv-m+s^Bu@j_s^e}vlQS}o=`>iz}$GP zCOG10#^gg&4`mPOUQTUqDEPLL*@M4+BWmEmik&_7m|7rh&Q;OJaiFSOBhEA3JUozu zP#Oy{cpJCqs)=9T!j((kfFK%D&=j{nPB!0Tnf_+lM$2>ku5jiib->Htk)IJ_1r81l zz&Lj?)ZHJHP2}PPv?tW~baZ^|J4c1)&+k2YnMF|yDX!@a)$@v(|t3_u=*ABa~r zS_9x#p6+)^y4LE6PM39Ftr8vAFMqBH3Rno>n-QQ0=*xg4lnuqYYk8?bdcwU`cW5Mt zj(0>TD{499)CM^QZ-Emc4JQ6L%t;a9Be}C^($=U#)<5ifp$j<^Sp_7D3hWnc%>TXjkA6=Ne)lXoVkUPzqm z2S|~3d-AzLI4FVvEABkezy`=cwBtxWgKXQpPQB4V^$G2S(6d2jB1n2tujJd70iGcG zi;5E%`6NBu%|?eneSrt~F)-495YP}dHP0OkxRx0R02ZrLUz6_=q9|DVqz*V~^IjxK zTSm>rg9DY&F>We}EzTM>=b3;JfhBczGSMvy!$$kwVMxB=*sd{3T0{=OcJuN8E>*RC zVs)+~L1N|Bg34QbFJfC)0gCwW%!j6!-ZH*vhX^SdkgZirc|Uuu63w@!C&;FMr_}0Ai9!W1zisWY|1Iygu%G zQIW#uA5!31fe8VF7+8tFZNE`rv30%6xgp^ze=IcA)R@R0XfYC>ke8R&D*R%z!ynX^ zAdM+M_r);aZ!*%o_M&!rGqFN8ecr}WuT>MMucE?8c+bwoC7!1MQP*CcYGZMQuL|QJ zb=)XL!C&tq6(2#`Z${!j!$!7WEDIon!Kj?1b^DCUD6ck(b8xW`@1>6dhqNg+^2+~c z6S?T2$E&2Mu_utKI(3Vm|IdcT2Q06ae+Y2~jNQwXzrh~0m4InAP_rQ}-3uUX!XMb( z-xwjA5h;(QD0MovB@d9SOTxO%~P-U?6E*8&8nu8Gs1)zc$rQhb;Yq)rcI0d z+7G=Q4JRkwE7%Ag%`kh|uN7us5r?GRpY98R7z`!T{($iSUQyMU#hoqhGX|0H4Me~( zKWbW?OortC-D(@pZ?^y@fTk(2^r6+&Vr+HSK|9a&?;g+Tdp>3s3%x+LR-5uRM3+Ur zX}kc92?XI54};V2GTS;wQwSs!XFqA4F!tnv@Ch8?0ig3<7NE5|ubrD3Oc6YJVijrk z1T`2H79fx0(|`-F;-d*b#hHYq{7x7UCHVkWqJ)Tk(2x^mRaJdocSM!cvhNQ-_t#O@ zb}fa%Gu+_^y}`_GY3}tkP?@ZLOZM9j{gz7zVyYxc=nNnmKJl%dVUGhG0FMv9oI$W| zLwEZUKbwQO=9UUH-ZPRTZxs`oaJ*(Q8}4nUCABFsFnJ_5z`0>@pL+cQUNot!pqB?C z%>}&taqx@XAqp}Zoz;GJDq4t$um((6%?RUJ3TSREH7x(zWid`&SC0;H@J%koiWS^y zjo1On=3)WCXpz}Uhy$uMs21PJOzHeV1A8k5U5`~;)Na4vvCPVKqFr1>hrS82l<{(1 zE~+XQWTaabs$`!6?0(%m-uX4`?D)j^zcg&|*cSqNhGQ=2Z8+Z9dDec|Prc@5zq2(t z{q@mDL^kJaibOdLE8(aN@w9Fo8TsPP|pFdT{Z{{7wE}T0S~Pm z1r3PB6M-DMgPDW_!PeXa#ar(8REI-l?m9d)J?^{{EI*J}jt zb1tP_zG}Vs{&sC%|G>wmkD_4an;NePHOj$!V(!W?8}eOiD%nah1yNvPXK$fodM&;Z zz&hB!SAoyr;iHd;0c8A0hoIEQox$b@@8u_36D|`V%0TB$;ZA_DiE$JAlT&QKfF48R zT^lM7>aUP=bmYE`)3?Rl-QI4n!;dj9XX$Jq>3``~7re?XVs7>tEN`ra8tMptFNQjC zVXXb85Aag3IjP#m)ZlYHbQs?YMuQna5TDv&9H8b zw{zB|{+LTRv&x=|M0iiQ#kCkF>pc!Qh|AtAi`RL$8r zdJa{_(d|XMM9;ot^E#)~@Du|yU(QT$RGkT$z&n_8|4 zsG2;-5wF{wV1hI^MP_9ehO%#?^qmsA7eaYR#TaPaZP(-A879ym;sS@U5mdjDkyrkH z$}J4g^t#MZ-e7Re!aVEv1@gDhAGmpW2Wwg(fA+a?IT$`N(ge@QDv_TW*f>Bust*@l zQ5h>b56g75rc74}Q}d;Q0{yn+@g$)+IO43@A9SE~ehk&)436*{T14|f-m8VJiTaFY|B_(w?0q)B_W2t%8$RYE{J+X}AVk&!frTb2 zhynx8@Gj2ITHS6P!tI!Rw~gnBjaZ5UI z@Wy5cF-6{xcm{Xjs{4NCpc#uaJ=X)2=7csm1tbghjLr2Cs z(V)ZpU(II-@#A_wqR7K}0&z*@xFDpuy4qa8UhURFpJ$VR`MioFJc7o{l2^AL7% zTW_EZkG^E%U^k|=DqRA)DN4V8xRm7gKp~`qh5}bmz zN-X++8iTSEZ>=RBG5=9C@Ou-41z4Fv+_d6|5{M48Pk2wZslLTWe11Aj3YiQRXJ_j} zYh`#ax)2s7kcWx0M7ulXv5pHtl;i$J_f~XhBNI3)?fOrbcSqTQKLdD0J?6tB=+1Ao z52NV@+@wP&iw~n0xJ%LUk@)u5h^P;+0iR(^bJ!mJd(-NPwIDp7b&t_kFFH_+^Jl#2 zP-+e%Sk+T4qz_n0Jdq%rzY!DDPY$)4`ua{+?iQ(K`C}ODK%kFbDEkh<)TAWPo|h%B zm`(iQ0DWjv1vHcrg$V^zBp)glyI#6^&jWv|p|A>kde9a#elK{AmF*Y}fXJ8B;hd!U zzuv#w!IkR_h$Be?&YS4>Bj@1Cs~YS*$SVrz?mF^TAEXZB!QvHobfACJ z*7KnHA8coDt&21qY}b<dbrx34Zs%Q&vHNfW4jF9>2uXXuyP4e_G4ustBX6=gZ!Py@> zmED8c&@OpSAjF)IrO$gpDZCOE9!|oU95S*1uVM4XP&V#EaIp$+TFtPkTwmQKMEU0h z@A)6mJm|4}2Mn`BXxA<`iU-nWQ%71Rqkr4?S^-;92pt0!qxmk^brpru+qfQu67qoT ziIJLJF-wfYf;vASChA-#OCm&HJoS?vUfJ7-x#95r!`wFd`q#WXMpN-{pl)!#q0~Jd z#1{yO>o0xS-Ni;W&4K9xlrCA2DO{K^yiS-0a-CI4jcj5c0-S&98!n9{cLqMwEYTZT$PY1& z#(nk9KrSO|BE^~JN%)`om`KW$pH(l%0l)8Qey297U>6BE=ucCn z0H>^2=oAy9Ahk9;;Xm621BtaV2Gy@o)0}?c!_@vwR9;||`-5I5Na{UAsAn1;4qP63 zR8EEq3xiHSN`v|uTtN)myW^p?M{`N}>!F!=A;q1OkP%y=QXF5H@6A`SOR(u5T(_$j zj$vcLjY<+8-&7HUY;$vS$mODO4Q3D#9)Q7BqU(D1Z1wTaFGAb>o`F}6u4?_q6NUUn zAnB+WCHTRV7Sk8Jk3u^T_GAbY0-d_%3 zc&`bEQ3k{Q3)E1@^9zdV-$JcLq4=~FL=%BTHhS4kUTHBDLCc`;-j*Y;BPOvSUw#4~ zZxrx($_C&xOxP~@^xu4^ZufD;xUZCuJU0A)WPNu$mu>t1MN6d+MJZ$pnT70;kdX+< zC^K2vdzD0rLI@$*Bayw6lD)~6y=8BH$4U47JkR&nAJ2Wip8M73In zp~6H}Dp(sKo>TyIrh58$tEi~NgJ|5{fqG?qea#u5)^xwX*Z!!+2Be6h6Ne7iLYElm zLf0&ti&|ItN1?5Td%51o1eBQvD?kLJpaC)o+o=N>FR`v5PFd%u)HNA=7c?AExbwx2 z${jBRSmLI;@2YF7V|o2u3!$0PEq}<^FFy+XL-zdu)`bV0?x^pf&+86f~GN;4}xd{BEosphb1l1Rjiw^!^b489d3E#0Y>x#T!Ze) zGwI$u10bU4q<8zf-HuJUY}H)Q-s~<0^84UF*dDl|t`Ze0Lb&QQ5Z6QXZRpS8+Y){# z0;?&W4af%htPQ9sF=$Esh4Mna8FbzuTDR;e)w%f9xqsWUEQhyWoefVra6{v5D)zc(-*E3GwLbjxqKOGl9NyReQ4{VrItWno+BEQhZWw1} z*pNK4>zumVz3FCpcd9ghCpfoyi zWT53j=roW8v~MqK#<*$csX;fz#k=W%tyX(g8KEy@aPavrjQ2KB5)kgiGyje{6qz2! z9-BgAK=w!haKcbreZ1V@-(Y8vxbYkCLviMm;JY-@8-3c3)RWJ!Y?L5eUkA8e^xsrj z1hW|zK!f+j=YZ(&<{NifcEHs)5>b(}6ab%#q0QzdnMf#TVXx||l?_zrLGpk=k0=SK zXzLGtU z&W5}l>D6TqkY4?4SvF$#$f8_Jmn3}Om~U?rIpmBZV}%3umb6{q__3hS;Se+70zm)= z2L!8qriu9*J02u(s#>7=nu`x{iIbKPW^iyUjW1AQ zq8!cI5g8dp^!A6j;<5bq|(WK|+y+l|HK2F#J|7yih1Pu$r30;Y$po)C{%2Z4!xJXX2dEU_G=RrC zxn2MO3@(9#KtLSs{uyp7RR0_;0j*Ox>2Ig~T7cm}YYq7ZDLsD{n!3JMN{-FVMqHB< zi~!1K*?HjgUo^exBvS+wWkNM#J2SuiS%j8_HA|AQ^zrPP1MD~$krxz45>()1Hw$ju z<~LeG$Qg{W?*Gnh2+6<#dEbDy2i^=}6v8(@oXK(%eB=`0uWCsu6F_Gn`ge2EiT_ef z*>Ms;pYd7NMlNh2oJ|@K3$V;}p@zr0BL2vgPaSX^cc7$11nd`J%cFs9ax_>!2AR`N zxmf^2rk@f+M=@%WLmO;+MO$ytGb(q{GyglQ1j-i`^h>xFSUSKLT=v^-pjnUvpL3r0 z1AIE@gO`^VnBL>B_K0AB5Tpt1wx&vD3?p&ZZ9Y9U)iAKE82LYhPS0NGOh|G41Stu| zgVqS(#ZR`PiY=I>4H{vHei+tE6^vP$AAu=FWQzx3#>6|8k9Pjus9j&22m$^nP{8&R zld_l&t_KF9VJLJ4Ee|V=Jh&%Jh?fXMjL;35aTc%XU3W4xp1n@JA}A~llV*6Z#$Lbo zMqfq>z$RlhW*DKWRCLQh>hNi{qPV>x(#aQ;5Fnk>y8jfxtk#(DK{%P#gzxK04EOMc zxL|4zBD4EX1aqk)jMU9#!W2$L@j+6D_MU84-k1NQG_<(F@~AtZaqt0aBO0rMwZRNT zC;l&JX#`*db4oSPc0N~I@U9UAv_Y5-1%;+NFDtRW&Ch6uM$m$2(Omm)HBOUIrvP(8 zX#5hI?#Xt6Yb-Q@WAXP30U%^8Wul9)Nb_xE}MB8QJ-WCEx_mpc>{bi={*GhN|(?Z|%68$sXs z{j=Hmzak+U>I`FdPXPuQ%5zY0E`pD_Uu5Yy#Ha#enngji7pR&E8HlCD7GKhk>$WG{W@*uh04zCPJ&W--s_q z7?le;1?uqfI*d4N&(QcQa|;JId}5mz{)DpzNO(}J9f7InH%v78WLp`qiB#&mA4JUW z22(gDs_E;Gz?`a~(&Jtz7eEmp{2yo$h6;uJS<|5yr^&6#u|kvlPi%GX%x_sPWUT|D zeE4;64r#C2e~=dbVo^1#iaSjP9QMOgq`C^OLYEoI_^ubO;GeVL2eHGn-+%l#1&p-_ zNthz<%^%)GNcVw6_Mp%om^1ju$OkCT_4U?%k!f@{YHiAPbUe!8UQhv z`xVPnfwn?WO(2G_Cqi-1*4`&L-mx4!z%17df`8N<8U%NA*MSscK0XlGyRs zLpIZX?(b)1Nvi6z&Q^NH&iu;pbBwrJNc`O=p(EnTU}PToDesjmGpi@zq3!b5tPM?i zw#D5E*{ z933ml?LvqnIHnj~n*F|QSDeyi?V>1^ff~!1S8~#dIo+&d9hFr&8H6wu4OcfolW3R5 z-A~Gflir^`rlj1|*C)?5>EwjTGa;`q*{%$Fk4@%+{V(<^gEo92B=bA};uZ#QF8Wd$|oU#g_vW7f_3 z>I-AYcpy>+L*40=?REh3=0r=CaS-Sm0_LZJ^zyRS?KWXk7(qxh%uoxuDkK-!+lj=H zo(n}IFgIFOhwd!PepE=WukW{}zA~47$8|@xt$inw_$dzSy%jt7;@pGI4ua7>x)3fj ze<|A0MG@xnyTyvJ!O8h6TSNHoZ4vZ&kUOPmLkuqQ)!hbU>UnF5rfFUAJxKy-M=%%< zh4o#dt4jb2YVxH&jY)9$S8m3~#?j6nI=19(aP?cGr_b52>3WrbUU@3mL$cQ#U5%qJ zEbCZU$mX-HZEVm7Lu5bPD7|XtECbmd)-zqmkj&18M%phnb@dS~nW_^H>h8p+N8WU~ z`0l4ryV->%UB_h+-^lJ|ziZc=c zJQF(fTYq!4BRS9h6Lj~L@kj9+4PloI!yi0!={#)uiA8miH_{gTpY{=dZ~SuH6pTd6k@2X@ zfKkR!LR9s}q42l!jeWnrb89>n78Ww{^6h$dIn6&3j9L>F5jJvva5v*o9EDpqXk`3qIt; zDt#QO^Z`KqKu2hpg`|U1WWQ^Z0sLs zpmc>`N>r(n@z6x(MP{!VU#XD%8Q*8n*n$yqfARIrihC4pLhlgM1Ox4%Vg%q3KzEYl zZ2xtFcBtXyxlb3>(UV+Xe5~+(b#1Flc{^w2f{=c)iPHNd$AZDLXqi$7)J~>uUmQ-l2)C*T=pOJKPAkGEHaB^+46urD-;DSsqi@--9>q z6gwqY!d=t2un$jcw5Q{F-HiFuPsSd^D)7`*F+y18&EvmN}G_7A&)2TldVG6wJEACF9;y z$L)yHXOb^KYH&iR>t()rbQD`sAa}{1F#_Rc<3epZyim!2-cMDtCi=3quOIxugI+-F z<;&A4DwFdJGWuLqPPfxLQa0zwid+$`1(9uGa}pC>>zvl5ay}H7!R`t z@{*jLIof!go1V9>*)P4U*5XYKq|{)S3kI)Vh)Qi8t+vz;8}?BKuNnVzdaNPBjOHcz zmC0&M2CfGC0O!U5Q?il88#wN`+aXyI_EETkk}I$7YDD~i*7i*PdqzVodKqe{Ho<7j zY%ShgRSh-{@R8wa5Z10D*?im%CN5|rzY{Nq3fuz2w8Z=dsZzcOBJ~;SHeB%wK^p1~k8Ett^DT8Ye zTQ{Q+NdD#Dh8B;wg!|E^oR@A7ZCKI6Gn4&HU-6vw-WP>%g$rZD-@$-MqQQXQ2aH1X z=Kc#Q8aknsLoQ0qw*&Hs4mo<>1PT**HEcqapWgT0ulKmn5<(z0PTCk}mzX>?@p=$u zqZuwXx9rF(tyngvwixzu6 zc1{l|EQ(%(TdX#d)fMYQ&@`Ok>vaaJ;Dz`c050u`D=1cFKn7BUIIw0xdbz~VL5ESx z?4;tNSc)9UK#rA_HH_a5wBQszQ6jUU9|^6^&8LE0PLIZ=>__MaEfAptW=8dB15G!d z5$cl{krUTmGj)ZKCzx;a^kvgwHV`Faeg-c_6 zguS2vhf;f%JW!{k9NSJ%>!kana;zhMGFOh@RLD&QhfN-yUklGK&e)|A?J-HJ9O@MZ zXbN}{lMbjH(gf0h$6;=~aASyn?$klA9Rude^14d5xjWydWz8F9sr@y}*lUiKuL9`C(^f>G7J9)T8r` zsd`=}AJ<+&*JkN0l0>HZn-|^}U#ziBoI9%yUyn@MFrDFdu2#M)S5?ynuCu4=FamVU zv2_&aW37Om8Tv@D2JH-q=J0^{Q{PD+xh^NuPTb=vl_MJusbkm6Wnii@V}M=6D)4o) zJ}~f@-um{&(Ud9umV#X_pHNL(D;o7{YvW(4Gj|On))#Xv)vgIiXH??=898@5)Q=Q*NGjh${t#law{y zeD>NTgdy3}Y{5C2hu+$H<>oF=mfO(_^tLAinUtEYk5KylBBBD2Zz{x&L(aZ zXe>EM515$`?)Hpg^bL)@pvyQ$-hZoWjr%Uk8Ps|NpLT?xX>6sRzwhk;zp5Lel7MKH zZ^TPU+b)iD6B1B>i>&T0t5xAc4e~PamTaUQ?OlEH)7|~y0_~Fsw>~Y=4B_I4HX)!8 z{Fq64a%xRFD#=pXCjQaQwyUffMc$;8V7b$`W^jrZ7R;XH-TfHrl)j<`Hg*&cMwuxJ z%`qZwKTZs^t-txdV6Bvrln zjl=w_Gi2&dvc$a=fa{;k!QxC^assH#+L?^d44H`ALuVXp!zNp#)RWdsWidsy&3Vw} zi8s#GZ)p4EYz>*K%o5-pKB&r@%fIh|pQQN4xnCLL-@jY6_4L#pJw^k(WOMVCe?oS+ zOa>u#|Ja96frcoH=Dl*jOkQ$<)vb8!c9fQ2V~kvz`PA?cQrWl9>e!d8zjLVr&O_l7 zI$mSQzOQ#rw!ZaQH1xs68Y#oHVJZanO)wxhprTHzd;5jZ#vkz~-nai_`X6Wu-;2QV z+#j$Hk!(OR>veO>xWv5vKsPTH2m^@g0JMvoGOq|$N+X-^*bC!*p9U^4`(Ge4Q`ogGS^cw9K*^)kg?$o0>D0X zXd_%>vN$%`txMiRsG7EO2BH6rgCY1&j|#$yMA*S7q!i#|63T|jM(s;mi*IE=5In7} zmYM0-CJ%Ozv*KSav-<)i=KW(RYIT~WDntsqHj@U-xMuVAH+80XOj=|>)}%qY*e1Qjv8@NM}8eGbk;bzTuY+@N%XR_OFI@Do{v2*ylfZ~T(3KM2`dv2`g3Tv z_!&*rrS8OEI~1e)Rb5Dw#+TJJrAtn~Kg+v5{%T$6X4>TpX;e!O!Xx%#aa-Lny8#yy z5h+<&ABzga#qQtI__P#4yB$hv#$A0)hIx1BQrs&_1u~)voeYpjuIv7wy)=7rmKnv3 z@)-%;z?@*XoMNuXs68k$@>6y7*qvJ%e#~<7r2nL>Mchywwb*+IdB8ICtnezVD7&| z*^=InnN=KgBrf^wK0S7Pu^EkE%QBHDjnNsU_MZFlj>2fk%cR?Yr5<(cxc`!{DA7in`>h-<%_#ev zr!iqG4XmZiIUXI{?VrBBzDk+jE6nCtwaIyc zC&K%;=oykI(IpFOzXSF`z3}BQrf$aLU*YLv15I2T%O1jqTngC))>S#eCluUvjzBpg zxoyF@w~Fhqid}HzIXYnTA2(7T!0>%5hqjfQivzkKxyeRT@}2R$4$wWwYK-Uaosh5= zk@YX1WPe2jgcv8=T;b*(-`Vs9WFo1R{+!t6xK{d&n&55Cf1@-qGuf1}=87 z;mfO8`I#CuZke~Qeq(Rz0$H8gZdLVGbU<*fyxq>)2#C1p|-3 z>gAc~H(tyt%X^_a)#A^*V4BFd=1>Ag$sn9Zm|e*OIcl#T=^JDHsxQE1szelGpLp%% zbAqqop?SREj3~B3Mml>~$sQi<{xEnyS8|(stVh=Nz@q_|USj;I3d{wElOLLU0x4w= zz#G^12HHQsFj@Zv=ReafQ_9K|s>xh;P+*2qanBaW+8)P3|@bFINa?yGdyJI!*Tn)!z&BNSIjRZmJ_j(k(+$_*h z7=rlWkuXb_zmW@y3Y{2H z{zde!)#m*I!7eVlm}b2Dym9V#Wv?c78=43yx{aDah;TW+G`fWRUE0YnVV zLQxHa^PWLT&46S){j(a&x$uA(liYjt>HYvce-EN%urtEBFsr1sZe*Uwe77}m2UdbW zF$8gM)+V5IjO)Vw^f1p^(oepL;m`kxgS{S>%KXtfFS*gW{>+!M4WLAI)Sa^L$1#kt zp1@?H4d)f~oR9$46;ZPn=%YheH$x*jSB(WwNIaxeG|Mr2vM&rhoh)+e?jdBQ24}(w zqg(ewN0C;HKP?ncadF1*|D0ZMxl25V0C}gRMc@^TY9V54K&&x$!jk@ntm_*A8&?^v zPdUn{diK?OdDR|X9x%uOl&bK^&piUt;Dd;pQ-(@(?pZI8%^IQh1_tXgdO9Ym|MDur zQizR0~Z9*iXKl*z~;K-rzyEA&-o~gnRl&33+Nl6*tTX4e}C!scy zXNO;KCu#x~`CbjP^{DkdiBulQuW$f&;F__pD==U%1qtq3W_o#%HS7D3%4f$hZ?&|U z3yx+T{G$D{#}#(&$PTX#me99daiGyj3(Vxqc5agyksm1rv&bX*zK%0fbj=;g+0Qy) zm-l09Lt3Tqd3=M9Ef z;Fdc|#gh2YRf5s{7?H`n33nqXH|O1rmEW^a&=LZA>!lG8y$@Gx6)u;rXpg_zK0;$q zXWSn22&j7*S=sY%w%P9G$O2XF@Il;ZSL;WwN4e8&z?_HTV929 ztT7E|N>4I&L;|727-Ub9Ad2r?zwOayKz1&iQ^o5m0qiZ5!CpBnrpbLP$BX-|sj1uf z0U*LXok_97zdz6B0(AtE4V>E@g1W|~^9-a6xTEvy+1osGy|==4FRgm&)fF;?pAv*# zgX<2iVckh!=@K?(4W*XKtfo<+wl0X0{Zr{1ifTVI-+%TGaph&+A4U30726dZ*P5Pf z7|fC=ePXLJQ-!%jmNUm0(9%RC9`W8zpPVUebm(9AR-4nb>y3LwUZZ^L7U6=+KPF|V zu{c}RexSc@^oc~7s-ap-M`-Gp6f@5jj5*`I3>YPVxxl|gW+a=^?cx`MIcZO7D!^^Cmz zGqWPnxwUeEVncb%$Sk3UIAFw*p7RZbh?Kx)&EfYDnQrBtof%nY$SqA;+%@-~Xukr$ zW*fM)vmYIxq{8xG^!NZw^<(U)eI9FhoZrkKbL}#d54V|V>~V015gDUCGu56877+;Z zVu}fyI=QaP3zuh{Tofcy?P^0gAZMk3`5$rV28yW#Xq1b>hd~1&4|aPlJwTSVn>9m# zqwt>6`^rTvzOyHxzC=V%9_GbLGO`}GxDc~qtPCO-Qj?O}x#`$cQ##V_O!6|2a>EU> z07h}pr8}X=(s%$eLID2~F#EPu`dltz1(qxA`c7=R!foUKh;O#Es9y)NaW=?E2nJ1R zvKbjX@R;c6{tLz~N2ZL9jz*h;EnZ`R%k&`0!$pwz(x0JdYTfMAzaTu(a&z~KG-xy` z;6AvA*{9Q)zm7^}O6sc!hHNaAM-Ii`RRE+mRde;Bl|CQP6&QPTacQr(MTr{<81dqZ zC$RgMDEwFR7#mlaBMvzNRw%E)*O$kL{S5x;1*pFbg4`O~Q5{L3Tan_0pdXV%e!RB% z&6~cnrKM`XvCx(F3#Xcbai*l2=&H3BTWdvX)Jt6E4Slg%)NkG5k0U|h-=Khp(*=Cp zH8$6)gHxZ+dY!rKs@zs+cL~^622i~5AKr9$mb~k9TC|4(R_o4$O7qZ@hc-N(6^KOX zxS7Z5QLH(SLFqFB$6g>{w;SoW0{tW+f&~lCpf2BFClo_ znt}9;mws6H+2)y!D-K7`x+e|m@y1NrBlrF8@`?rsT8Dguw7|07a)gO;!XdE#jb-;A zAy6HE9U$6Q#>RUrXZR{#Ddlvh?cWszi)i%k{C+*TuUKiXz6lggGXAVIZv04V&(O6) zz^HGIjZ|HI(GW#8IyK)-EMBnfSFg3KF-h|f!+QhzauNtlG?{b2wzP+sHvY}eumq7Z zz$b}H%?PGpTxgb^{mQYW11almDP5}@k)pdL|B>1PE>yiJe42}t8jLUzxY+ayg?5iX zHIvhf*$-a2sf&+i!Ie7F9EfRBMCAOYreYx@zz;Kn9 zXoEriRop;%d`t~Wb@Z(W%3BGaWFv&-q158~NOuHd7lhR~ZEByK%I-}+ytM0gmP_(K zl3O`4759sf8UTzp0d{@|Vo85bk8{ng7Sx>}8eG(_1SR>AqhFx!5z$4dCe1KAg&ZKq zFLny?IAUbSBGsEpb<>1^3BNSG`961`tIpq-_b4Q~M%Wi`1Y2}a*Rq6X3gzeE*A+9x zc1yjk$Cv(#*{x85CLTD;W)0>h)j3D$)w=h(T{bycS&8roOTbLF-_p(ZF_Tz{TL_n; zFk^x5@x!7#bCD*dYOemrEL)xyXhNjQQ9Oft7`VX#X~rG_p;E1$4zhNadT4uF{uGj> z(44$U6i(|t2=~tx2!;4k-!gOcJYZNl^$F%=-DDw^l$dK4=tsvD-EL`nBu7S)vUvus! zAToWozX>u3NJ8IJ;QP|6-_6pr3*`;vbD;wmg;I(05a`{##lhnH>r3zL{_!{FHjt&> zPd;Q98P0_-Ro81emQHvwb=Y-i+EoqBCqg+iys5t2h%eV*VW~)E0*_4kRFzT?PcR}V zycQ4-O3;plqL3&q8O*lku7HSYz3}w-#eV+>Wa=gR`H%w_%;h65B_XOxywOk};Ty(A z0uu<%&~H(r`w;EWeb4s~O>Qr*B!_N4m;&pWJaXO6;^O@Zpx!6druZN>A5YBUtD9*J zm>a9QS}kUed3i2u)xn9y7SNmjT-7D>(pv8|&%=YM+0VBk2=E}@iBzBx$XktM{K!=% zX3zktVSo)8@6q$gg3-X)$1RpDW-NC0zDqn&Q~Isyc~Vx69c*R_905f?snWy+>8qzl zU#S99@EXJ4oWdVjXDf1yzW&@V5?C(i;FW}Ux%b4^ihrLd;S0ACh{P_~7qP*Yf+5Cr zU$ZKZo9g)VQ3MfI7(IJoo)n1oOVu@nONITjiVAji%9Q3$MoxlU|CE@ZrK;-jt=BNp zlVrT$mBuR!DH{ce`)XbCxkig#nW5*L*$<*zL&W9>l*gOeq4^S8BPQvdzHD3mn$|A`*q zG6C>?8PZx=FQ89%-B=VJ2ZA$b9DexX zZ*)Jw&{X@v(jCZ+dQg@(?F5xQKq$leoc89{VuLhHDV&B#gtwJLHaE%(8XzUW{m_a7`xLCiw)GdtIf8$BP51&*BS3a+ePlY<2t?-5$*aA@ z0m~Ks3p9gk+Cb(*>xY-A8zL~Cp$>dZT*5+#3T>F;9*LBEE1HrFhVQT^Q-S`%Dx00Q z+w0%_%e5j(f4t#TIZMm{{p$Gg@ZpL)WFGz7whFDgWx=NeF{-fdmJU1cqRDVDrhCqo zpBdo`g*U$Rz5o}^+b@hPJP}T{t~X4!M=5LbR@V5Zrs>j|L8CKg+Ap$3smm# z!9;mNOycw6n6u*pr?-7cDgGO}aT2gik{=iw_ybZm%y)mY$vM>m@W@IV6-0RM*NPDr zK4Lq6Jbb$M;I4lvete{@y7&N}(}ZRXsV*u0eM_&|76supe)tCC%q+*q#?D}Ozs@m1 zOu~csm0Xv))(5bEMYmLRc1^TUC`&v3t}5jmnRj${HBE6)01@Cp?_A6221dI_6i9d= z<9@M-vu7MK77~CLBvpmWSm}JarzU3GC*S%{fSLmac%KkH1tzNr_s+Pvtom;(KBu(E z#Hh;uR+`Yp)RZXP{?~LKf~*EdIWP=CwM(s#mA3nY9iJfK5&y_0ko~@u4_WE`I)IobaOSxOa8zChqoPi;-`E9iC8WMa>48=OlV3Wx{;sb1N01XP zPH&c=G6-0DUm(HoyN-9KWX&xL9waKer+^OnA!=|XTxM)M0=U`HC&GUKn8R{-cOXhO_;ab51)53^!eZaX-} zZnmL$McO7?$u=w8Tk`ejL3hR$=(QwUa4rZ$N z1H%&X-*@bu^GP5&SWy2}ZDCsg0cRpiaqzDk@Jz283in=q8u3+9J+CF>`c!=-_8V03V%N`9p+8+Uwf4czoX_Z3pbBZyRS{@9YoySr-9Z4h%&yV0i? ztqVmo`l++|t4oQ9{?J#jUSO*0`9Ml8oE5p0q5r2!C;ia>-kaO>Or z03rO-HR7($*1|IL?0xB|JKpOl3=ZRn;5!U_U3c8_x!w8lR|(DrbO7Y+jtXusjkz^K zz(^XqO-cH^>W~ws)%MZ!t9K|>pwXj3|LgKG34bHA#h!|h`E{CPUN>k)L@5&00t94e z1+}Os@irnEKVa2or!{r611?>_D!2=KFQ+{4&9m_*kNQz{z@3Z>zzi_yx+NlP(vU2m z5)7h9=Z%JUo={8iKThkl<@oo(<=}0W}$18-o#k z_M%w^!crWCd2|r&xGwJCObDy#Xh}*+N~Co>`lXlK&1ZoTJ_XMGsaEvvZ-2K~Wy41m z2DdwgiyxeGp_S`@b?C#TkQI1fsZisoR#SN^{t>B6FP7t=zmXm!ybh-CLwNW%G~yvK z&|Q>I*-0cks!PJc^*(y{ycdu-F|gD`IEOT?^-$pS;SO~X*=kEe=Dt&W`tkg81-^lY zF^*~Ipt`Lx`Z*T~2peDhT@yhnLH|x9*tXNfy%DvuMbM?P7zxyy1`9pAprOXk9G9(F z1<2%23hHjW5L*f?lTZOiqm($xUO~!DsptzfwMv6_*Ma! z9@W{~&^7e^2F&@;p^Y+DjjcpzrGz}~9=h09=oU0)QfSl>@-P>^30=y3^PpT6T*RRA zpK|5I_(T0q43?eJ}A9LBj|X8Y0<|7eSLR&76Z26UWRv(1GVZhE9{~w@(=@nMYGY zk=-=u#*;hlmb+DDJ!KjD^3G1G7)tf`97jepaZdL_zpQ%6L<`}P48G@w=E#OESUOxo@)X3lvoCE>!sTf_OM&5&Ae4f8F#+VTzb8$;6! zY62OXmDa#SJX4@c0F)i*5AY;%-w&0Sb+beP&{0wSe`)D4IZC8?C!q2Si{%0SLWBeW zT*f5IPEld^TIc5(Xi9?ZeXsZDP054UW2FNZ%};_2c+uD(9(2~1blJ7#DD=@n>I2P2 zc_+2p{pMnBmo0bjIGqu2uYk2txkvQuYc}UbcB$95H+pSuF4Jt^3U+|ua9J?&2YmE< zBVCiZ#WlZTF7oyH0G~Cid~+GS1OQ~HVM9c4xuJN0dLe)c8Hd+~axvL;aB+86l(?cP zA+}ToQDGu1n@cSUHnZRSm*y)epS$!!m4Ey8?WN^;qX<0U{Uoe>`u^H$-At?$B|XHM zYweEmHgc5JPOg7iB0`*n6`;TO;8Ch^?QmqEmFh=UvwYMHx$ptH+5Y62gzM`;;di}- z022FN_aQ!nn1TJO1}k9+ySa4g`o^1q`Sm*;!*?_Td7?8PiJAfQs-fYm#eD#iBKv_e!-Te`HrU0KxJQ@nh~N1H0^r zN?hzU$u^y%5B0WGo=QxqriV?RU?(smS4DBia-bg%_6=4R01dNhKaMDcc5e+gc<INGnO}-ruVWeMyOstbz^X)JH8&sItv91AzWf%K=qaSnyD*b*>Ur z2bXa%G91vAl8rZRLAhK`<^`_;?EZwuAvYKi5v4-=1re{Jb@h;!4+6U4h}m$zXqn$U z0}aoSxGva#B{^_`(gHSH2>j>qW4u@DW`azEp84WnVzK)w zJhXkYD2+b%k%m{GQtLl%?W=m{Z>i~^m@L7YPyU*7@$Pzj_z zOz?u4!ynvsK>tqKyM`B%1qoY()xc=4uvR8T96dRrM_Y5Xy8Js_XKMj23H2j@(Cc*^ zbX(eX4=o)tg{C%zH^u{fCnvU9VmHI#hnbWXfecdstKGwqP6~&wUum78n;v*r#g90sxm>1C#&-L8bGV*`rlqkwdLZ5f-v>M+jSB z{KaNq{Okqup7De3PJJi+jVkMBuF}ILYyYBCXIokpM$OU_q$@LT;@ta&7~Kodv6f zT>4gWO69-4o}f13cZs{@#th%eMFO7)oYORFVQ4pGK1vN=?}6CDiH^t*B( z^E3Oa9Z4uyM)Wk8niQ<~^~v=wl7MgpJ`dSexnuZMfvy!~#r~}k&9GoMf0Iu}1-i=A z4CjF=efF<=KGuik02VfvPsIv``kE^h*aYzU#WuYuT{ompU{%>v zn0!&f!}an1`eb9oLz8Ck7?c(P_u=MOL#E3*pI|T&S2Lm)!+|YAIBt6*nZB>1zA6~{ zLSHe(@Af9CbZ3gMI&?)az7{Q_o(4!&F5&jHOBOXL3CqDl@7#b}hM)L{Ch)VT_q)!v# z5Wy1#B*D!3nIqzlP&nSII@>=Siym#g6QQ6Wob5BXHGmwKs$$Qk4_{W@I3>*%AaNfW zj3=uyPsm)TB$(dILSOCRZ#-Y2Y=rj)n5aOdZILFi@5VAzSUL5XV~YXY7fn-lHa4#p zxP7JBP_)o)7c&Gf9dJq3tJg{>Qnx)?c{%+(( z;kzpHRVLvvcTwNC@}jzHGOMS16V?fYYn9;k9g$jI@ag?5go;6`+Px|(FsERewLsz`E+`s|CifqcC&9l9zkk=P)hb1s^vEjf^s)nn>xvtE5qT#v84`= zJ>aiZk(oY*jdl;sh%0*1(DW45HSR>{;#GH|0n0drz@>PgjHY4OCCjl_{Rw&%%=6Cb z_t~kIacDncc-;*%EzAtxK194^e&$%cBw~Ubx_#yNHP_|@-Lx@~Dn~+jXF=F<9Qax~ zA`R^;RP@69rBFy@xP1y@ z898jWpcP8+^ME-50dsdiFbG8@dN@zeMA4kUgM)r3!P3CjMBsnHrE;gL4{jvI5{3R> zgvI{M`1-~wc{t+<{POIh%bzTKGU?QU0^hJmlT6_R0@0XvJJfuxv5Mewh2CK<_-tp{ z(?!(fb{t-@A`3`SN5^mUX7rTjk#UD&XbWXwglYg_mV#MV89@?yEiAqT*7p1n!T9zM zdWw6(vik!`Q@fEMyN#~`-U1DMGSlQE3v~7!JtgOafW{eNM3an*pw}r#!-;5gU|qY2Z`gj}oGs;3@F11lUr5ERnZle~!oo z?W_5(vbEniLo-%2h%vn0mjIZxcDerEuwI8jH7XL#cbvjN4!C`}FQf#Wy;#Y@yOn3q ze}SmVANx<&+k3hgc=jCf1)aA38Zy(ru1%cWY)u8+h*gung=GhJ>r1&+8r9DcEE$Nst^ ztu(~uj$O(ZD{n^B`AWu`--20S-hTqx(4u1qD`kh zh`f>76VSX|b2zkiGJ@#)5qQs2d%&0K(UtQ_s*q2M`+voPta0!OIWTVU@;3v1beVSe zt~S4V=G4ttvs|@G7HO=%X8cL+fpU@`4E=^$=V!4ztH3wiYt zl*#2}5t7n3(UudQ-OCiBpzPGa+_PZ*1QSK&UNZM~G)?HXhT^Nw+@u*Wz`-XEEEJ?l ze)pTJex@|e?YmXI%LytpsLd@Dx-c@>EpJzP`^jAKM8~~uezT2T0F(LmC4Ygamhx;} ztb_oZmHpsf=5~#R&;H-akBSqSG*vlts1wu8yy0HnHJqE(nYuhJuC|&A2 z-WU(z5lNB7toODT*|{VHlDY0Z7Ih->7E69||0y?z#L(NsgE&4~dO_{^py zY-4a`?7nEytJZ}dA37F)eE7!K)n-bFQ+v0rCd_K)RmWHt`6r&xBUs{7RV{m_!rh&F zViEZafmvtk50v%j0+DIeI)US27?9G&%hkOzyQASWv@8a{`T4#JZ;abw~loV3XrMg8pNL4YtQDMk85jN?19uvK~G3dm4($tMvKeK3rCH zCpzNNTndrdv)C647CTHy*=ae<$DN;=IDIhmG(N<>czM&K*M^KquIztEDmn}efHiAu1GlRm_|I<$#CF^Oi<3;r?@?@lw{%Y?;I z{(!(xRyjU1Q5XJPtAYIaNpclTNvAEWEq^eX+3Ne9sTSv1PEp8fYpeDIJ^i!VK|)sF zq`UCPaPGUZqg7VGD$g;$bslxXK-?<%2oB=?N6lV`zk7IySNGLhnNN9- zTvXCE1DQV+G$)ARVzPn%bu7PW$*VKxyh$*2VX}q;WdcehZ6~C!1+u6N)tYP;ZldEn zj>1?}d0ExY`I$+1a|QE0xV!ls#hL^fqluY`s(YHfe2#j~%EIa?M-Lpor5hK}X50}` za=BEfZtODL@pa$JHEL!2DZyCU>_?r5{7)|l#-7Jw?(5&twkE|SYK6`pUor+OVpho+ z4llIb`1ufiJ~S4L9)7+qBQkQSq$S*A$CY&QL8Ll3hN?!kP>Q@i7(wV=Fpkb*tC0Su zaxZ@iV70nG;MNrX)7P_^hDgUxj5pj`%p4W?^HbdDZYQc(u-3cq=8tG-98yx?)0o-k zoe~(NHN-vn^uAXIYZHv9rfUun9>U64EVEMh{e{-N6%K@l{ z3j;X0tZeg!)2eBth`ot#f~{RzU1gAd1iw2q@$OH@q;O{xyoA>}yY!C*472*S*kC=% zzuP|~CR-b*-(L911>!mL9CAkS5 zS0vZSQrc7NU-+t=t2uzxUcA6>H_}F`eMU!Tmbs<`S^f?e*wmp|#$^5gf!K<7g`-|m zmL2U*Td$E9jV6IXo#ln~?ChZ3?E2|#yv#xdXa7ZKq&iDuDSQf6SbHJ+jXK4zzDQlc zVjcKee08RIIzIN99oZBv*c7Yuj-n4&u8#iAlKDSRjUeivqU5s(*eskBN2*~T#FysG zOghjY&QjKcm_T zvDqw}CuMN3>Fcy*PioLI6xvF%o)XRcRfh$K(-Gj%81kC#`OE0LX+DU?|tjH@o z$`14OuRT`kqS$wf;{HbQ;+Nc(#d`jA|E_V$twkYKqgscW5X1HLnlE}2w|~1U%)BMl zswQ@#;E9L|{nv3mf8Kk^J0xv3(kFkoyNcy(_ipE}{Fr(MkHmzUo~up;&Re(yoEPNW zi2|cLe7UvmdB?D-MiwVDY1X{(RX^{Bg^KFx>N*THPOXm&Bpuye9%IoAfUDQzGj2=k z#x+G#tf?tXI|%f<(H6W9aUH>MR7m)EIE12DuF9o>AB=x zip7Yyn*p>@rfVi=c;vROHV+I8Fl=@8@3xlCS_NO`b79@x;#N5)Xdfzx4&CL?@1iyr z<(EDVtkNmqNh})RNuSI9^(2P-;33Xd9rem*?x4(p#n+nqPx}|QgsYp~{CuxpP}5Fs0Po1fG89 zKfm#p2)sEs6oU2p&wvp>03*f%XyNF?hfmVgYoLR7H6BZM%L8H=#n z@BI6wTO@SeyU~=9z%l){p6+?uq%QZ;r&BZ7#gr4n;GN6T;hkx!uF}yPbocj08Jibr z0dBzV*C)SfZSHPa= zvEvmAyW5rP6aH@05&>+^6Ta&$$Jq#R>674q3hidAGa|J(=nZ(QyfUZxLCg8mEkuKZ z{ZUNVt=l|t7Vd*G99L6-hi+b&SboK__ls(TUeC9rM#P2J=l!p{OFP0&3p{o!{Jm9S zLzmz9m;zhlMH^jtZTpqyajuWCG}>?ZsZ zCywF}Ti@^BabEmzgHt`lhl3+se`~O47X)3Q_9*8+UyodZoEC*RnBkf0phSfJ4 zBjf(d2alIKmD=-s6Bj>Aac*asz&H4^X4rQ*xx39p+%O$Zjglg^Siee860ChP^3-6~ z9pjGS7~w)SJl+G~7T0WNtHaYN&*%>RMJkw^H#(;zlIu3+0sPQI4q#xRPLp5ht}@Y6 zhlzyUouQ(|6@CXdlWBq-2Sc7K`W7vNED-Vxd06G)(kXlNyt0T6mssXv^HQ1$qYw>S zqs!}C`eJ1X2)&sLtvx=xaik(NZ?ifxUHmXM;LiabA(Rd0N4K7Hinv8BX*j&U>s|0$ zRvq^L*VeayLz%w+zinIXZd$c%IdquXl+H#H5-LTaR4Ro~LP$h8Gqc-vCPg_jl~W}Y zNzO{Kj^hxL^E#hp#%VC~zwdWO_1)jU>-t`Mearj2&vPF>_vilH&kP%|Oq;sOSn{Oh zZi7-wCV&P zpB;S~;w0oAvYhgJ5GM=mJ9z1ea`m6r|7hP(T6%~(+%(GVOd8LZPkXv<-aPZwVmy&U z>%F`v6CLw@{gunfqK%dP0|$-n{72A96<^*BM!O|$}O6K{oemaDAXRn*oi*d- z=9b30#y=Rke`(wCB137WImQoRoAi^Y1C)bwa%K?Va*GwC2k5X6%-_&&qQasSLWO^R-DX!IXC^Y1iq_)Fo@#6De@Mi29YS=U*9 zQp`5p*ikBmIX!h^{L8}eGGUK5#*I9YO!kM#uB#$rOJ;az0+R-h_~{zCo%GCiezS4H z;UD0F*9sv?BOaJG`bmtglfF1-MCpM##Z4k;C18IFy`kYLq0WVhJe zuPv3nVo6-qHb%_W&2L6MO3GJXV+}3<+p@Ap9CF6<#SRY1<~S1%mqXE`r>-r`ydz;$ zI3~9_fG%gG5@PLWbHGMBUbM(EOB{Yz&0ipT@ZR&6j@qN6qjO=hN2+745$6ox-q~I0 z9f+tOj_JCL4eB?@Uy`S}j%FydchG#LL(Zz69O;8^TX=F^WxVN%@KJ*3j#~Sy$7iWl z!U?aN7SE3YHA+KTeEaS5kK2=6v{J!`A1tn(+^&wsj4*c&(M?AAJ{>r(~jxOoHx*f zy20)F3&2MBLk;%w@-iJ`-{9t4oKl}BJg-9~kINe6j+rk}4*qc9w#pYPMrG;UC|)`H zB~RbPlAO)J+7SOGWIolO`&14>5d#I1d%?=u>&WkIO!d z9$o$>ODXAIkZ949xyKCxAddbfS0NU^f{X?@sJHbPO7%HU1tmM`3Y?0%3HqyjK2Y#- z=PYC&A1%YI2Rg7}woKHcM=JrvyV9McfY;W|oJFow@(CKkjz1@A?TeUwYkG2;Cl{%UCrE3J-p}ph+m`{GV zmbD+sV-u0>iF9F_m;qj3$cOa9G5$t3gx`9cx>Cd3=YyqI$?L2%mFfnkjQK@3%08d- z7;2$(WEiFEk8ZFZZol3SMx#1cjNiQEAtg){y_z{O(vh7R{dYk6LJhq_vRBU5!qRF6 zszdc^phmIczNkC2#l?J%AL9T)Q)Md!l`4l2x+xI0W-*r<<&iG33dLR~sqF?qNwk{Z>bIoMem;(hn4~`&< z_y*4^HG4~2DttT{I7-1_>7b`jH&Z`zhtZgg5nC0$VGnv?ohw(ytFJT$k5p$&I|}S) zagpDq?o+dpm0mNDpU_(iUvEHNf_am;|L{>opYu9r?4VJtOB(J+edY{x1HhWhcD=$< z-jagO&U4U{ZP_;BQLoZH1xMLJZ;jLlVE*KwFkd+_n;VH9u*OZ4NIV3~r9W!+{ z0qK!=k_C}CY2U$;8R7UFr6_lVX4PGR{$kJf*f(^|_Z74VyTF?H zNiEO6+0A{2|Jf_hFj4iz(CWvbM6a&7+o}Oxes#RCKZ|!9NaTL&_i|IP4*Yqz?MNXm z4Z-;SiFdteO|=WBBb^`;eb9h0P;L*M9I@80V~G2XcHfrj__MDMdh10b{~+kIdd}%O zBH4D1nRp`VD;LrVU|GFp7D27W*W2$tIdWNI+%h-o%m3#PG6`>M$!-pp= z(2H`fdGVfAZfES5h3rdsv~gkt`tPDyNY6tK`?-f|Y?J6ZVq&LemDJ0fuxSJ1X~0ot zp_#`n`E6zPI=M&XO@M%Re96-`L_4U5XFjUy`dl`xaoqC@VH^ia7twydqR|PAq9D6w zptxGtytZDy0c9sHjt1B=X#T zvCj~atg+=(yqiI^O8}8IE`g3dRU%Yl^C6QVkU-60$>)Y?@I~kFN4W~n9H8EHyt1_P zepc1VdGp3^&!as6;@3O_1Pb7a6)){|F{``7HwaK9r3iN_a_jNu`(I{ERa$<`%Pmee zZ)rb(qAM}@GRkD94cu-BdHQ`J9A=&M*#?BmSef+0gU3%CBx<7exIfoR+z#y}DwHTY z5@RP+rba0pp~;Q;6DB5?r&2#$6**g+nuNe6MvNVGadk;_?TADDHQYm>IMK)7;f@@? z+0GE!b>KRne-5MM3Y!AfZujq}FX^NGX{07X3r!3TN;uo)1N8la#q+Jd%q83`nJN{5 z(W8ARTdTPXNm^_w%)D|0+A?g3sZwM^P$D7n1i&UGQWiP_ebUPWVde!#MIj7g>h@uk zQ(}}7ivJHpfDMvM=NRY)#VDmlv1;zmfga&$u^8dL;L(p|as9mwDH~=^%{=pw>8tS> zv@TF%jFquuwr5P+Y3uRzDb}p0x=U6uD0RV~q8rntAGN)nf7AUwfzFi{lS^ zDu5ng>%xC5U@?;5PF3&L6F_i>zwwhIM@+WA4x{h{z3W3Y_pMS^C1Ayq84g~8cWOO_ zY&e)#atd34CyY2$d&%9dM6WKskNUpbPFj-q@K=t+f9uCn-&1>zOTxy9*Z+W~Ex#b>I)N2JmlZv{w98gcvK-JS-;%*fFH=ck}b|66xq`B_!mq+qX z=?|2Ex-Z4=+zDSh=+u{f8ofV%`0^hbR?rLG`++!d1D!G}7D)IO<%dQwYEuRtZ5$9# zwM`FCJEi0wkWjJoC#QPfI&2hg>L#xO3IE~{Lfc%!!$*UCE=i=QdT}fat3tq^)1o(Vs@@uPhBf2_OEF<`<+CX5Njb902F#_LSUz=qIPgkoYo3N8Vb9G;oFML9$T)RAm? z$bGu^+G%okSOui}3$^L%u#pznN5ki91Z9D?3_x@jZYgD9|2_CKr1!nE!M_b({y!14 z_z7sq&g@6(cF&`AJvnLdpzoZ8le>d23EIxXNA-Ps4?uUrf$rujH7CP>KC6A)d^-ym z7#TnDUqw%X!h{TNg6(#vdJ1<|KRaxMDVA*A(E5u~wxlR@sZ4LiKZB)*fG4n^B?d87 z3p)7{U?+u46*!yPBYXp0;nB7unh>APtl^w99~-TZVqt*NwaxHU>wX789^h5+V(d;gm=Htt)vtc3RQx+-UNv1Y}`j}oN9MO_7W$SR&gDcQ-R ziw;*mK;`<5Cdgu4xHm0uMzBxs0lP%;;Y!eJUKa=30lhy%%q@8O_U&ZP+kwido-pWu zKpSp{=Bu1-6a=LiRF!#uk?E(?ot-(Q@M2)y%BWnypnxuep-lZ52==|!m8-jLV9qq2 zyGl3`sp^Xr>4P-hYTn@`p?=ldfvDXMUK|agbL2~Djf4p2u7N3MFRurn_R4JCdLJ0Q z#{i8I>lO9VjuUT``cd^qv^6v{!S#TpBs|H5M8xvB096{p%NL-6KTrzK{C@5cQ0?I{ zxyOTjg;LTrYI__CxgyPZb4G81kucm3hQPSm_I>1K#i7}8PDL!l;~bhJ;KY`)-2+1# zs-t17wt=0UKHUB&$9bUMv7>mxB4zCH^OMO{SFo+3&pOj|mWHC7e!cpK0C8=z$$uv? zd3+I;4yjKY$A8VSchh$P;+;?0zlJ#tIq_@{E#XZSrMqflCod&8c?`tp9mcRS5s)X4 z#V%I2N0+z*saiRc*y)Z;`s2xOxiwL+DHaOC8r{x6olT&5=hcl*rn}jo(4SS;qZ80t4jLoY;iTK16Q0D!~JDK|B^gTq;0m{}sx<8$fhVH(T=WNP~xf?zsxhG4xL zES;RXUk^%Tfuf3QEy#axW@nU+Si`jg)DXsY=IWE?P~;EMHe;N@U=GXq`;VWdfz9~f zl31_y54;H}*2q*SgxC^Zdm(BGFVG#vckHb_^rl-jt$F@%*C7h%X42|$OP|x=10bad zef_Q^Iis4(9vANzo^Yj|-za%!+2}+53W_kC1f50}HY4dXsSDhK{76uAl| z?D;Vh%Qw4)i%dcJ*Yi+tvTVrAf`LQ6(SEZ^kOb|0uIHyH$u6a^1VL4QvrT2w zK?&p@tAKlGF|Z||W`GDQlb+3Fg zot7+Kq8;1e^BhK}M1Tjns0e27d>6rF%&xZmKuTBDacR0jbEC&#&iy>?qQcR3y!8RR z;zC@pcCdg^&;zj=P;;Of1f8`(TIzMo>Nuo_E2;2Mdy4aBOw}AXkkZbvQZm5D10uhx zM<(4N`^vlF3zM^pkj@0mLedDMv`R~@c@ViNt)YyJPzHBQ5_IbGhUpBy+foJ4-YcCT zS28sSW^B`5V*!H+=w1mkKeXgVP#Tdeoasj2E`lP^HC_Xs9r||>aS!yh#C0H3Q8KO!1*YlP zAH)TX7u#BUeC|D%5YCs-0!{%TAV z7*H~u<&U4!1>4iDSQTdSE!FM9&?8di5E_d>@X4UUnL+8?qzfOH!40HDd`AYfGCD{f zVkEWyisVS)nIOHB{@WIPtM|h_+M#Fn*9)|zA|>>_{fWaz<<3t2f`_Qmyw z)Txf7p%#MKHHWNMM+w?M@F4$CV$v{l#9jk0F=%C==LhaXX!j%a4^T(fLugk&lTP}+ zK9XAt*aoo@Q;iG}6yoejV@z!(Qlk7j615)#Tu}9Zwnp(A{SMf|zt^C9XPA9UT50*_ z!b}v|icno9SVy5A$#`7#cqy(E1N0m0&=#ey|ABlN(cS-*JLKJzh~>B8^zl5PImXKs z-LGbnFpvRo(gC@mQCP5;-=WYo5ZQqNm_DTK^z8a_*5`FX?-Cz4q6bFz2?8+0ueEl+ zmbX{14KuemSfH4$0dIc;bERv(kg>{dp$k?(XU}?!sypz~<6cjz)1NEAohI|)&$0p% z&G-x=X|zd4965^euJ(DA3cvQ0yl+5kqza_wt}hSt_3QyUpKg3c>O1i9x5r3@&oEm^ zzNy8SM$M}^c*+^;Z*^aT&Kp2~`2RR#Oi9pfI$C>hE`61NPMknASo{P!DbNC2&19qU zV8o6s+&8D}16|xDEMq#%%XMVa1*P$)&e$#kKSl*UWl@+;c=gs+xu_7V{H&sKR zuF6;4uf>S3D-WvOX0xB)e$iF_{jMfF?>Cz8DcoGVnvtaiEk;xk^kq0POdsc*mX2cD zVrbNE07ix#IzhqSRV-^a++FA@10OqH$dDxG0)PeDgElH-rwdvnqu8=ItkyNSYzmy~ z$2r8qI6)pVa01`O(#wr6#_pXijEOktiY4o;x{tM`7UTQU2j$)-@J{pO_36=f*$m>z zZ4m9Tna^`^`4C_@`oPraIzX1&ecT;Rg_mscxXS%OHcB1ziC`P+Vu;@NV9R|&cryj& zyJ1z;=>l1GAqBq2BnB?ULANyCpBQ>ZD?Sc#9eX>1f=NVI>0~eBWN2JCZo)xbK{2@@ z6z)4=WNtix*FTyWywxy#InYB={OKA5mvH1wY?f{h8GsoD_S9POsQs-00z;0J2?pr3 z`ZCIojh^SSQv`Q+j=)qIe&B@dSC;*cRhlw;nBl;Q>hBC z72f_mg2;w^v0{Y+m$F@hxfO61Z+ZcliKz@Q6m*&QaS{O@O|QZcTv>Ia?NpM5rRC5H zXlr3S^KJajQS$%NOfvnDbpR{Gnl|u(%?9ZVyj)lkJKB0HrV2jgMHK1FD24G*N?Wbz z?*cZTywkzxDgv$vV(dZ_mlS}P>GQ0fwb8@smx3I^4 z``1i%0W1VEC)2q@Y81A#_zAQh2pIOLEOd3?Z`#nwB^R;h`~p`zfzfy@k!uVKzA$bn zxK3$bH9Z=rs@?&^sA>aR>=?k;q3@3u*i0@}KrRJWtD+=uB4NUj1%)eAe;{9QcP_ve zMv~6Mk^UG@uQDL`;}5_v2$w6uD|67c%iyJtDFgV$&&GOaC+a37llcvAcB`zyi=Nme z@UNp~hu|=U=Q8M8F{EcSRxZMd7U9Hh04)gb^flJ7oXDCgL$39iT+7OepXtm#m0uUnaumcF&1K!dJ=Fje4%x!Mlumx@FVA#MHIliF770;6X z&@{3D6kWux!4|^~Ios3jsz$+=ye6cU{`k{UVB!Aj`~f zBtgiOEaC)KgNzXu>j-y(458|g-G+h z>Tc9%_6Qs9P!67G=vH2z%Rk#m)Ntr0pQ5%1v?x|w235)8EaHecd_PAeE#r$9tMT$9c|9%A@ee^8k!?UmO8OxH2T&kwj+>at zg5*A4RfRe&fHC|jIRTi`!I+9hO<6QCCr4vDnY`pk!`KkG(lt--PN_ri=>Osh@{jNJ zrvT?uVp-d0FqR_P=VGL_hgRrzI)Z|dTci(2xvk;lx^H3Xefc|8LB>YD#lPJVQ`3#i zq;$L~$|pU6cww^*M85LrX$rB==YPVqcknB_8OM1O-8mkw>AqTh@_BAiEoe7&mkM?9 z3K^Lo#(!dU$AL(UROZIqUg}pdF58W?)?Z+)xzGS`EoIGcMkRiLM*qmRlQ|~jSTj*w7s((@4d_=%bIt05a{pRF_^Gt(`Ts4lu;Dzsjeu$rUWYar z5hXkP?Gb>G{{3!bMzhZp$(nA2}r_EXs z`>HReHtvDGMpL!u$S*4}p#5*H~tdSd91&BdC4)-^vI+ToA!lH)d-Y(H(~iLFNNtjo_NEpySQ zg#3!)Br`69*TY*}JQ`Mf-@o1b08ljAK`0G`&7-y5(MJp)Wf^-l40+pd{SCPPvX0(4 z?n!prFSNHaYsae{8#}5QG-0h3Lmm7zdoMden($ zMC!$~QySeiJtjZH?dx-zRKW{zu*wnU~V^Y<* zDOz28oWdKYh%KYYkTap|#uIPsuB`dO72PC&&XYhXa3+NYuzo zQX5c^*%m}|n@GAr>KRS*j{EBlF?lV#--}1%c!6hMSAKRn4f#4o{TG7wlj`2XSpi!f zQNQ!@F($E{kff*xc%a1$B>W5%MrQ)hfqBqU?YT<;uRp8~%=b2IIW z^Lq6Sv&m?fedk=JRGqf7HTNDq#Jd3xHPL_HJLTeIrE%wE_~?yJ{5krrRY3!DgV%+R zE1==Hq~Smd;5-Gx#hnP3yUG7CkLvpF_K{-7P>v%nUfQKr#n-?lX`5jHocdSt)W5>1 zrJ_7L^J2?_VL#*D!SVLvg<>XnY{LDtWKh;{i<_ZC+U%}VqdJDcw6kDs`4ebu`8{B5 zzg8C?@bZC5Jz3sZdym$splzg+OMUmS+*?i-obzaau&|ZKu(16H!eU1o^fIw!X?xiC zf}QaTibo%O=ScY-xO6964WD-8Z~S1-Xu3X-DN;OoeL^GdwcZkK%&zO&m|aRyYrA!I z)Yy5?r&rBB{XY>_n|Qx$QVGnob6`Fs)J|bA(-(}?C+>-pg09~3xOo0?BgY*nrfE@|@{E=j>0^{GLx*78r5 zZ8#rJ)<(v*YZN%FVGZK5@{!+%do5cI8q6C~itX0p4_galMpY%eu?QgJN zu|&0gtk+3AJ&%k#P;fX;;ftH%PlT)R!_#>1a&qcPNb_VHu0+s)6i-X6B#R1}BQzT` zM+gQ5Mp|NJ-umAjxRjil;?9b$<6KmhN;`Fh?fu=huk6Kb&wT#X(GAmOp#0&C?eUM&9eR>dZ zc=AV{wifuyq)dM3_=7Zd=V1tq5$647J|;JjC%y|O{&0W66a9kO_4Ve-uI;V+{DVr7h1YCM58n-><3CbbEIGkb6WqW#?sw>ZNR z)jmrT)oA0biQ246IiqNo$7Uqmktc938xd1XN+7SO>6lkL1!=`gP~-7SLpE3MlwrQG zTqd*S!7&pyqZmNJ416Zi4q?@dfk*(81gx;v*nA?K=QdOm9hkZ`bUF^RmqYAkEYXO& z2}&A$83sdBBiQInfhPM8j`Ah5^ILgiBUb!_r$=8^bhMvncdM!n%I(zt4pyDWsyU_u zxg50Rv5JKk*B+kK@sE;>4 z;s=P#(M~#Etnw9*ZA$sDmSEcvcP^8rq-mESfaXD6G)cBT9PbN+B(G3>>Zx9gS$FxR z?_t*XN#7n;vPTHB@Iv*9DGQnW^FB3*(+XgptX25#293iXwIe+{vy#+k+xaoUkB4hV zI-C{Bs>@+X<#yWew4ALC@fQlD%c7eH4Z$1Irh8~_#ix3Fnaahwjc%dSHAwVaOyLGd z3*D`aybBSY?F_6wPP(LlubfwB+iM)u3#YmN#~su|SoLze23Ss}m7-I99)ftMkFLg@ zj_d&|MWyeNdOToao~s7v&6JULE+GxfP6Fq!avU3@EBZylv%pTraI3wuaH}t(VXI2{ zNfLmZSO+|DxN}XPctn=R0HO#S`2~e^a%SzFPIF&_mukET$P|dG z?cpsZx%m2~LmM|K7xhtS1(*Or*C3XY1x2G*63=dHjBWyoGPkOe23Es|Au_$Nwq|Gc zT)3S0YHWpoqwJb}n^qv!&{YA>W7bKLFo1`Kz>IT~_Js%`5o&D3_XNVk_6BC4D(UB6LvMHt{x?+z z5Be>pw2yeJw0$XfCO!Lio(|mF<$o_g-Zx@JT-QJVWqSeyY1?hem$nkRCSwwgIsa6% zf^RWxL~K2`yOhicQ6nl;R}7@N$4!+VNX zpwUz)79p{5RJaNN6yh*ufVgKdeRqL=QXuwFq8mEBbV9Gi}@%mJvf9Y`kw{ zT?+8nj>OEWt+~bvK!+gQcai6vwP330S=BS#C!Te>49wR0ub21_k&(?_1P?*R|2G^< zJA$l=>$qQ{Co%6uwd8z|Ns;`qQv@U9p%g?00;D|4<#=N;BEk!`W#Izpc zn@B22|8vD-%6awm545zx3I!-b#*oYV?xFn%tnn(mGoEi(2SLWnCdr=Y+CMmN9sdKu z*B_=;7MK5fr7lx}F`N{&Yqmc|yQn;wqbqK9&M^Y${TSILXj;hJe8GgCCFQccGP=z) z+3N1w%PRRvfS^cPftw;O%?`TZA^+ca?R^>f;W`q7EG4INo^Ksg09KG55wjm)jEVm8 z2dCK1W5!qlxK2pn2aCVc(>6IC`A-$zx` zLJSL4lKu#-UNAK%4~+$c@HF1hgR;6D+DPptTZbDH&K+#aLuX1+a{Vb@9k3*(A}MR4=k+Yp7a zt@f~Ups&L66r~*O;02EoqUQht>QWUL5HqI&Da+C0bQNT-MEajMJjULrK`IkMkG~Ho zr@DREx$W2j*_KU42f_X8>(8_$D4H~hUUeGQGM=51j+J`0#FrcCa6R06|b zi~!?Z{*UpRc5bZ>N||cW2E^$sm>h(h_dk1_dF52G<~BhRn&Kz zK@4o1bgO^9S_ymw3C1Qaz)_!rk-ui{u~!~wIt*K7yxeBYX4z#U?3RTC$> ztA^V0e{-NR{6l6&vjn>M(;N(Ry8EHuhg;Uc(-2OP6|20o+_xb%#*w_&CX$sNdX+JN zFDC;q+8jGC(vb~F2#MZR3zRg5{^N0O@w?D10krf4OV8%vZ>)`&Aj8lWd7EthFf7!^eT*~3~Qdgedz)tnT^AaG2B7rC}%<&<_-Ug+CF$`LcqS$sK-;9(=YT>Ogu zI;rADgz)UQg84$B}`FQp3@ zkIil2atlYHcX!(E>$Z1j!Olx-Nr$;dVE;*LZJEkL6 zvY+D97_BZbNf((w^oc35pp{<#%37K(Gu%cj;Cb^iLm?<|G${!RH~{Q;-&@rygX(fe z41>sqoz5lsbf*dSvs)hXs>IX#_eJ^uGNnwmby#?AB|+Whw8fX^m~&hJv-yU}foC^E za(%?)nj+Z)m4M`mA$!*ahPtuGSYKMl0S(twE|f+0Wm`dg#7YcSoW)AdPwZ7=NfqJg z8_Cnpgwy9GE&<~66YUZp{8MHW(A0zbAZ@ctq0Dtu6^~E82L1z{PtUh2F!sO>hq$7O ziA{ZoxnjBxSao`S;L9@f9z+0WXt?w2ojv@>S?rM+j3sPL2HFs)&iyFf84r@-GuwdQ z9cLxYrnR@QIw11+FW=eq75V43k1NU@QDc$n0`(2KZ`H>j-uW14ij`9mf1d_j&CE(s`jSsS{VS{)mA1eJHYNld{{Q;w&Il?;2C4`6RuWgx3{(r373$ z85(+*JLJ!ZmM*7aK+f4uWh#Ew+5!*IEP+Z18ows^SOjCgSecQgUC|$tp}^$4C7I?R z3c_s)fWcJ(9ZEYi0gXv%4IU$Y!{{e$5Fa(nd7eqDEI0ZRIH?L&D1t_!HQA&+z3<;?4&ClgHdc}mlx37c z;7k}!gNlDSD`%Ve)R0vR))4e%O`&K`pO|&=7)b;F^1~SLPYP`%dIp{^;oTfFr+{J+L1Gj=CdNzh3v{Bx2m(qnB5;J>Zj&CU^4Z$BZ#gK-mhE$lLfX z%|!_}rU|XhTG*KTK`L`Oa#Vp?3FW`h&2%Lo_ATpXa(bYL`+Ia4NLCgkA`5;p1pPn2h%^|s`*fWB-(v&s`t-LWI`_SgN9)%!qy-IZ|^Yzf=> zWR5I-gEFyL8O>_m$UEo;0TvP1;Xjz3FXn)?vFbwceZD!q74YTvk#}Ywf+nJhW{>OK z<*yS&Vl*at`5(OxyqOHwMHRaIBp>tx%9$q8u6ummJ43yLV*I3`=a9(uP?D4BN5H9<%;ZIki$;Oqz zIFMhD%f7tCDg)_6y$^?g-JiAivP;1DejoXq2*OG`sMn+&AL^2J>^zCl=Iq7&OZJl$ zR2tm{Q+%lM1X~C_hbjTjn*li`Yt=}h*ZsGA(WCS>X#{q9pB20Mh+(*j*@BUru6t_0 z3`+tNO$0E_&S=+@LE8OgXg^3UvrlJ{>00%GJOnAZ&@-XH$E;iBQr%f22bIb^7o%y~ z9qg-uatRd=Y6W)ZSEnv*fE*xQS}Mig#p>!#g?$u;ia*~5n*45UCli`-)>zqofZCqa z9dk~16igaGG?I0KP0kDmcc!e%uScM1$n)(m`oIR;&UuF(T9zOL<7MZ)+vSQ0@Ia6Nhp;s#M8yS; zyCo}sj&HWt@#PHEG$8S*?;-wbtJ_G|0YwP66}=E4)INaFO+U>)NauN@aB%&-1~9+} z@Enxqj9=ih0ra=Y3ky^X4KJPw%K?$AU^0CJGH@Zjy;Nh@c8lm3h69E#^@C1E&FEC5 zia#gLm>aGSQ=FIz4BU>dc&1_ zIXClJ*qZ~~a&|&z4#HFX<|3#eUhht)eFxcO$dc;b`2s7pt}h_*^*;8#mZSh~$Sx>8 z>Y&TkzMQsD zF2AiwSYEn!XS$p)8_eqCDG;0w7)q zWl#P?P}-SmQc|b3n=NoT3D0!hyXSewyNwUjYA_voc%!XLmFZI?iCS4$5I#F{hyU#1 z!ynC$sIhgQ?@|GcIz4s2R21ARq{ITC0ulsi2c2=|6P!7O0|n7>IP=xQoZ?t;tQ%xA*;2j8BJ;{N8##NMEKolvY#u1# zf`9GI6raI3<4QSnWB_F-YtjMDeo-72+37pOEQ@>kn2@+74uaFQLSdsKW| zZ|&`L1ZW21M}8^mzY6_4wEq`=n3CLb=rfa@gwg~ds9DH)HV zhiX?&RZ0Lkq~dg!??R{HABmZVcaPTrJj~B(mf7nxmIY^TO_YS3&=neTCh^-J`6db zl5TNv*a)WoahS-?URaPb@Du2)pd^xDYP|2~uI5p$=to`ckFc=lY@$d5qFbL-7~To+&oBy7m~LU8ZjUEW~G z2ac`EmaRo&CoGfn;1a^M8AQWLKzX2fRn=7qoO7!~9TcIHq7HU!OI%XO48}#qWJvor z#s1XQT)*t;Q8*jyVHH>dBG^6>zNsp-62f1_BC7s^`Bc6hij}h(?vU~0WX^v!G-GkO zQJu%~#9z`g!1qV3WOch|7~cTLbwTvITW>0sY&+&$-P#=bGg_1`Owuz#8IaF$bNSq^ z=9!?49vI%U38F0oU?}&WeK7jIHiNEQ?%Z%Nt-b^j@D(Gu!nwiWz;fjx3}7YFg@cdC z9L^4N*%Sd(Ibv^94uHMj2u~|5AG^TRm~Y0Dv~n$2iQ_AKZ%1z^P-j3yr?ZHN0=i9i z2d)ld@+i-)tLzuo_Y4!Z)P~>l<)G368JaUvh25ti6-!jF2_@9+XL4l)Lup~ETYZ+Kr^dV!c|-vcO14~7OaoYpJi(3(-7wUn9aPIq zy7ajZq^p+fw}6WqRcz24P2|87)ODbX)v6rd#ee2p26%rEu3j6rG<5vy`BFkd?261^h7ACi#jR5{huCPkAQe*c`W9K&)G{8KW7`) zq%3cQQUw935B60#sTo~=5a`T&w!is0lW|vI73tUu&^<`$n&23cl{#q46H4+=>}0@L z4WF_^Q!S~uIi2nRa2h^&waiNOS`|oPVclfn@Dx@8OOP!2EKdON@T;tY#0fcCoHLe_Esnp zb8P(s;3P*B4{Ju+ZH-p3l(?9&yy<{LTy8vMYHj^~mWE7yY%JfsGvC^tD7mnaU-q&e z@`FXyWMchP(MZo4TEd$wE5OqA@9I} zj_7PMY7N3H${p;1eqo4-=W_!*d?t^1k za)m{5A#=Gkt^Lf7L9;mc{!Y-{$%`7qU66px6PHw^?H5i@lG{5HZ~DlJE=o=RrC(cd;IHgLj>iO~7WJC#Ng zT~F~FPojaG6%b7`QPS|BJ>W(hqk9~UJ*E@eXZRw1sZvm`dX{&Ok@vtt-2sKAG@(YG z(+p*eAZ-sG0zF*H$(_lmOq}GVPR{j(tr6)IzNMBUJ?Op0*4_96S)n0<8r_d0-pso< zMKPIN#xM1rH5~vpTY2-72HY~a*O)xfbV=a&m=|lP=eH%gpHw#8$onXPOS|$J*b8q+ zH)%+3-?Mdp5R~?!Pn|{{DlQJaHoQCg+s+;2H9zClb|<~a0*5-JO&QWgz6=#Ka!abf zrrK3p_QZu`6zFIH1f}1@!DO85VWx>HeJ0>gOHIapAZQWryI+mhZZd}qK?xLj2Qi1g z2itulT1ZcQxX}fa`H)iKi0SzK>NcYQ4BMtAzJFZaJ7}r+)(3C{V5NsrN`($<8C(2l zmcPNz&~qfoOzS)hI!|z;QItpp+~KkLtR+^!RNsiOUz$i(8^ZlxVd<$wx1rs51pUB3 zq-Pr?5a04}l>Zj;$_+$8mhl4M+j3`+=Fn&Gi?!(d_z!GFk#6sk(1SJHK7r9=Oz@wZ z4Oev>|KNoB2f*Jp^q%xlUqB{`&{n<&@6LxEWp7{(O%x7kA3(gL@;NM_ic-(e1n@^V zm*}Cwb*kgj&yttY2tvc~13TU*nvx8x*uC4sgHo79{TWsu$b2RmoZ<3t`JsF0r)h3)o;QO-(`pl7yrW&iMl7f-UBKYg_l4IkchZ>Hdp@x?o&&YCGDtGH~=0YSkcl2iw zP1*I#{$u0nP!v{?c~vURj|Mh;F{M#a|7Dk5N^soY3J}_;{9z0sv=sl+bpih`OZg87 zT~+yU7{ucjzkq!3_YnLzAw=HH1W1fo+YMe)Spttyoq!|{jlO1RU*-SI1~LkWbhz0T z4V3^UE|J^__;PM#D7n?G1Cc^)j3CreiT!*}j4i>@d}AKl92%3^a5HbzcSmtt)Y4V( zE0Pvz?AdkHVI%Y*buwfaO!75DA|38_4j4RvfxvUHP5>;g#NKEsL6b6F%X@{4X)(UR z$&vqxPpa{!p3;<_XBmqD2A(&YxaIa*svr%&Aq&t!lPv$loQGs^&V@7MKCYEd-T!m4 z;=V{51F!6nCMPBYKYJbGP;uo{kAL^xVS*~!FX?=5C}=X{Mk~6niLb~I59i$Mp7AjL zjRg4`_nrLLxSv&g1~=2r6g=b}^_lB8gYKRjIP}+K1^?NHQv4h305&i>>h>B-7}odS1caC?67Ib zDjfGuAODU2Q*(~(PZIuEt#CeuCcBI8aP_-S=*oU=4?5 zZt_UA^2Sn2#O)<>i+Ceu{tmu&+H5x=XZ3lh)Kb#?bxQ>=iMxM9cIu*dLcDK!!2IkF zeflkOQ=Id6Y-%r9W4A?QXUr#0Pnem0G-OB|$QqbA!qhN4@N-keQ)9Q!ul2>r^{A49 z&8UjYeyW}lzuqsR5vKL?8xvZ>+#JdLghsika#8XpcS!KxOkcQW)5zs4pGReezDl;% z6H#N#Yhyx>oUFg#YYFq8$ZRGIcCI@Xy3!!)pUo#2KYgCrsP9!$=%MmcUb1zv^cws@ zdgB8A2HzxTginoy2%VmgaF*HhMv)@6dmw-QH5GZQ8>BtnC<|V!cxb=ug+#{e{%Gdb zx*Su_CCzyU2J=s^HI(6>c$whD0WXg{+peLMDn6&LLM28r-bm|Cpc8X5J2Sbf`e}8~ z>%P~yvvCJhZT{JbkYoERwc?_RNAs)abGhz%gX2#t@1FIt6)xH6%;nx7@vs^e?Yc~U`3I0}VE mZVnZ%>vL5Q^a#587m;iDD+ literal 0 HcmV?d00001 diff --git a/vendor/github.com/golang/dep/docs/assets/DigbyFlatScene2.svg b/vendor/github.com/golang/dep/docs/assets/DigbyFlatScene2.svg new file mode 100644 index 00000000..06a7fedc --- /dev/null +++ b/vendor/github.com/golang/dep/docs/assets/DigbyFlatScene2.svg @@ -0,0 +1 @@ +BoyerFlatScene2 \ No newline at end of file diff --git a/vendor/github.com/golang/dep/docs/assets/DigbyScene2Flat.png b/vendor/github.com/golang/dep/docs/assets/DigbyScene2Flat.png new file mode 100644 index 0000000000000000000000000000000000000000..1b13ab4243ec46bcb15c9a8b36b9dff556265044 GIT binary patch literal 600027 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%0At`1m=44Eey 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 %^T}^8@9FNX7 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

_&^QYa}}#{>h}nGF$J}W{oHE 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

    ~?wBU%bN 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

    *ZG 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

    yT;Li1J%?l+(kx%3}l_{6)W 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ℨn!%1aB2qitzz!nnAZ6s*Zwoh7Jly zLl2K7}nPm9z*v7!W{3ib{7;N6;kj)U$6KvsD&nbB5 zpJ4orAE|{E!ada<3u@8Q(s-glQ11ZK?n16yg0<%br%n6mOs)t3 zSG-rlQH*LNt*`%C?@JI1Hk%yWXALQN6ZSnPLY|RQsJscUUD_MUCyoEE5>QDKPoZ#NXxn|r^2oh&VpY@~DH9oteA1+-Ze~5=#&dHiD$eGMfQM7|Vm?Si3-R%?@ z-9oW&YDC9U`$+4f%aHZqO`_0=2BA(bLA~V64=yWf0W8$wXl%hdHG=vs@~&mZl3O&Z zi(Els+apQhz`&QL&JT*Y*58IQPN5|!Mpy?DN^j$Pxr^=ul+2c$*g$ZrQrDL}2^}nN zYzgs!*UO>QW3ZV-yL_-XZvkt&V|#z#6Nd~0V}?EkI1&0g-t_OS=Le66YF6tkoo9Mq z)+DGb+SGS0#?r-S5)=aJ=z|97#~5k zo;zYc+OP7z^zz;Zz&?LD_1E@u?mB5)+ZtW85OwX`VIF{7O`E>ZUBQ4v4U?S?izzF- zC+q9hOC>EN7yN!nz_{fATkpzk>2Df-yW9V`o_PQ4UmKb(BG}vC}1kOH>M&gzs9iYfCpRh~+7#3b(MP2Ef8E!}y>U~W| z6WR=vQ$imPmmy;ST}QLC^Y-Y3O^d$Re0ibiIqqnbzeSF9i#eRXO<5iBoyerScene2Flat \ No newline at end of file diff --git a/vendor/github.com/golang/dep/docs/assets/DigbyScene2Shadows.png b/vendor/github.com/golang/dep/docs/assets/DigbyScene2Shadows.png new file mode 100644 index 0000000000000000000000000000000000000000..f15ad9a4cc88310b73c79bcd5f3b75c0f9a9efa9 GIT binary patch literal 703064 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%0A;wcC z?hn3gZ5H@s`t<^NGWV&WjXBMIHt2FLJ%4;ew+fXo0T+-3(8RV9nZ&QdG8n{4DQei2 za^f!HOVH-&Bem+}#qZGp(tr^_R5o7cB2ISEFR21xmXR_eqXbB4Uh;^hzi|1wd@bx2 zXz8&&9@ceuN_Tj1dh2b8^6na|qL>iIRj2`XDb|i5+NnP1 zM)Ir{f%fZ&vFYD#sW0CJE(<%Gvbj}G8yo!4cy#F!2Kx}{4% z1eBDJ?rx;JyFt3X>)G%7&TqaM_CMR1J#Oy%Ue{XZd7SHV=Wr)-lFzyo6oBfBrlM1k z41Iaq`o4&#@_T>>;*u;CzZ?w&w2-`q%NeX`Rk*weVqSr~x`$ z)a!+fKtTK1zumK`HLLwMsE*6*BzXPF3@sn!)|9+4@%0NWOzwga$(L<5dr2%I9ZMJu z9r#zq%PN}h2|mMme}1KHc5e}bh3KmS3FI-;!}cvN4Vg^MMkKHZ_irh$_JBM+t~doI zOoKoPFpfk-*s&0Ok$+}8xIQEjbwIS2d3g>yv>!J`C51(?*?_R|S@-E;+|!3(e$xEqvqATQj^z2xSBO8EGQ zckOo$f-9Ujlmye^X2C>|JT&Mw2n09K!Fg(oZ0an#KNG!PeZO+aPFxwQ34iKvrf_*P;c3j2=j)ivd+1875rLWl9H0rGczN?fqj|GMg8w-RVt`3 zPmE2d30*{JGg%LO^As52MVtQZdN7j}^}-5_MM z$)@qBd{dWzVCPPJfUA&2Y2qP(Q?>*|6*FUmg5ci;N1{a^S6$oV_P(Tn%3&H=8c1WU zQ%_`ie8MNPfEC=ApdB->aDJt%jw!iDslq8{5A^aU%+Gjz8nzX(pXtc-asI4tZcz{C z^HZH~ZL~JIN_ve3lx-}vfHn%CP_FwfBoGW68@i(y==~9~&gmlz!{j0t7z+|X z_VOXje-l!TnIyTU!k7rQGkw59jDwgA6Suvc_Mm@3FqAed7*%*v;v;kN*Dii!rF-*o zjjrsTZb{UeWJKhGud0qZiMqXKKiy}klY@(7`fTIZq*1<|O-no9VTr9*jxzmP`7Fl7 z^!oK|rI8fktj`LZtF=$$Yf@y?fg%t5(_=95q3zciEY_!9IH_zGo=o=etZUlcN1wX& zmhk(o-$e9lG$iK#oC%lp<0nOE zCrmtDfqNdP@2`@)^?f}|@k*RI{5`S`BUaC$)_7c7OI?R1wVF{%vj2V#R(Ix+EKp=n zo(J|0DlGO?kMpCO|Gj!7CoHE^)JA$n`7?PUH@6WjDVoRm%DHQ>Nt;zOx89Nn6@2Uz zp|vaa|EO@$Xf|eSG?;vwu1Kw$&0J=nIMu3HZlJklBr%FOu=aR&X0Zq_!?EAE;6S_>4-5^fjX zXL7Fhnfbme9pY$T&t|-J@oHjNpCC#5G>i%N{7VR*-eXNEYqtfHLPD3Nem2|B{p+YG z;?t(5bI$HvjBGxCXj0Mfi;dvA4h1P7g{bbm#!F10hmCaCHtQWfnR;8{xR_^NHv8!|Oeww!LEd?0UwwRJ zL{~po@*qvSK2~>|Sc#gBpwFgzInzQnS8~Aj?7eq4YH)i{?F51OBt18tp}$H@fH$`z z?kuW}*P9~3eT}KHl#EciW$yn`WJ8J=Q6Lqg{gh(%fzKn4Zsiz%_HX6=^!8ndPA<@( z{^xxYpPqT?(WqczCC_0lENXmNdxWX|@d|v)dCsAgX8h*s!n^-14+*wX-Y# zvgeXx8rEXZRM?D18rg)Q+=|vTr)&yy{Hq*TPldcOhiT-eN;g^a`$mef>{xMcKRb?l zTi057bdK?_fjA=`=m5I6yQ`kSEfY#1FE1`;re}Ju1sh&@e{NZ<$+TsDH!0FmNRL#F z1x|cioZ-aH*K`G=tKigOpD)q@J0i#L{8TL;&4X9G^K&7zK7@+cyJLL*w6xIzXfk3z_ab zbcf_n{8Xl~roenZl^J2ecwKqEl1kgTM<~x2?y#rpjF9@a6{8{re+b2vD&bR9L_FGs z)XJ$lwGwS8A0(M6XL84onNeCrg`2kU;PXGD1uvy&N|7(g9$%w^VZAul`hLB=Ti z7?uC&Q{@jlwCmB0jn1Y>))-{i7*KuxyK)mXwfH^lf~}@%qMHeIsG&V#b#*nL*X2Q^ zl8ARRTxu%O$~hA6R(m zFkYpFV}H<0dYk@BJgmY{S8HL>OvbIu=iifvpi+%4I2~9uVnn+isT6A`mV(Kjh7xd> zc#@9ew0X9{gtAj9NE`N*E<9mGkHhJ*vC&slNuMtUmv7BD|>;A?AXAy(EQa`a4&I?JDO%XXu(j>~V%JIz64k7TmgqeASaT@}$%FcG;NuZ=6pmBA&xf=* zrmZ;^lE3z8lkhRKswYd7Q$OAz)9#Ta+H-pQ6`{yWH<{|>@L+FO{o3C zwlZNE9+r6Sw|8S|B_GQW53O~(?R!);7W>a6jG*Q^qy0;WO_#4M!@-HuW*EyDAb}DL zG3OSb$7Q77=y!mxl%>w%c-Zj@q6poExil^{+`G<&+FH?~qymHvWPSq9nA5j5GxpPG zM9Y;obsnf5%SXUJV`fgh^Pmm-@a~m-QGYxQH{4Rn=`on){989p^1-PI_z+NTz_!wM zG#o@^%#)i0UpK*0MJ(8QrHP{KR`Na;^p%A7rbsy3oF=l%ZPB!`E{q8n8E@T5xo`yb_-V zG6ssn{qB0q$ws$g2CErgZlt|LD5vkM(5{(g2P*xg>WEV}n0O3~**xMfq~~D8Ebb?= zz`#MNp)cYOk$!h))J`f+#d>LUWFbX5l_ks3Y)V-`9aNtvhkhRC#~r`dEH)rj<2Wb0 zxxG&zry9degmr{tDmAL9y7}1BnXhQ|;29$#DvEQT&6W9)!m|xA;iNcpc-98Z+kG|b zYtMQjIXWaF;6`rLzt%nFcwtC27x5Nz-lLp@@;v_RhGW{@#N_+3fWz~c5YV^98G(I5`pUnURQnCLVrWZGs z+`cVO!szHgk)Jjzcy9zc$aKw;EbJr>&HNx)Lca<#X5F-~2`Og$y!!grLqmhx-V!;O zLS!S?P@q`Vg+E>ql^VxCnTmQCMBeW6>of2>-voU`u_feo3(C$+u*$pVKqd*o42F~7H+ zlzX$b>4#8h^q{!W+Hu!bQs+hBJH^3n+0`AJGj9G~m40nuGn*{Scho=g6wOW^SJ#UN zvlS#6@!NJUDNrrolojm|0%S+sV}61cD6s8Y+4GY{6Q(~})U7xeW#B^CMAWQN6+8{4 zkLBsn=*^h3bJ(&@XscJ~?b}ry$7Cj-{F!jkC<)P3`L=Mo(xI<@Zv4%Fl1hn?(|A(7 z3m^C_=ns3H+;qkk$B{x7lYT?CAss_uLA#xukT}BEiW@nXrcN5PC=eI~gkB+3(ezk) zd#bz!ULseadc2mUyI1vhR5&G7HPx%r62~j)#N@BD|0Rb?DVx&KQd6X}4nZpj#ph5G z&n6}&f@mzWY)Lj;8&+In>i157wuIYX`(>RPL^P+jXkEQ|qZ(9O_XFNKI#C|Vu2&Qy z4Oxe!nn4v-z#gO+&&Ph-EnUTfyPs`Z{bSy9;Pm{`)3@lVN3CK+Dc zh~`c3o9^Yll^2x#%0|>H#)=c@k@egKm4&mwg&x>C-`OQ|X;J<;F=~nSO|^(J!Bi|? zmF}?a;-8k<-p5lUuAG#9b8aN?r*IR`2wnKA1+B~HZOR3$Pwsp&umuOcYb!H4b!U=+ zbDtY0s0%IFGG6|T7-mt-e?n2`N8e3aoTQ{g#ajhxTxd^H$@O{lGp5PD zSQCDFlP}7WT3@(#g&q}==5>2;-FD6<V6r_DJs!oE;4lOe(GqE<=$w(p98Gd2_$Pmm-@o~ zwcl4g5BKx+#T2z6Jsr^~745iLIt`3yYRF{+FDrE64Kg}!4yShJS#72$))fEqZe!}- zq?dJH-ZXrNI!i=#&7~JlUR1Sxvn$sUm@nGIl=Oxv5Y%wM2Eb{JH(_#9pS>?{H!Sy; zrH9KVf09Xjn-OJg!|>*Mm4!kd1Ig&vTx@hZZ9+xRWtc?W;~Bi)+!tLD&jX6VtrrO* z`@0oNSO~wqTAm;U5C_P=r5y-R;Mq$`p&9xjo$wx%;@GxQ}{AX^q~Yk{i$8VRizf1YFjPMvISWSG5Nx8_h%kKrzO)tl zBGLuV2_1t;u#2cm_Udv?vE*~NCM5GzSNo#UbKSGT4SUVZNUdxCB$J^d{&$=NsBGid zI%D{nZbd#INE=TPe~L~nyeXa~aUm9z(9Aw_*O3&f28!)#ho0_d&9k(FcA?9>9`HJd$ zZQD3s&6fk(&7p*oM=uR51p;Ht1m<{XT3UW_1PFZHUhJ38dge^V8-`Ip!^~e7?8JR0 zQ2K*hpfj|yw--vk{J&fd&HX*FNbj#x=^Uzd(X;$+FtF-)8W#R*C)^JUM!*P@D=jhT zV}ObX=uP{Be+mYO_hc^4|Jr3vm^l1hq{?>N7VX7{ zj>FU6Nt&(u`DipNP&r%@@DQut+?xG1v!}4Va6WqXZ*BC0j^AoRVXDjb_}<{hI}CCe zXQmc5Q4h}mCDWxofQNa|x_(-SjiSVX{W|AeXuLALWa8WJ z=&xi%f7#S8n26Vf&2~1*X?_MZx1C&6B=pEvN3v&rdL~rAffVpP&n+@?-OG3XGADeB ztF%p1(Q86%aBU(=Xbfzl$QY*VHJSY|hKNP=<_FPoov_Hi6hTb%FNPICbe2i)B;7BI zdMW^nSTOA5aR@!|ydggY+Eb``+z1dAkDoTVVKak?DhD?SRAXvcojgfRPw3|C-lN+h zIVrKL+8P+2P$2CP=G$_Zk4QcSOR5U9^4O?^5>P^D8+ya7bv zqBg8zNASKxlZgg)|KP;3S&9CNi_7_bWBY$F4X4i^3B@{*RmrdsjbaG6F8q@In=cJJjok7WeeyEMoMzn$=3yb>^LD_E}3lXc# ziUZhhUqwQ}0iRimeb+7VUDV#*UJ9ulxLt-ZlL8tf%l9yIl>Kz*!e_@E>f)?LxLwev zzSfl~$VX>RCIQggo)MuiQUgEw+~f4JkEf~~^Aq-=+IP`FN+5OPU{@pQ=rFQrG_J3R zVbPdkHO{D6vbIpg;ki1#bT{1pGmb0_2# zDGx?GeOEZ#%9YayVkna-n|`)v$#F>}`kd?tKDeAEafoG;R!xie7QkqQ#|589khACU zl0DJr{`OgqO253UTUbg=+P+Une){}!KC255!~&P(7U2=!v>CC0uj{rxl>7w0?6-Gn zfi%SM8(#O-%C@r`mgN1nEK;#f)IhN^+3w_w|7m&UdMgscJHyCyA4pMdbz`mM*<*OG z^8U_F^QfpVV{Ie&9E-GJ(Xval`4$Z*+2}42_+7C2kB6dv zg8(H1ydRmD^nJ0RlI(k1SuF!<3~>b+^A7!o7Yb{LR`Rn-igCcZBLRc^$lw7oD=P2_#^!&k1g87|- znSf5xj2vqA_$x1&7r6CrOis*75k{2Rq@Pt{#3p^fU7x7idCmj$52(X!5C`5#FoR!o z(H5d2>rj!5W-=0E{_AIAXG<}_xL_$woZfE>j$kowvFvXBObQfPW?k7AwTK*FI>tu! z&c7{~gwJK#{zumJxA)McL2jGp_qzZ^4o|$d4+FM~r-|ygWMZ7?A9RBVSata}E0JE{ zL)!w7BD-Q%*G_9G@a2I^(_mtvuoU_i{QnbsUB*1w{^4|TR-^?~8;l$TU+u|aCR;Fz z_2bo-KPr0K@jr7k_y;6aegg)^BH(S^?^<`&k9kVS7LnW2)~}GQqi3o9f~Uf#9%7JX z);w!lin&%X=lnslF0`VsZqbrP#pxLl2}!sB2Cu}QL*RfqZEs$#WV437tolC|z`)%h z{`&g9Yv6ii#R#U}|7kvz?1UNzijD9c-n>Z0-eSz`FQozx7m~V1~*~ zWOxEir%GE*)N`kfsdW{H&c1LL@zHg@=G0faq51`)+eta@1+>(6UD8Aq^_p2|9LVwB z!`FP=l~{7`>2Xy8soL9j&kUbd*WH2Wlv39H)a0Of2w7IZxe{6IWXdi=c`mb3-+=FM+wYVBW6j{{A~=O4VF9Q;JSf2l zyd_G`tl+;~K6|@8NJWG+WDGD%2sW&55qdf!KUo_loe0%}DwGS+Y9xhrvF|#=tx+jQ zBho$yu!VI0j9xWzzTza%mT9Ov)}R$wsMan?=q$FGVy(5U)oosCly75uhV&U2CDO?guZH{H-KleWdKQDPTl!A@ zoSO37`TJQnW`H4}ngTl7j;LMrHX#}kA#5y663ri@K+K10&V!j-LaS(J zfc+cNWIMZ9C~4xeGN)gj!@lo}J#Iet6RN2gemk-l#w-fx;A2M*oz2A2PI;?H52S)t zGqnoDd?0u{*#c(WFtH-;B~#&PkiT3(AcTn+$)m0?#Q?oXOQ`D;f9mbGzRte$lE`sj zna7r8d3BtpD9>)5Mn(w3n4u+m37bEzT^|~`XoF}~vlsX!yP|qTvQX z2JcSDdZTxBUIMEYx}h;b39nMXd9n3tVuHjJtv));lLSn5By+%8?MUJP?JU241(TIP zkhN!1dW(4VIyE(xTDxj3jQBj)e`Ndpodpq|WlV)dD0X!~^PR?{$Jt=?qK@h0{<7N`ynWs6T z#A5O{<_u=+Q}hdtTM^>iEoJ&3faSj9<7PE-8$3WXrsrA(_bj#*^oabRLlv`!E3hIQ zCVplH_y2>;RDbfbINP=exWw=7P4?1d;iBPfIBr(?fyL2)Rf#-5^Az4Ws;m3uXFuxi z4=>m#!dBnVz|OwY3gQN@DaC@qKvAzR+(<|;fX*Cte`!dnq_rK^{B_z?_CNzH*UWO= zGupLF&r`M*i`M>61F#WAr4FC$KNnqaBm?#m$o%~Ei!v*J(Ps8H-opbA7jLEDbh_m_ z6~smMvV5kUc&svm6=P|p(yxEnrY3b+6A0>}zFU3Y@qvp4Wp0hh_P~Dsbh26AeAS)x z0K4;vW{)Dt+hy@#^rutKU_HZ`DifYEQ=*)YejmQn%D{_lq5?eBpzGS*Yg{^$o)h-x zU+OB0lEi1|lFWPLYJ3IPtDM4OTlhTEX5IVO+x`!!CU^Cqfu2%_I6#^Qsh__HIV!bs zVE6^NiOXpw&2;3j56}J#kgALL`hAuhVrU1c7P*N*j+tTj{2kfC>q>%L#AhHe(2Wx`XAit!zU*=)yCqKQ30;fZ{%)nmoSl{HkM@Buh0Z zZ1|XUo4pPfM>1_4SpVrkEs21I$g4g?J1Q#a$W)it>Qke}1NAz2ipV;&X0X{1s5YBhTpm5`f$l5kEHqp^KF*5SP@+@`zFLKcq6iNolTt&YPTy zN(}$@hPFFB1DssHzsG<7^@|6eXABk5+tRs{?*T#L`rd@;mCqD<3~w{>=Km|xFn}(i zEfNn5Ko$}C=i9*Z#3F_fWEC{K`i6j^Fz|9$6d$0#MvHAz;pNR97h$!0b(=wm%8qgO z`+F|m9#Y=hR?%N~+CL!)pK?lFZ?2DB?+Ro8?vhBmy(f6)`&1k~BI!**APtSI7(&M3 zrOXgeyb#Bfya%`h@VSgVfio9#B_bToHj>=~7$r`$4q*b?CNlLG1g#&w$#gV$Q4JT2 zthRzPi5oI)>S&?Ff+!CEq0Z^g(BPngiS&;Bly6^T1_}33?fP(CPdb$2ar(*gd4t<= zds`s+7!m{}dL5waK>TCKp0|EDasNROCj9&H=qp%@0wP*zI;_TkK()NDoF3Go_6eyQ4^{x{I@IzcMe&|Tuph!9zBAD|jG+(|F zNOvAYsga~f1?XF}-Xq7TBk)xdTA0;^v)kv-VhbJ~@>PrIY8#YXyGWhfnkM_ysj+h! z1RM1#Ay~m5P?51&U}KQ3kzp$qZ^+=0FR}hoS@ zwnI-&#^kyVI;9nW_`tlob>*y$zk@9AnEELOhQ&2pc}&iB_c@sa1uc8ng5SXhGoC4D zPre`!i_3?DtIbq`YweXqSt4$K`DZ*hE)L7xj*lHyKPM+A&CSi<`ia^oQKPVeV5`H) zINPe@dmjwFMt3ZJezo9w04OR6;>Zj{+oao{Eo?FjPgVj9RJ8eNVtwM zkw1T>jNxk#-y+^EXsC7dN_j-GrK=fhHs>g3$F6@7&tZU$rygN|Z|5;6DlxAmgzcS) zM6dgWs?OlPG$dj4rAHvxd?@S|<^VE@P#SVFJ2G|J7qz;q8fQi9se}dUeF=7p4bw(u zG;dI{$#n|0hL1$PrpXrft1JD{Z_61;b0`w_9TVyf8XVZiFWC6<50L_S6mEqQc*Ta~ zu-GIzP;}7X1QSXYfTKKBRxiA|i5UTHNY|iOlVY}fE=`)o8T{sYG0?~-CW_P+5F@tb z{G*n(6P2cC+fvVQw)+Lfx_Iy~QOxOtz%UW#4&sl%@L!0zo8472w`m9%x+?x6N1)&G zo_<9lA%SzZ5@hjCs3zTDjNh1TRO84BIMmKc^#Gg^3j8w3PY$P%7CM9AJK7@5PyEz7 z?c{YT_G_4!fD7TXBrWk1zr2V`hjr_5$n?4t81^?e@vi@kOMCwt6LWUf+6e$rHy~Y~ zf&*;)v7}|0r$p_%l7V$8QLf7!#JJaY$(skS1z}X@e3Hw?REBhrIF-{6BdQPF#8tqO zxhVKC{;5<|E{en7oU1N!T>mii@Il#co7DYo@v6g7uEyD!RsnYqKc0}NCo(K4unh~W z?88F2w)4g}bTQ`0W`m321&%ff2xwuVTqkr6jE5D}MQgpw-Qoy;H>3RvICdMu=^H?C zFaB5)iPxh8@dSt*)5w%#LRiIapd|A%QO+A`dF$#~EkSOt#?xgu$VLL94eR5+3Dc6` zKmG%R4hO+4z3K>MgNFYIAtb}>sON#c`CWfKQUIMf6TCzZs-tf-b=A1f+A4PjeTXvQ zyc|lLLU0a!Gx=*Gy$so){}F@GA)ESFiSHQFft7&~64g zCZNJ53nBmP>~!7|xS7K7)sUz4dH40jCUEVDxp1{3a==i-Tc8n&jDUSZxM1JSl>UwfxxW;|4~Zekp{0mczt1R zcjnED?2(u{VzW1KzlH)O8U5$+79Wmb@%)TV@N7UjW7+?M0+w3cGaaiW(2AZ*_8)9S zDv?CNcMZ8oScRl5heKfl1(=p4X!Ff%A}!zyzgtqExKgTNyH=?B{(u@+(?Z>&;Id;L@tod_=~Dr(DUYxbjH zS?b*I&{>K^S`5^H2tZ<7d+Yy1f!GkfejPav*|&z-n8Bq_t>8e)Tj08rY?jVM7-LSq z{SM`T$wG-;UGB!mONA1|Sq)G!0$x#N15vWAN|4*AV>+mfl%-Y$=M;hoHp5Q>R%z4c zg2oB$?c%ujwn%U@hoEuHZZ8EXO(`770GJ!TUZomFUn1E6lku-G$U_E(4l?h7{X28H zBk)mD0ms{yTwOdME>v>nw<`+>VZ@o48QYuNT44=vDGhykA@BcmCz7|G(PEDZg0^Og zYR%=i@>W0X|IKVW8?}=dIKA{kU)-E$)AO%z_Ek7bij_ad{a=SlolH07iL#wevk24$ z4j4U+I7HI138g#J3l2*q78K>g(Ut>|%#I>$dR)~!c}mBxoW$O`miz5?%a81=(5*Gd zVqt8ZEr(QOxYKm^{|$TUn227njL{S`1(dUB#i}MolbS#IRq%_bYY=7>a&X}&R5oOo zEnh_;a$tulD1at{uwYnTN2w3sen)FP54)MBf7T9~k|`TLF34 z-)qkukNOKk`8A6=zuY#QTAa&G4GRm(>1m*B(f{7i`k*?T_RRzA`$Z=AamGZ(@Rh_< z#6%Tm#L5G5)%w4yvSN9rwo(Pg?n{~J)%@kg4*I5n!>+L(oVZ(wD}-VIPR3n^0Re zCx)jJhbiGGU_+_ z+5QLME*tMflW53j63)MBl>LDSheGWLphoryAO7EMnWDeTweq_Iz)k>bbjI0$1rJcX zYP;Hz5<#jQMgC_JJY2N5BgLK&072B5<8VQ8Q{#LfZeUE5u!&P05F5#EEnz?^u{WEH zKOF(~&cD}+S{_6$0{16=-o&uXpHEa&afVrThyNG1tKS-S*kNCD!>K7#je^9dteoi? zBBKJeLH*MAxxo8(HNTUKDfz5o7I|!Z+c4u14AOr~qd~v)%xg)oy*BIeKu|n)i>qz_ z3P85t4v%KlYQ*eJk;D%!))TuFSW)5C-H<2{3<5va+6_tI-4;toj`&5I8TnVg+F1#k zn*eW*hp}_yJvfyTOza@Bn-H0a(E20BmE4!uFIx5Fn43#^QOX{s{h8jI1hjgY4 z1?I{GKM2xadxyo$V4_4TBT%&;cX$f_*Z7GTP$&1r|1O=ew;=N}{SGk+Kyq&sIRGci zD?j{shbdt6XzBlfDSzVwFJl%f3KJBpK@6A? zP6~R1_a>MZS$6F}$ixI~b?^A|GG`}Wwlc+;94e1%&&>mT{VK{ZC2m}V72|KuNl$kl zeJv0uA74cBYki;C&avT01F%!A+HcrE-~@(iyV!R+SOoM7=_X*4!1}h1))UN2A5UC_ zjxqkXULe$QwX0H9qt|xZuoqXRAyL*BLBALLfw>z*9CICgIrQf)XhAf;pcJW&i;fN; zhE6}QP^IWOlitSVhsqHN2nd{1W;elsxEnzb1@>SvOEO`Bo~lYl4W%NvUQ0lQ4vZiJ z7(Lok+H>mpAEPhbSbD(U;N$$ry7f{-@TRwxP($L0UzBBc`s z{*x!|brdJBkFom-%V)Ydcm?b zt=H*8=@5>g%;k3~VPT1Gw(Nx8qbC1gqWsu?4V8Xg9cT{j^F8=?sxWwD<| z_IX|%v?E+x&<{>aCu%O{O1W2GAD_Zn#fiV|VOC;5CXY}t`>dZQVH$~#DmMz^>udL$ zuevSv$7it27yAVoE6hZ7ZB5T5L3mtFUehYz4hR^Y-X4!aO8VwfI*2({QqSPeCihO4 zC(&pWkn+SgbrT&I_(6b2axZVlnAP$z_l64udAH=U6IqzM#*DK$Zy%4{9#G+EQPXW6 zTw&SXFEr-Q+2wSHf~H;!@;*xpVMw7}iBbVQ)mftC#4OP8H$%MF5zUOOIG7S_h-)!JNzLhP=T+DIjRR%H zJdvPRh+2FQ7M`jl>DfPj+sVPZ>Mw?j0!f7-H~{|$;OT&t`hel_|A&8T?}TY@W95p)yuz zl?b3bjl8^W8O%ze3fq0x6rajdIgD^0dPs{|uYceN=V_nBLc>j@7b_D37q_Z<;W z>D-iO*FMev<@DyilcHQxDp6`a?cPf7!Vx>!NN#|vyv7+(L^H>>lS*q$YM-`{VMkHw zNcP>mn)-FdPY@A_FtiVv6jBdozVAvCJl*+%x6zOO?YnHqfM&v)4<&LrPV2a{8K$H& zEJu|KCWDuXN;^v%79=H9w@tN4z#oNMgc%x)i7if!7aB|u%%E(7#P$WAHgHo%l<*1EHFor*iV7eBVDyLdLnRpX9K+c zHY@0`wP{Uw?`5REo?&r+P}^P?&r#mX{xc#&kS+Tn9Nkm5 zvGZW|3V{8zb==Dudcn&PUG`onFG{*Q$Ko89(-LE4JB>(>2TZqew{pcDr`F#rW==!n z*$i53R+qx^ve&_*6kI4x`sR6DSs$g?`AafC z^Ouhonhonm?WB~j?8i%dc{5Huey}S8Hm(0V=-ja-hP;DTFga1LNGvC^ePb+^{GrUV zc|80GE>P`{bCt})<3?GV|I2=NNpE z+5P^Bsrde7u%{(1NjEW-3Qclmn&|8khwo`ZG9WR8Cj*>@%v4mGLYvGa!#MVYz`zG~ zjQm$v`?ui!C%DW%e(Ek{B1a>qV_;p&g+O790{sZWGsd9nSFxd70C9A2&1F-PUtK`bluf~>9W^z@{yT}pmGgQC{aaB|W_gTORd8U#M z`U+9=REvxq%CB440R4SoM97$3-!8z$#PjyUFNSLdM#nd^f^TYdxs)X^5!-M-qKIR* zcbdFLpR?OVMm`x3CCQY0=$K=>688*cN(0`cuke(?=W}&Z{)Hs}y2_bk-cdZ`tF^KHFEv$|tChLG!}{qed2j zbz<>v#U_A+*-xLRH+=S`dmjbLm_6|6QREG~x#SS(v#lPoMZ&6jU!OZQkvcA&5}u6P zZ)vBO^7z}TfuYLO@h9GzN0$4oPmT9X*_R%77l9d5lvE*2@ZB>hf{@=rn3CVh=j*gb z9j@YOB5UMB)hHOlTd-+ZC5PIaEo={WURrv8$Hrc{?dV?Bx*)n7Y2T@ zVxmg6l0!=Mx86~y3D6(0JxImY6)E~3;KAmA&jwFh>i4(2WosRKIObL@&k7R$_Jh@8 z_EED!XfmWo(rn?gR8pj zmYU1ep7WfffED8Eb^~tkXNr4?f^m&!^aZl^?h7X@y^l_0quoG*DkbSW5;PdH!*N&UPmN_=k1-c--TLj&;3Zy3Yk-0URip8 z9Hx=%aTI*_e0<@oyo1=Qb(?wF31)MW4PZiy)9Y1aoYo)&N@v`z41OKq5v|9n5BB$3 zD%P&XPWN#RI%-}DRP+03+StUXy<2IX#^OlSly~Ee@y9`Q8Imy2ex|itDiB(Fsnl}$ z(Dj1N>0@%_fx_kXu-FesLdBfLQLG_sU4egUF}Z;B9eJ>CQdbK<8*;iy!` zRxZZDO}o9;DIH4H)1wa0p;#0Hf5jT>#%#7pMYxfuH>i-WvCqON?pLNPUxV1Jr*}#r z+H(#uOm4p|qI7$!SBZt%l*thF%+7j}KVFfn(g7=|V0%|#gFBfW`NPX4uP4ks;ypvI zSIUL~L7V}Zb2!-Xh47dG9iXz@K=WgWiBI}-0@Ee=uka zwR^hm$p}k#6S<*jyj?ubbw7n3-PXYCa!DZ~I}{(|ypqW4sGZTps2mcN$rc-@U{d*K zV(vgH7W67O15s_AUD0pOjvaL?B`^0V7sn6T*qBR02Gi{~AMbnt*S^fMpnuY@5;YNU z8%h>xXt~GG&&2EQ%L4DY9?R<0>S@3IaS;sRTAm$;X_g7qbt+Ta4$~J(B)%iZ56HJK zuXi>=GA8M$lAClY=MR72$Y1{}rfi(??&V`AaAVVMH*Y}9ilOAG{^O(?E!*0@Y>%}v z#an#}(T~zBT|LC%p1Io7alh<&3Z7o#`@%^+J;LBf+xWq@76jqSYU^&-q>A+_p1rr8`TUjo zNpEHoo8fV4vP-V%sD7W7np*jiYw2q9-kbNg;6Y)_8AEt7Gw8hLz2thL_A{Dez@b8_ zKsOS8R>`21&^x3c<3&)p?Wkj8;qEtgPjqdr@f*SZp`*APbmQ)A1*z`r@7cniCgREs4ebLZ6rYR@Y zk;n{YI5VxpRkQ>JR7hNkZXT-dh1kKuzs>XCTP=3dQc{$ZN^Qqxh{)@WV`ChlVOT#T znFxvMf+L5HB-azI%o`nF!cioKR!|Ef{L;kzR!b4`=F_6TIBQoH>HLYG{ym<-&qngM z9GUz9Coe$*7ZkJbQR*Bo9I?e=PFno-t}b<#&%iBJooE$8y%oXvo=>29@9qxKK{%|7 zn)Kna5#vR^Z=Am_#vh= z;C<$2^Vz}#_c-Gw!Qc)YL?ohquUJT@%N<;Z@C!e{eMVx$d#rX8e002d^D0xMOM7p` z!NEyR44#akfgEYJ`9**91o zg+XWB?QQVH>DG*^ewZ+T?_z9pFv3hWPN`sVesQrf`6I6wdx+!^;;P_XupnnEId70=2@ykEE| zE+{fiadYRC7NPEar?zHnAm7(0{;VtTBw5#G+HuEC?w}g7vqRXs>1dhq?DGq{#HoGK z*a5sqlJtu}UWOgSHq4?RTBMtR07R>WCO>5~k0s-3sV(>ETKBqr<^eA)$cMec=fT zIBMF?ynk7ng%2Cp>pt~mS8Lf>cks=32ck+?6n4JORQ(#u5pGMu(N2ENt+hgn?ao5~ zRs_D5eB7PpXuQ0&^SKpI~ha17kytf;6M{a)DQCvW>Cyj{)NmzWV_yTR#@U*Vx4 zcAn|&*o>c@Q6{CY0^i)YZy_zdT3YjpYnnF)RE(+#1JlFC0}QkGS#8N~zX<>b==8pO zwVaAaqaECLOIKh9k+lbM$>)Y-W}~XiH~v?s%%YYz|>B{>V($-iW zlzOLBPP;Ec>||`sT#iF+8u5~?@wS_bck9cRYoqTqb@R?Jd@4fH6nZt}a zj^o*D|MkVcumray_Mh}7*3hHzaDA(nPvYc0bPZ87;l<+wb@G$CP9Q8pi&2B6kuP52 zK6iKy<1oK1g*5-cnbNMIpjz7>{(2$YYz+Io)L>q>StG)?VkM^N%C*h$oP|&ktYGdn z;>`WEDw+fNDae5;3=U=(nvhZWIc6KL-@=`kqr-0>@6!8vPv$X6r6wz@-bNKeNZ67F6wc(j~67+nuR$~z3MuP_#1zJD{FW3!O;T2&tIJ8 ziozXzb>7=e`}v-pf}s43(|`nvn)-~KVwkK|1Tix51^Cr|`9tL?`JZ*}jl??{G-4%j zp~{Il3{Wym-cJnEoZYvnyphDc@;b@B7zY;(K1KYU?&x$sg<;JqlfEn*B|N}vH~vu= z%eFNtl)YEL{O()YUykNgQ>*~_gJ^%~9di~KaX8}E%=CUN#icUESN>u9PK!#U&EbQ0 z_W4`sP`Y&aw~a>AYqOzOl_D9!dVCj)O;ZAvKYdY}?Fo#nXB2E!HDbQ?7T>&Gg>y&e z?v$$l85OcH&nQf}SP8B=nY!CIqXAng5{9qk$J}Bh0Y;nuRb>ZJXQTGXO=lHZfCdg~ zdgkgk>*UdwNUB`jb_^B7kaa6^pbA9E&=i}CbUZ=Jof1kJejk?^o$Y(=$?tr}y;gM_#^rFq4|b1vu;(dhO`KbsNDIpPrPD_hZhUvuh4di+KZRda7 z)XBc8Te7)X?RGmKE|jqWF%6DU*^BQqh?IeEN1Y<0`-huK*RMgC<<`jLO>n$$PER7q z>Ct1sx@HG$CVOIuxtC90S2w$4_n&*pv=2RPjTZQKuAe#=u2IZT1T@Qa1gOk9w4JDE zZO5E`td|X5PI^&1KjiOIs#oj%$%s$v*PS^Y=a!AELJmL%W((X)B&Avud56nbOgbbZ zw3_^?*hEJuY7QPT>YOOlOb+=2=4AP}#MBsgtC!r23LweSNjr$gP{uTa3DU|+H1l0L zu7#I)@pR?M>1k=voC4ORqym3{(S(n?)+AB{c{{XjwBVNVUP|OWo-znz*_dqeHXKFf zh)uDXW8i*gR8EypuJ9M9ElReBtRb|Iib8WrGpAu=veqPs2UXcs_~PZmX`jOZBBJ(V zOt)E&e;}g6!Jm&{jaYz^xp~~1LU)s1gmM-gf5~E%{JX7wzrON1up8YCt$}`^-+`_` zlVR(FYNB6QM9f}!dF~J6KbU`L-X#fcU-Kc{Gj0Gu4ftRy97gOOw5%s{KK%f!p5C9tq(ZV_3C>FAKLj$v|j|jFBZ0y=Q#_ z9lJZlz~=xodYe@Ek^C%G+XH`zq{mM=_{KC*;WH?a#DC5$j+Wg`@DRyO3DJwgCCGv& z>f8Awgcf^4UrR*5SC#;n%X*w^WT|$PoVHy2us(WB=d(@y0ZQ9v^hAL0bkZr>6pvuX zXmsG-VdqBH3&|tof9+3}92^H95j1@$ z=JbYUX}PM)rui|iAa0OKzBItr7#~bKl=z8GaM;8JYD9VYdBxvVs1;8sSP{+QRDoE< z5+EZEx@!Zo=24_Yv^6#EUXQTaAlu#CI%PaG%-YKS?T;+!aL2xltgWdugI7RBxj0+D z!=KPE@6DYqHfB%ldCG`;!^J`28cHUaFDV!GCgb;Q&PV&DhPx~S6hiSJqLDs+8Qg5z zh|Gvo*)1BVsdcoo%YDaIs))_`nc&sU98`ZwLP~(9;l_HCKVR-)^K0w#0Th7L`wT9o z!wu$}*~_oY6Vhv2`ew|EmduW}%}WudN3TCLFNJi@@i{tr8LmI!(NkLobbk2$5!-F- z{YmD{Eh^h~w(p+|!+Xmevzp4l!EOKL6B$J`c?#;Jw@5O#CjOA3yC%jXiSM+rAT!Zoyyv#J7=Xc?9L&Uxiu4BHh3AGiR>3qnU-a zCPBf(;q15YN~O)$d>N(H#)6x-4c3o%pOjv6Hp_R5RRrfA&C@BTLigXpBL#;i1?36< z_}he@AbxR*Bnon9dX{XgJoUNlWwF!0BY)Rf>bLJPVT8UeV2YEb=3vr7r%M^nuR}?* z%xiyq1tOQ4hX-9?@l9Of$qV-2MD?SoYI{1rerm^o4%|YuV6|Q1FJH_3fAB+j`?7(* z-SdGsX9LtC_O26GQ!}%ay5F=W9OQb>IfnPFZ%eB$!|5-K-?NCcX%8McD7)Hym8WH3 zVeY$)&h^pWEu&)P|f z*F^9gF75#gw{3~|JX+<=0+76?D9STmwkP!$FiBQf zM^q>dj;WL;1HmN%ykAB4-ugDr1gw)kQc{}paW`(4O?HHVFrk^Kzf}e~A-+wR{F-$V z7E6bEU#!k@kk{+u;H6jTsSi}Y^Bj_i1w?;dmoxow9_A)uDzmH~uPct)V#=wZ~* z_FO^Hk70WEMYau2)F1#7zXL=AqxDLCbHgF0NJ%?X*=zg9p_ZcML=R9q!op()x~AR^ zO`tY&hlao}bw$9x{Mp44LrP30VWLkBW#k^D59kp#29Or*^wwuWcwWAt5wZ9?{wb>Q zCH9Sm4fb7@3>H)z7Da4dkb9qkE$UY;d@K5n$*GTzuNuo*5j#DOknFZ{^h)}DA2tMz zMbCAoR+AQ~6BRC2EuR50zQi8=N$|{s7y}JGEiPru_LP!C0J(7YIu~qRr4ov1%Y!l7 zu@JA27Y9wvOd4JZ598&jC6C^ezAq8Mi2xUU;$Mzd@1ZoT z%D23T)H&XE02IGWZY!6*w8f=QMm8b6C>kCLKUgz#sx2ug$sxXiQ=1Zw>9-mLp(zD| zC~LVUnsrQXh0(ELF%!fjvbKx^RlX{dYV%(z4Kk7b&|mn6puVlHzP>*k!|rqbckXq3 z)CNY!)9^Hdllom3T=ml;D)S|Da1)!<&g2A4uxsCoEy~cr3{a8Tj+-4U@m-k2F%{0! z)h0dV&vZexN>z{6b@6b@cpc`VpF0tN3EK;j9h_aCNxx%_4Gfn0iH*6sjnuK}+RD*Wb8~U=7t>zX zpj3^^A$9= zM4wIsAoBv~cLE4p41PD09+1;qDt$68^hf4vuwfnq$@ve7dpxpHm2z>#uhUba zJT6%*b%?cL%n$qt+*|VS!6!gpbOqmiCF(qy#mvzX^+WyJD4M7MTwOD93MTY)9gbXf zLb!5;YiFtKIyu4dcKZoE--!3lHnUZk-T9(+`dLV^5)(nR~GMD+FUs54% zsU`GuJ^v(%g3wK5OYw7jB1oGQRmn<_yHuUNWw3t&3Q#Ux0)gpC64;2r)EFkJ%mDWV zObj3dWa)z`kqkJ5ZMJ5-O&%i>Jf^AcBs4Vez7wP8<>gT(D_lTEe7#zjP~~hH&tI9ssgTt=#!qeIrg-&_;>EgbekkIvr@8-bbJGZ}r?+Gveh7 z7ak6J-4D85oO{9qRKF$0XXQ%UX{m^fbXvMF{!S(^=}%LW!5H(YcMB$s)e=Fjmx(q! z_6+_Z0{UN{$FHKN6I`423y-c+FK}E#1MzvWrk8_P2U?=~nwmTYb)`8t;`$=svFnPg zPs&HbVq(M<6%WjGcw0>k5?hQ=(*~)GFOU1y9MBne)WA@Z)3kAw67Zy{`P+fdvb}qV z0Nbuhb*OORT{F@1e!t;GZVNKh6>Let|IU2HAHXkdf2YEb2FRkJb82>%$^-Tmg?c8! zIY9wy{ri!Hr$Bzl90xLhM${KhcWl2pDOos8ojY9$wheSn+_}3*J|&iTw?!TJ zIA|J}=#$PRe{sBPn`Y65`a$Mh`GxkSE1=N82r4<%Ki>U$BJoX~J@SB1kmneBYhZ>X zQh*BHu4R61>f+8x^O8!9xw=Q+z%S5(i!{?HW%g~(~Njwttn9y zhsZ*AtyMm_h-(RHjXvB1K(%uvkE@pJ5no!R&9`Mx>_{HTM35I`Vw&*s@3;HKU&4_C z!u8aJJXM`+!t4}Y^C85g^W1wJ{UABN3Xhf0>;&NopcnEV+bB*cf7SR| zl*G;17F5nPBdMc`PMROH9!kS%*#nIdV_LS&JX-3bbYaVJFfo)xbp&g(?AU{bto2ii z`&iA20Tt;ZHRh%Qc)wE-1z$Ka?r#T1P0;*^)@B&K21$e~&KsfEt+8Gwf5O`iz| zyfMN+X43tA`^0bb=*G@BN=kts?93BT6bh{*ZWQ4#s0t_w7O*7-wlBKOhp z>F8_+>^1Al&_$+~9kFgbro|f7U;0+Zfdbl)QelAtBYqyW3oj5w?+qF{nLj(*;Z}R7 z_gcw#YTGz}JaGkhRH8$fwg4pDxWfV_MHYw4Qp|4`^LGPrv*v)xbU*$P{r07-fkgm- zGR+RYW4nyGre`K{uHF6>SN@e4pBWz7D1zfmb(smWsu{CYLkf$}V~9dx59lb!2EPPS zhL!U3>)K>x^E?N@2P@KrrRdo3I$zaHl9HXCUUYiw!!8`>X2O2no$r(djIpJKy#(dl zN8@m5#0Wz9`qny@jsbwap z6pg4qWGMoz3WUi7;8@A0mMBo^GSK`&VZeMKg7a~MPIFB2ObQ@Mg<`mHliKRFc<(}0 zIF=gP%P>I!z&;c!=Oc9JIOW_v0ptrf5O!8RpbP2IBAvK}=k|znif`m60OP!uV<|Kb z82L_*+M%n`U+IK{(N4ADZY>Ot3-_4cW5;`;{Fqa9)vyKw)6S!hZP2tMAvHZ%Wuk5r z?#&)rygc)w(eH(H3x{-`x+tXsbeRJ?V!P*0>=T6QA_AiSfs!ZO zqnP^eK$|jhdYbj>vlVs_nN@cNO$kkzw z_@^BlbcrhbzWlm*_csQ4UoQZQ+G3Pp?5ipmx;b{8!0S(4hiVBv9J<$M9nq``vd#Uf{5I(4 z;%9Wf=hSR4-xISw09xGKk%)Zl&O^9uH$JX~b23QWH}RsuQS>NFOTVini#3_aj00sr zpGf@1?L9xoK=;C!7g*mOmWVvan2DMg0h-3@@$WWuLiT&xpF6Ksn=0{`lJ}_uILM*i zHuWv@E(v-%>@4VH2p_eo>VN?q09>z{t}R4B4$D=YY)h$fJQ}-KboI48IhF=v^>$5x zk!o{24E;Cj-b#bIYQy5`r;gTE%P?J9afm>Z4orN8pz9dskW-GbtS4ssNl3t1#rS^Y zTi|QG{V9Tsi7E6MI7b|7(i(pJY~LN^8NQj^!b0c?J!-JQJ*usZngP!NNRqaaj~uP6 zbmg|dB@PGF)Px+Yd)Zaqv4)tp9;0#_!l(cc@AH7ej=2`dkDva{TVVi;jEF&K12^uL z0MP$T6(3}G9Db)73~-A1m8Fd3lVDt^8$3kv4P|h^S}_Tc2`%Nog2QBF(utrM6gByN zGF<1fP+KaTr`F%#a&^b8+S*bOr^?GFLKP8Hgu0900q#|lk!3W3>rOx>*nP(Y4FzJ$ z+2uOt{xfDv<#mr$ect`&vvL#5R1Fls_6?bF0@N(jHWwd6B2}V1V-uY9ujk+4llMV& zDIOVnZ^r7>Z;n_i<_fASi~pfy7~x^;bRlL0PxjMh1(a}vk^MdL0=GI&hRdp|s&ZlK zNOZQz0`^uImdSfGgVsiM_q?vDm8zQ*!>6Z)WQwBmgEjqecEBdZO|-(ZZbEK57!Sbpq-T+xD`M;L3h-|U>UW4YH2Zw zR2So*iX0KC0O|P-9mNtq3%LSB1^h1ORsj}(CY(MhnSN>A0_R~Y^8nCq%ODN&~X7JW4KU& z6KO|)SC0j{s#A`(C{Ydz+GMoIaUjpaZ&{N7ID3^AK#>Mc#NJtbBiy2uJ`s|8cRn*oTmCYdc1W z!!AW!&*w7&xXg}4p{cn8IqOX0+eoOlU$UbC!@r|=$A)G9uCmwI^3f6Rm6wu0mBu%V zN3Zd3h;Q4<@c_iqw6@Bz`Ac|Pz@Py}dQ|hRDLq{94{pD^5J5+4u#NQCp*e$)Xmg_b z9pGdyTrjIy={1>qU|bZ$;Kmc<-xT74JrX7DUPMasORAo?oM=T;$_KzeX+|0I0{*+# zbp<@CKOUc~^r|#{0woL}L8MfDc!|?em7HbNzAexUPH@JcLIE&^ZY46P55@(j^6ypM zE7LIjNZ^VJW6$rr4tbue7f)2V*Rt_|GhDlMUKrfTPqZYoJF0qfx$~$8B+?JA{G@G} zO!*zy-8`(xiMW!;baXh#D4R{(d=48w(W>37FlJz)JN2zDh6_Dd#p@J#?;o$4$(EtI z=#4Lj0lHPbLi%IALXMW1C>xM8kz?;#U-9L4l%nH*MO_Gxdf`|92akrD43s47Smokz zxW#J~h;9%Gz(O(E%^OZ5*djnt@&BkdAgU1i58q?;8b~+2l)D}2ZLbMUU}a&J0swJ?=pFnDH<7AmGqTdjrw>+kp|j*G{=AMKW6;191^Yx| zk!~)r0_aU&`{os_aFc2m^=6f=RR|dyi1@_9Ojia28q>a`P?fvylUEfl0-}Ps{ZPA( zF?^!sV?0FiNe}_$<_~D+f#q*%vkPjsv}`d)eVf;WcIlmMakF;j5X7o=^$&&u*0whD z3N!cQWSVDp00UhJ-|2?phQti%ix)5Oi3SitW#S@B5v(mmDz8hUeBF=5WiZCME>>bb zH5s#WlIxX}-g9qBkDJ6J!Cim&|G8zyOy&E2&=Raqr_xXpf#(lbO(7;hi)b{(?Xr8; zavxCxQWJ#Wsjou>J^9qqV(*)HCs!F_JV!?GapaoLjgzO(i0>VKDVvyQ#$x5#oB_4t zEUj|-C(=|^Un5{E4+kK@K$#NvB_(QdcTd%xKS0eVl#RDFDL@QMYQcmzwr6vL)x`i{ z_5iInc_+gF4=PMTK_88|xqCr58r0O{eCX)O$-(iFw7RFKSSBPrIffwz91XIE+8)D+ z!(kSW!pAcpSSx%53dJBF*t&fPcyn#=@X}zZRlU0AcFp(cC%sm-hRaW>k$1Tli0>oAyhIK}%u!%@;hlbscY+wsPL~QSq2V!v{*{4fn@yV6!IU z;)K%zyEQ=Pfu3^)Dy+I2Anrkux%q(bG(Dm)n^%b&jVsa&tq^js&?V-a{z>=rsb+C% zW=(|3)%N5xAd-fj8bkvrOj3^{Cm@k6A8kKO$JzU+a9ao9?(DDymLr=mX2OFP;%#%N7HkJ#Mw48YhP) z%vcmAhK9}F+odtlAhFptrY9az0Y-f7*c};$OYTF*fWZuDWzpMcmU%)uCZMuA?bs4% zH0D&v0A(QW!DhgA{8MH-HjCBQVOmOeYr#Jx3FUjvmOeVeBCPZ`@C2g@BQ|L*K zZGeWE&hN6WS6_}K@9>0~LEpz%EmpDj4sBPBQ2`ZIRaZMqiI=3~?>2=4wH00R-Vik% zQYqT_+~RabS`?iixW5_}l&~!+7nbc|S*Q|0FBIZ>wYM1kvN4(cpve+BQU8+7qMdBP z=Jo?#0@V9~lEmRn_60O_PS3&kVe_G(VU+uA0f!y$Z2hz|U-#EX>tk%JI|ZlU2C2L{ z#h44`BY12=;NPL&-7#lPySxWkF+qD%-%g1XI3qT0e;4n_jZikiuIwY;QgIIS*%pWeB-snBN%P~%Y5qhi;9X;1-58V}hn z4Z9%)^s2+%gfs%DK1P^|k;Ab`a)`t%#2}cOv*T zY;Lx`O#XRnXHS;})V##{ItgA)9j82e=@;)7wtNSuv>9hBQXsSs8Mg=omaTGOAn7=I z^FV-lp*rP7ANu4@tl65GSUXfGP#YE=UPK8Lt6?X4OkS=vL~d^Q0VUT!aA$B^e?}zg z_RbdHx%CFk4QO1@$-MoCQ2;^$xZS}&@LJv+)XpV|z$x=1fGL2o?LS~h{Nz14Nhsl` zK}2yUpe$Ug6dZE*Ow|wh9pM59=U4Bd{e4_7zk)gyP#xn&3`A+*E+ZCFjqM|julj`NjuE(V<4Gu@^Q@}?9%Z3H_RRmLM zXBAZL|CLhfh0alWs0GxVgb8Bo@Tt|fFga(zPt-$&9x&;dY8=7Dm1-qT`V-aO@@aKz z%2t6vepP2P&Xg_>hA*L@il?FTKSF)>rWpH*oe~uYRK@)FbCu!yBO9?tUJgzo4@$&@G!`dvm zi^h;X4;4QKQQC;;yccpH?Wi{2el*T>C?5|EKNd4}JOOknjTPNZte`xRnyS;Y z66~?-U?0y9-^+%SN!#qZvs=RZsCFSsEjP^Sv?X}#=7mq+wRZ{F+K#8Mm_{I&larGQ z==Je=TJ@FX3e|iXI(6=3`i}eFW;+nuHj=PnjJf=-t=;<+i;}ANwx)H=zeGTPPyo?# z_}gpTL*m(>+*KPXX)eA&2G$|twogo>*Rw#FWzZ-Nt}%p-k*VmLQ`!ZQ7J)hYIKtAn zXC>$))%W*;0ZuBYmSF82OCO7k>tNfVWLTHlm+TXD!TD5hwrzMkPKw-P}F0NXgXPkH*? zVJ;2m{M-5}EVywfdm#6j7@mE~ z(qQvyf0aXvOyqDLP74(5SB;uMe```JNcpwAT?y!2nmPFW%DG3dXu0)IhbF$v&8~7? zxIrF!qrT8zK6Lv9`bRPZ+blQ^f=52|p{b8Fr%fkwU4p_EJ0Xqgm&@-Ef6T5OPKyA5 zc6jk@A7J)CEmy`#iXn6(h_2{O6OeeHl9_(5ZLqge`M1U-egmJH*Kk{6W^7y^Wq#{J z{>LvD4b3{2>!AhEICht-A5%9F!I!YlYnj`3sKlxv=+YImmMReE(w6GWo&LxLEi4(I zqA(c^Et9EEZNFntR0j@v)fQz(*q*TnSP0n*zta}wYkUL1P>vqIw~^lZ+56OEXF+3b zWkV!L*`xPFhIhaqbroXyNFDa}y)TB)*q-Xd$Q!`?!7?d4ENL+W?4{Gud}A}%DJXy2 z%8ko~E2mn=4|bIxQ?JO+m-KuSL21VG>}W@C^>y#s_cpx!dj`?nWhSNP#)Wp8W-XfZ zGQE>^_-&Ipc|QX1-^H3}g2Cae)&q(5;MMLG_(^U~Vr&kF=J(k17*E@xj2yI7efN51 zC})4$`CxQ?w5)H^Q~~in0G_P(QnAS>&0A|V{xV63ZijOPyQ3*Y1vH|JNYGsnZbR8; zZY7c(XL}p|MI#-CewzQeqZN4ut=Uz7sZN=y(^J;?7kEn_5bJ-H{Dv60DanfcXI=mo#ErHBPPl%C_$eLq&i4%(C*T24zI6n z=PZ*(tAizzEub=x3O-gw$(~HeA&B`Oq&vo=OC*-3xjnq2N<@C;x)Pq&OMg`8kPx?c z5LhB0;Na8UqB!utzbxpP+SvYO2%krGn%{d0fO=mNZGMTH0P^P1+s$nf3zQ+XoK`Aq zRZxcNp+*>SrZ3FR$*~EWQvT$93H~R63nBrbm!V9zYi@p<6rwH{00aee3)C?$)Ul8P z&Lc-EUX(Cgv*}56b_Z2Gj;fq1%>JlWq}Ou+V%#e>(F;ICsu~0U@IQW*lHoK>cjHJJ6*1bHAS+r`{C|+MiEbHfUn;&fSMdl37m~JuKu{S*c+y+epy51+( zmN**1^yqZAiq_<@Od@Vg<^Tp6ZSsg@0W6--#5Yd-n~@~~3E>fR$cEL6fI%|+mIiIa zm&rk$cN&fdL)}x7hcy-zFEvgT%0y4mD0IU#HM|%Lo;77ysy$@hB-$$%4%dzvoPWJ> z=_7%|4Ro4gh_-)%uEkzwI)ODo)pd>lu>bk6_B?a}uE2@$9UT6(RL!4tSHvsayuJSD zm_u&qB2SgIJt;-lZSFg-q#Osnq=f0hK{m933@aCht(K?d0@)=HU9RtcHaD}}+GL4^ zD-a=COf4U^52ZYUZMVkV^jo#vEyw_5tdmbRAq8900uLlhFo&l!&?T|+DS^QSB#Qo9 z0c_7l1$jIQXKt&PuNp=Al7F4f9ez)Rv~K>N=cM`o&F=Kd#Hsp-bLO_jH9XS5}1IauUtY{1c-fMGDcG7F+z&nL5Q1y)px{ zLuEK@vIS*ZW?EACSnz>jt(Pp9{!lI-A+QPvcckIHd_N}jcCof512spHGEDemM3S)Dn&vPY75KtSX`3v8^c)n(B znjCB!ERS007q?GSHsmi=(Z#X+z31G80ZkUE4x~1{GK>#M0YBI1+!-FGVjGm@lP$K&5<%)EyYz_99s!+tdoJU)5s4G#bopX6yfcH{LjI|){yh|u}3 z5VYvSjDKdAu+IBPAm$TM`Zgg0iVzsc617ZKHba2@M2G8Odl(vWaVOHt%!>KA)YhS5 zZ|)`drlp0k56hAJR)F>$i6hUSwdsC-Tod`u&3)T;w!PdL6qQl#H>*@3Z~R_{L2BIp zm;@URw+V|IHpLB%_dh|RMsq4Pz9PWm^!haEIIyHy)($FeQ2y~7MyARM$T0e%^qL@nPx4S;RMhBWC{f}QFtjqM|`=tWK(Jk`4C!vfS8N@_gT(^!C4Pnj3w z9{yfu$bsWP1ln;l?80M_^`eF;)G2OSC*sl>VX(4r@fp=3ZO zfhF=pn29CDp9t87I<&@iZ6|2Jpi36Tg%(sIJSsi>@x1qP1=a;m&E$Wf`Q68(AHIBa z!`$rKRdeI8DIFc{MV`)3O58Eqh8H{6thJ;4X%Z!)fs52J8*J z)L)4XMTi!Ed>z{BFe<(_G5jb`i-S6Fk!IcG{1S!dpLHud>!P)$hQnRhG%O-Q#@YE# z1uwS8>E?FN9)W>3?EVp}lbVI67R6HQ-COXV1C-%^6gn}0xd(#CNhaz!lBlV5?!1m> zbU@8KXj6)czSw=~Zac`^vVp99@})nN^5HBy{#J@owKRbdiMjedzHpqt(z2{S0#|lz za63r_;c+u;jnqOPI13ECX*$FLFp zqxZaw=>@5zyFUh%CfuGB^Fol-Q(ieLRD(KXT*Q}RjGsFK*bhxtz5C03o;{y$->k3I z&wu?HtQZspD)L3W?=3RLH{HtVk4z9L*+DtBLxjCx&z8XYpY}Vr|gHk~Vr?B;%6-eU1p{(O5W~beF6@B^c zkHt0#m(3Y~4M(L2viuy_zu zqJv)m7FCJ*mo{v$7=j(FI3NUYXUWaY9U_1jv5LE3>UHC4fGRJ5$%L9AIu}TZeV@_2 zt`;qwx59Ha?D>t@SAsM~?B-uxr}*0L2{G~IH&G(8k-F1tY;E}jB0nOizugANY&B57 zm4}}@H+A>yI;vy2M*vgCdP~dsM^6$onKKvNxJ>kVPGm-T+FDY2)7-18b-|OU>^HPE za!MB`k468Lgu$mEG5oXtk*B(z)V-KlXI!9Y+2*_H!l94?_dQRao%CKCekLap(19+4 z91}2gZUe0J!O@a@A5v$(XSpS4Y508&q5JxXtkoBhMuR+(x6}WBwLrJt8BozUkdgZN z(E?!kfX)Dpy=0%i7+D^7H6MHS4h{|ku2KRTzE{M-1CcUmDlKBk>%l&$iMMgxQz`)#)U@_IsbjKpUzq#Z z488Ed(ZHgQp9Bb00_Y3OAS}mRe(;HXP405A2Tx~P!>wOOmA0(Am@FQSW|?k|l9;A2 zC#pB@=j>|*8IggHYe7Skj^F>XiI9s&8a=#^X@vConm@6BRO9QH4P zHOo$<5tnJM9PO9DTQ)gk7AuUa1(sBFY^syk#l^`$;87VD!Y_+Mw$s0Wz^V4mAG0o2 zdF`+P+L*PsA$)WbvKsDP)e#I(RR}IEXZIJF?=A7yf$4e^!bu6d3E)cppB4a6Ytnt+ z{Zfz+0Z`pwSJB1P`ShCNTdQ92^eKI##eYJI8CdUd#IUn}wUs$K$@#8Zq<3B}E&Uj6 zN+gLP!x90E14Ml3C_t5jaOR%Rug!DdEc2Cc=CnGH63HiDSw4oaanDFp3(4nyP7#PO zhg@5==fg5U%}R%d1ENou5ZAZLnZd47%q=M7ev^RaJB}bUOiW`NnAqWH;Ti#+^A!V&+rB1kvEcMT4;xTNKd}KK3rH=E-(5%Uvuv}o=Mx(E}*>e&SAkgRPK0+BkCDa$^rP}P_Sim=SG6!}8EYd%vpLij64*&p>CGFBv zRS}K0rU&=T$(XL2K+C<97Ju}s*|vmtq{=;+sCwkKrB#j1Foavnw|Bq?NbB37LZC4Z z1k4E#-*po3oqbywBVmy>8l+@E*zEeMw9D`HU^B%PbSnr!SNP@$Fx)oVca)lMa7g$Ere@;xu0J&t;ckYSG6Z`G4enCRT6|}7QH%{m5 zn4wihjC6E@oD=>YUx=y2gHpiU_g^K+7MPpdwVr2R1_L!&>PjkXlus9y>Yxz!E7IiY zm=1%s$IWc^o#MBxz@mkSLEd+iAi5D>dtXypu86f|LG4wo`)R>6GF!{C3!JCn|>ifO9*}VHMF_63UF4J4_m#IL|rMZ9I#Ebs|Bz~Ch z{=sCQ1+9ao0Hr~t;o95!Dwtr%JRz=?8`hxvcWs+=fDM+Hf=&Vmu@xBcme{noAGfc_k$b%x{a4G=XOc2p55gt*?*Ps$ATJ zJ8GIU(jx&Q5gl~b+1^(~JW>HjupsbVHEjpL3sWNKj6**;7wnx0%nCK$*3v`ch)7ka zwG1Ie>^ssK-#2E=Y~P{6U#NE+$?up12J2bewWaeVM`u6ILV zM##kjkKO{q6PGl0u(xy=UOb4&wH0{X{%hE2j#i{@+kfenw|DMhMNUdA?r8GR*O`dB z4M}#SqUt30f0x0a|Gp0@FYi$2g)&6G$RN6GcYR^hc?YHa#xfdIg=e8*?MCCDk3~Y z@Fh`5dLSMlb)G}(>i>@tu%EdCox~K2Hs#Ql&~5v}pQI!tsEh*Z*o~EBxu%VJhf=sw zDL~T#VI51n@?hSDD(4lQs%vZWQzF3NaD`F;9nG=yxN9ia*2E~V&z(D%!tU?tp16|o zyJK1YVl~-M&XQ8VX)eHhx@>J+%hCd84BY?4BK(2lv9<*{*cpyzEwhAEB(tD1$bg$VX+#bDg$^*z zRvi%Nmv;;uE~@AU<3HuG?Mq_a%3Li`te-8fuTMI+`_7e+CW0_;EqMK@f!5dKed zJP$$6rokWs$MTmlXvp9kkO+WrWFZ;t&0~Gdw|DlPbyN?|+=SGQSQ1e1|AyU6=zDg*-`b|R&e34Q~Sb-luL@^^ti;k%(gTaIw90E0<1fvR^W5%+3+gAPut$cEvdnY zlMCjFCwUY22-htHDkCE114-8X)jAjfS$15$F|c(%Q5<&x8CXJ2>UpXhiRoQ+B`;;b z-tfO2Ha>Ui6Z)57L-{}rrTkb5_9zvLl!VM$<#%CEPhGDV)jvN!C6f&eP3+8al&Q_$ zJiVC=)t?epMnJS3#|RB1=A!!Wf60jU;esB0(y4#K3sKX{=uhdCNkO(=?Rjl*FRUSi zPY*t*VIvio7lkeFoClC{#g)f{av;VOXs=)um$i<1Y8%p^Pp%ehSL+K6$ZU_l$QF*f z-KZHyCbMpY__(|kjw3FMm4z=ns9%Bk7T^ixBlfL>Smgpf@nQP0$N^z-6PIMH#;8Bl z?EjANG_CH$sYub`M+Q$1=azrxF4xuMK65SoW=7k`2uHRI5%~cVIukauqG1Nua)td0 zqydnhAj%IQ`k0vYf!GVn2PIN!TMDquU;Z1W?KnLhh6{^$l}F^GB8vw|#UK8Tyzp|b zVP)tvuV20hG<+Zx%JRZF()krw$r05P8?YASzU@nXN+d%M;@4YxP<|=Q{>F;&+0Z%UKJTP)(}*g?U-%ev%RL6>#=zEjTq9T zYL+8+T8sSymF)LN7Epig{UW&y=shfm(>uVakwf# zGJ(q%$aUNkXJ+MF^TgeBe%x!qmY@ zQiQEX@m{DH3K2mn3v$`@X+-Z>xA+3J3JDokd`?GvDsyqG1yVy<>kYLLz(fMs(@lg- zMTWgS0#sdpNW+A|cbBUkn|dWDLfa3vp$~H~w+{bRf2evAj9dyNYSHFUWOxe??YaiL ztX7aVZCyaO_WG}9f?GV+>5aKIQDxWvR#jl25vyMAqte>Yow`@GK*sRLwe^$VB7?x} zab6er9K4@>E7Gzg)Vp^BL}CAvWL7&`W-0z_SenMz@qcw-i?4+Dn`{>2@~>-w_=&K+|2vbG&~*xU`q7@HDoD{ zX=$~*ln=}!bDMTrRl(-%T%5K3X`(-oY5Ds%tDO>->`DI-&U@rzc>R5pG%QNzHT4TN z?y-`|dj$n%R@K7N@$8L5>xcFmfo`!XxZLaEKiHx2jiHjC)IxD_knx!nWi@Si@jpyc z#>>Yir7LyQA#KI%d)+j(JU$<{dpPUOd!OC&?8W0kB~UZQVGV}`GOISc)M>!8J})C{ zo-aKqa49BfKKb1EDdXLG<$MRmQT<43S+DouFBjXyKke!11MQhxw9(7lnp=G}WTTEI z@(m10fi?-$(hfM#Ftp+uq*#=Ho^oidH=xdKpe%2Eo@(I9kLxa$?=$Kq*VZ2&Jys^n z-FB^ecJi~$?y=NteBAfAEw(Qb=KOms9uvOMHf5NsT=M<;=|$Gw%)@7EYlO(e5m}1K zx8Ede`>?3>g!6oa>Kl0GeJS*^YFU=zby#uCQwA3Oj>OLy92_-exEuaH^i0NCpjkWt*%oV`3~G zo{D|DqRLIiLruD*U=ccxpFlcWMbt`O%Fl?l92RjVjIVy4$BgZWiSU|h; zrb}}ZztG(?y}zosbxRx$x=SOb`Y1d*@$7Z@QZ7J0?L8|W!HI$tx4ye&;hVr-?UYFs zqb~{OQD|t!W@O1bMROKGy6G2PxsUb-_L~t{wQF7yU&SedprAtN2QIcR_kTZS_1X?@ zuC~^+I*};K||L=>=)xHQYg<2r>BhmmwpF=ngmzVEs;I}?av zgB`IOGhJ<|wEL%jyzK1=PS+P>=6zS9volU)oi!Kt2FS?9-S-k>@mT_YYVdzs6gjLW zxit97gc|P&swYM3cf#4pEAV8$$GJeWh9Cw0za!Y>cBfRcu}_ zd@r(nNo)iE4^wX)RR!~fje;oB-6f55cgdk!x;Lq`8_-p*^Hj{E2n z9Q|eAlfc%qi9xiD4!_0yCBGG685U|MYp0hE)p|80{7G_z4wX#wLm{`7Qfy+{XJj;y zm^Tf)_Bz)D!UEjah9p>1*MHxZc?ulzxj3Q6kSqsYJmNc7JyF6-4Y=U(&Anu(@t<4q z`rCD!XUQ^GTas3iGfv_MVa(f6eiev19vc(mUN;k#oLiE%_hlEx%A%oz_C2`U)>pmZ za>TNjjGhS^?M~2Az;vWYTlccH{nWkCDIFsZmxCC`%0|CTxt86#PscXT46MyIX{ z(aLLY{&nJ??u*{o!)IbZentfS`NPIUZhs+1ZSEfFJZ&gi*ygzo`EB3oYD=6g;6^Zp zOG};c=g;ZkxNvmeCRWG4z?02wY`XI*H9oxFIsa2Xp^KYA4gBhp&MPXumx_I=C7Gfp z*}`-M&tFgEH}wDuZgM(gpPZ+?{Ls@$Y4r7}HMWj>=*ik>xF=4eCv2Ay_PfC``zFU# z2RAo+wFbtE!tM|HL?lvP3{f3*!U)QWR4z134?_K!OZ7`fZJ`NyaWd3FiN7$BK$VD9 z+BKKt<6eraK`=7;(dgKHb!EPOKYA#XSHmYYQ2niT*>$kSfRwqUvI;By>tYyzdtgX% z399<~9^IR6%F=` zq4qS>lw{3BUmhlp07b!?8OJ`VUv&d>;xA{-NW$ym7GnHRDQ9OZbzbLRQx`!v$yVwW zzq-{z(W;wIPn=uVsw=o8?8Xh7KC88xc-&?v(6(?9e^x}jOeM;Ad*fX+K<9KtS6p-P z&j3Y$A}B6^jWFCeVRignNz~lf*6x)4!Nq2&c<7w)*pb^t+MsC6O4ib8Fn(u<6I1e> zx1oshi&nwL+`48RjWcj=EQ;wV9#7Db7$Y5^hjYB2o^A^APKxneGeYg`5ZCAYPdK|y z{NPjILnr4}TABW4Wg4n&9k{ek%wq+NY)YxwB1AJQTG=5|yw|H7_Aws@S%pn0G)rs(CWr4F4YytvT@Osf!xDn~$v;6R= z&0HsYRs$Udo^>;tVjE-IdRF#jTA3Y`N%7pS;Y>(gx3frUTD0@sh?5v!Y~GYHT(qV* zSff#5oUR96v;G-tNFzuI4sMDYIzOlng;=3icBG9t)a9{Yuu0e@#0U9596Nv5_7*by z?;FTCa0Uw>=~A`+g+e1D9eLl_WoylWgujG^eZ*Zl^YR2%>17#1{o|;t903WTmZSmK zMh7IU=qr9SC!O|NE!)Yz=tg~ZLfIE*Xc?%TS7$jx2P9cg=uPC)!_v*>({=R)UXt&6 zfAxCx(;B+>SsZcO9C(UB$IX^DPp0^SR|~9jZVgSr?P|8Z%(v>+*D3JQ6P`bcOJ3|G zO{BZlejSkV!w>bUo0oa>m4;%wp10D`ZD;z!4@1x@-Z^KcGvn2r`_!%}tk80j28TPJ zHD#5QR`v8H(xTiO!c6pOQt1YlXG+w87GMA)QdlTZzEVgC10OQ@C9sg+(}R8_#t)lW z@iJoMr&%(A3@)Wj?H3HypzhlKfEfEX3lpC0<_^oP2M!XZuBjwBQeGd6N=nfXF=c5J zx*yv3zI60j^nQJPU48f5trfr6h!^OOSk!r4wAb~#WT8y}7eJ+CX}-RBVcW`KZ&M;| zD@_c4$AZ(wQj?a-U~1N|7&Svz#lKN8IJ-k$p?RcyTWYSxCkYM0pgO<0b@e9gG=xu{ zaT3e|{q#xdch8O!Q%JS{)BVjt&K*4up4ihpT+c{>9%u8|^gOiJcEuft|=g*aAtP@IbZ#MUv7Elr{2P@GZ%N}C|d zd7-+QFq*6oCi6mLTNjg?7d{YGT3UM0(6}6v8KS~D$uVwQS{o};FCQk8L=d|8E@^|K zK3O#q1ES9T{)e{HiJxb0nG>C_hWRab@vf$V@;JE=X}_HvT0Ax9PYKRZXn!1Ts?xzk z)k?|VDweht90UT3Npnh)0d(a@32kq(*f|Unr-r&z)ngln5ix?llhVm*ZTPzLZKb&} z(Pfwn!|g2?T-Xo(lMe=Thxikcl4h8{4VztKcs)to zZQKhBgKk~e;gAA1ZqrprsI6qFCpWc^f^S?+A@?#zZsl_lu(;Jn0mTI{k|hsHh%GEgMJetOE~mclR>BkI{HC)G>swM#F#5q~sBe zivuAj zE^qBSGwX(y*9eRP&K8NaMGHORNqf$!MX7kJ2ct;w(th6wnQ+9@ChHT2WsR3=^4WPf zHaMAk{{G*|x2Gzbz5a&kkyA;C@hPhuZ0w~<8g#s}%q^HOl)8+DuB{<5 zlk;2Ga9!yOye^+;3*J7cU|X{O-SxHec^mZJ;1S6_z0=3o-5fXjvAOu{>EQ^O-#^p= z`Vxkcv$?bGhhM=fd=Y}t8vPb-xURxUc75G`R396GsKm@A;RjV%l7`4`aAFsKc)s;I zk?mG1%Hobao&L*>d4X^@cJ=K^zuMu>rAQ{DP@+j}aAy;N{R5WHQ3qwDv(&ic^kMzM zc+}M<1WelQ$-(g?Oh`8C^BUIp>wdVawqiOTJTg8lJWt#x!b$py6 z1B%3WGU3+=sck|r z&Dtnhv_)*(*{iLRYPOu8&O}Mg-*bNkZ=80PWqu(KvWg#)p{7%LMKAQ&i%-G2!y;qI z3^yXRO5x$S6k?E-#kZ1?F;7iD;`KO6`0)4Nqn%JRB@ImzPQ;Wn>uxe^-${87cI=z( zoX39u@n$=)!v5C{j`DL^LR%hVd!P3fqzU}yZA7tP%0FUf|$UiyGr~6zfP&L%3CEQ zIsW9V^c>T-VaeZ0(yYFk>XsdH0=&w}0-YlyAd|K&>7d?KDo)cpx6sY_<9zNGo5!IF zfI43=MlD%%H**u$M-}|eehbsP;x_nxJY<0%4S6jsY-lxwI9yul>NQ`6LIyFAkvD3+ z)VQp277kwxOBw|!*Ic!F0_0(x>aQ5zjv4x9qdm+b% zsPnAYKcFB}Pct+{xvf-tTHin;yd(1Pm#!HX`n6GKHPVru9_se&p^Ly*9P&?`9BQTs z5gj?@3GTVgI$c5>Y*AqN4AVy>E@M`MA4T~(R^W|!fFe5~{FwdY2T3-?9nP;SG*o&P zaa$HB9Mxu~7`K6{)2D;yNm*R1{)Hq|LJhR!K^QKZ!VW=!^s~J$D|SsnGAh%) z$jpkv`0yOd;fe?p2T`nlFl?-u!UQke<@TRFkV8_m#FRwQNX#by4X$gO_cRWi{3^T{ zl>1pKDPdCQb^p-ZrhhsMlAV)Fy< zl@&<%GLtuEj`EdIak}SJ;y55wzmJW$8z9W$YkwT0r|xT40TGhO4`wDW6y4p4MJ(M5 zJ$T_#Qj&7>+EBP>V8OMgTn-LwiFFQ?X{}A=ezuG-1jCj5P0b>fu)I3kq=vblovcf_ z4miP>)x^aY0G4e}aLJSp_Cj~u0Z?vO%&Q4z><)jL&19YTCipDPOelAwU2WIhTILB6 zDRj38KIfyrO(KEw3dKO-QGaLZaWn3FuA(^b(T+i%qu9cQu>p1)`%k}IX@595B#icT zFCH?_%nXkD#6x#*Bn>tfcCE_J?ru;F2-eu^&GbVzJ#uR+M%ikzP?W`$3QqyZ=ozjk zDKReAz>IvcoMRUt`45dwO=D-I>y*#wJ+b?W`le|hCPXeIzl+6u-%Yn6&!QbOa*&;P zTv%;HSZ@hQGiC7VWYANoEv;^E>yoqhY;^O@oG-CH{@c~4l@HSP?rQ^`#Js#rZ}dLx z)<|vj+{5v|Ip|Do?z3`$N)Xm@vP-VAhN!uE*$_Rh2on&Jh&?Tk=@Su6x{WS*x>0^F zCHk^x!}Wu!d)ql5%(9=3YK$Npxe60$N~}E&tcUmPbHg&ZKP~DYnd!EEpVU9LACT?3 z>^ZXRt1HLGxzz7WGZAIX3?s*5*q@gge_s!toUGv`K+1c?M=Vp{=L*A>pmy7Burx8V zkT>*Bo<<=wsYvaDIn2q%Fy?@=Vz%eFq(Rp{!l(!zAAezwNL*=139CK%|9AmVUQBYO zDZrm(-+C_ltgf6UhkNoz59|Oa-~A37YJh)n0T$O4&~%60evJR1|HI!3cHm&EMp{3d zj#__UfqJyIuOYioi(2#mm^Ng_alkTW!C71no*!_@8x=41fXIBxJRru>oTcqNKYW3; z8>rrW>UGQlZ4mJndv$c%!kzPHpT4=|HYMlZOQJy3Lm7sFllzHxeKOCh>pH2^Zw|P8 z?N>-$cP%~>t1FRUoCN!@LVHh-LEizNNDs0%-;DZyXPx#xXVJ_Qe{&8rmhpnK#W5#m z^9H2$QReh7gAl|xVcdcs%?9~O#m6S|oLtmvM2&=>E&^tT`S~a33Ds1E0O8WbhQZt= zNCjTUF&4+>+L?Mt%U8DI`OR75H8iHEa*@TwJNscToEO;-1P8R5Nkj_C z!nmHDf7!4GeQ%TGYVrxfwC$vn${yWp<`_r6Nk;XlQ&%(#Sk~#RH1vXFowwt&xQJw!1J`;y zqBBhr)6d4i{-vlz!0vAKAGS5$Qwe%ZJk_6O{{ZQ=t}2%*^y)tXZQ>*KM@BxleNw*fs4{ z`}GX7SGnnSekOgV-8=?U_U{H%#Y&2LPxrih+l&p43tX{k2?6LKhD7hCvd*o(T<~0m zS`lumqQC2pc5##187p@d4`Z)ojErKsUKI?;?6x(stGG)AFHUt)7cn+0M%5^n*ZnE`No zE{{pO-xp4|aznKq^qS`aU8)D!YNDazRP;jx*#v_N*Q^MPjcsl5q$w4V{Xjs<8DbZq zl6=3pEBtQUj6>e5xb@A6+x05Dv=irL#)A|8u^SlT`?Xf;MK}dx_w3H<+?owQsCv9o z@$$6E5qHniy?*)pWbqG!A~8Z-bX{WmFgZ?mY1*(CN}OWb%qk7(NMrqpyuY6yNa`n@@M52f;aK@gk5$#qNU=QHcmW(>M zs?yv-g7oR|GBDGn?!O!fzTdz6eb&5UAsIbxnc8GgrxTRV4r5{fsOv_C{xS&^N;RED zl&vraYTu-71x4%k4mox7+ayXI)bSi+mn+S2ZBv$AjJC-Q@$Wub?%G54x+)=7Ei(8a z5M(mdNP4do7WkH~XF5oTck7t}l59);Rg<@T9roj=#x%)t+xcUT1N3gUsx>h(-O|$H zi{`8G+Ud}=<#=R7F!!yE>J@V_ns_uDJd+NlyFAZ(u$1Oy%AmpN1y4f|PRduP1^A8J zl3iHTQ0ta{@#~{ld^}{h+0s_eVXj%tKW$y<^6y&~@hx9c3SQGXUB`#c{^NleJ9v5P z$5dDw1JOdY7+9|_AINP&%HK%L0EqJ%##f*5va;+H=$t3!z4T`E8Nq2U7Kp=~C>cW3 z>Mo1AucUNjM(etfWw`J@fSV7dlbok#opSXL`b=E;E;qs3;`yY%YaeL0_oo!!m~tAxPJzd?0f}voS_a$I}i7lVeqK4ki#x%%sj7aYowb0$7Q6 zapWNCq~kW0MF|+SXYClh*{@q>?%*WL8<+Ma)C@?aTnMD;%n1=?16n1Hz3VP6thSE$ zpFCA`SoUxCXWK+jQQZlajEj=e|G<#gB7ls#piQ|}XYuG5bkkQkC+{u;O8fSbG`0PQ zig$h#TJ#!Sbyi;*_Q~4RMA**VyZaa=t{)*2(^Kkf_&fSe-pfwS1~MQuD+sFN{82Er zoo?kYFJ2@OaiMifZjN(7h41elJqJ+hLkEsDLXwK+HQ((c$dKouggfurGX zWGY_saBfWA6EhTOe{0537{|m!V2XJ#j2l6UIQb%;dUJ*IDaPldRgm?AtJ%j8765L| z>U2iO27;1r=R5ouKN)Ubbblb9n=hdLu)b)rB-(i;{$cy$GXa;736P(`;NA_xNHb0@;|A27syxY%sfFdt zgc3p+DO%czg=PJCf^q0%Meg2--q7+Z!%t6t76Q)QZ9i?#%%RfQh%}wRa={bJxg7H< z|C7LFk4v}>M>Llm_}L|?&o>u}yn7!PZw9UR1PzZ!Pkcma)F8_WXDx=Q{?q?3!4-;f zF*1V<&!2fKDz*`bgG@X%b*rI|mAn$TG4)te-H0(st#0M`9YfMazcG2H`AiECr)ON4 zfE@P0&CM!+z1Sq zj}{P!y6iOniEwd?G#|6qQmSTDEO09!wf~k4qso6vM`G5LL7_eydTt zM1t3#qohwJLLa{d-Yuqyg1(}eXkpA)jJH4SOH8SnQ1mO(Nq|rbf-scg8w3Tef{n9R z@X=NwZXZ>wih_`;@k39R+y{3(GH?Mil50Yol_3sBpG>*+n<4C;VP;0g&~UU$YIHjR zcWK@~?(bEO3*}wEmZGYwOe-Kv3Qy&IL}e*sEO!y%Az@y5yz^ClGj_d2XIAkn048ka z0Gxkhzp*<2^%U4rrDo3dT}d~(yK=678gpcKN?)rANUETrsOzNtJdli$t}AYJ@<&2V z9)TrR&$W`Uq*7B~O2D2;jgG&;s-(iY#ZDYnN)|1{UJ^SZX(GQwCrGWXx0~BTRsXFG zt>i{C0P)@cKXC&-QiTS9DHRyOdezkqF@BfqYu!DsC zDLMU!oJ=cBKZ4?fnHmw~D#D{B7WMXp#+~1lL0Sjr@f#F7U$l9LMpIi`PQkzMKj$iM zdtL{oJK0{{`@M_l3_p>uU8WioakH5Xh+Ek90JL~eOxBVEADgX8SKCIz;!J5%l!8U+ z+9lv!Aa!~46d49DCRz6XQr7BhAM70EF4rlpiZqtHgK`kmrZ#_s<{_hsp}FL>ajO0y zdtHSFK#+(AL52V@9W=cEA~hXRGqM-O zb8+c@!f7OhxCW)6uts8UsUtb&h|*Oo*Vejt=*Q#RxLYSDU=drwH5n+ajPheZ{z?|Y zs9cy)2Pl3L4U|15e^b1(pIVbOs#>c4+hJ0w`@~4pHI8g09j=3+x3L{T#Z@kzox=%p zMbsM|f9#rqrqs4q@&5zqV5R}RegB6r5XJDt?ZD%CxH+MwR4-t{B_J~Vq`Aw-$Q~IQ zp2S+6oowz}D70$=AOH0LLbM>Q+F-Z&d2|JIr zs45C>zW?2F-`?KKfM|Coz7rfoX;W8F)KIV{!Q-azfcRPdOTq(WMz5QgabX91hLK?u z+$Ar{@U4bdV=2lVG^2$J4voD>9(5P-ZQo1&KDxO?Ex_>vRF_2oVZS6mH^=KsbX)3_ zI?9yqwO)#<*;RVX0D%`A`$uo4UDHSYFrUjmvkHBu;N8ERvXVh4%jl6o*52NtMTrLn zcy;fyx}0YFLD}qpQ~{ez{JG*fS_ZRau|<0`@RW|nx$tV#El~C?+vaOmYWACt_HDF% zLkg4WeOG=UZi?MHC#}Lsk2eTIVong24#=^R2;=X$FNj>MJp{neyGF)CLeFQA#S9q+ zgDs8UK4lPwFdLT}Vb;>I{`Uy|w8_hp9Zm_OJ`+wz9UsYJ!+ngbV|jl-%eyY8nyhS{ z4*b3i=S;t+fbTA#{PVmxS-R^suW)xbjt;a5egd?1f5DQn<0Rs%wS5{&CW@c>z2hy@dmjeI~pwSyn$D zX?)mTJo1;D`eUU5Emo~L<1YN?k)-a4ub zqnd(D9=zarz(BExZuW`Fv=W3etT3AjmIspB-@hn865$m|pdpNxaE4bAU9iJ*bv04rc;oH#M4B^m zRQ!ahjr=LC7Bx} z=IkYxuU#B^hh$!6Jp9X>VSd9Nu_Q(($J~)$77hAa=fh0rpwYiu%Y{^i0h@->+0y57 z-EK>qm3r|mXhJY49u|j%DtYDj{qpYLwRojO3fW=BE)pKSY$fPj`nd4S5>){S-O89O zCVQG=(i#6qIc83g9w$9g4iY@EA$VQQClJ7;&j63oW;5;)7Z?MlMZQgnMd(VA*Ob47 z2U$l%?NnRI5dBJvv14LZ7IVZe8#AsrB2J>nZ$FB%QI!x>xRKBLnDchDqe@%Dc*6QE zf>?;&v^dU@2EfNI1rOJ9^!D>$MXrP$jX1W`ROqLSD5kipaRh56xBbb71#}H?DU7dws>`Wkaf5&J?K*s`c?w=j-dEB}L2&sjA5; zrT*vBm`+N(J%Tl;nogZ%h_mrFTltL(|K+X}Q%~taRX{U$`OH8hWUxuU(a;BPsd4~* ztQJNRT98Tt=kytjTb~*8C2*}K3vd5r9Rap&Q+4ojXYOpQSTHijq;{KGo&}3`#dKrh z$qREiW(WeNIFrEZG z0IKgV4bt1}_)M0~XQ6R5ICT4=9}jd7qV@KpMn*Uxhvj^o9afDT{g^BHpN4x*Sl3K) zhsCY@Kh2HFO+Y?}U%t=v@Cw>4(Z7jTcbn|LYF^u=qls$$DZQJbe=QdPD43P>aH8jW z9c(%gCw~EM7w9C+Q=x8lD~+DAj&O7=E-W>Cr~eCu8WW9|0)xt>HDk~&3T(xHKJNe7 z(}1O8^-RZ4F}g}Ju^clk>(%#6qQ4EC#X(62XI{^>ItuDAb9qvyJsM&y-q`lp{5ajMuTJY29h%s?7zC?%`R{WvpM2Y%QZwTpRm zf~BR##DahH5$RfXYK35YGpkz&2#-!)nNqc53am+0>VAa}Cx#;VkWR%2^D`brHl7eC z&*qsvYMD4(>DWXojwR|uM}tE;0lJNhVe9KQzkehao6Z#5=?b)7LWUlOdEd}Wwf+h+ zdL;z^R*{!_3qjC{Msg$!{N~Ja>w?dXu8cFjZ7+b=|5M`Fb-B>Z#$kE+^MG;hqUpD0 z?@=gp^?U(%z)Ep;)p#L5`R9Lgf4p!(&@KcIb9(RB)MzWHe_+--AExKZvW@kqYN+w$ z#}VmX%ah?Wk6p{=$-ZRz7((kV5AQmdt@AiI(r9qxP8Quc!*{4_R>Shfo_@QHI}S-PqW*{8e`U5%FLJflL$7pe-_q)FraL2 zl-Up@W(s~qYHNofGmbyIwt&n?T-@|t$3lT!eoL1~9C+RU+(!J5dpp4+GIvoR-6yeU z_-%%f5nhwO<+|!Vfg6UA=fE(M=-8K@sk8FPn>Exme25$DH#>g>pt$SeH(ugcQx2@5 zkrnU!Hs1}2u|W?zYZhx1;y~~WYv45_izUtaMbbXo7D@29o?gb;HvYdaS$8}lPlc?j z=O_M70%wuRq76lLF88yV%fA{(Puz3Hk5-&$BeV?tNR@>?1;J_&2IB}XX2sY-c6=tL zTYku5a9T(78tGMPPiF#+VxMW07Q{1xXNicn12c8aLMI7onWPdIekZm%r_Gp5t_W@I z8*VFsbi_v?!vmUqZA}M(Z(ev z0%a{{O3tsb(Oze+aG^B5f8b7cJ7E~EceAS-tNr^KjgO>m`XA>iM;R4Dpxev{rT_`! zs=$qln+FWIlJEgr622m^j%mcmL>S!V*5}bUIVHx@)5U0{9sS$AHZ|XXSIF#HtC&hN z-%SKS^p(y8-+L;+f*~smvKdmnpy1P{RmQ`Hxwvt$C&h_)GK=3G26OpWJPfF+AwG)3< zljrW0M(llIan7*LGzv_0+Z{Za_YL_N1QrW#9T`JmDR+>ka<;0v zltATi!&{xWNKwhSMXIkDb-yPtk+yv+Vr=k`DymdQqIBKGebewxqh0y}*kj14{W3 zDrV1t)%_op+*$@|TncbD6t`BBIn|OPQUu|IUllR$y&)UhpRYSH>dG}}RoTD9s}M2r zIe zc3hUkbM+MHXM2H*F7$V#IAqxQk6jc&bUz?{j*m$tJXgt!it*`(sAXm>d zlV2E4n4#5kTpF;@a@F9KG89k-&BEb1fTjGNAk{@$wh$F2~BNut_B6O1qh@TvZ9b@&eT}A@*lQD&I^!qOIX6kglhZAd3!Fh| z48d#XZ^s>gA=Xl<5hv!x%=Bk1bwTD;(ZjKZl3-T4BY5ojtYzrS@ozET&6`-K^S_Ji zoeTAqz;p4~dOSc!=7Z1xo9?4OxH-ZsIO6`{qG!~c+B5+rQ>wYMoK)27z@R~^?yCc| zpy0#_1(u#-uwGTAxHp6<)MJ-zO>3NGpbV*cNAM?>r|hbjmUQF>DA_&D#^42e9xRGJ zHnXX@taN+=lsq|;8p7Nv&PKr+?`0PCWI|2@1Azpw!*uzJ(>}fsI@+Kl0~M8_G5H|l z8ePJdr0+m(QUclT{5F~!PodcTww0mXFz6fu{u&*9vmF^fXm0aa#O-N(;;ueW3PwYeJH1xhirA{bM0Z9!0oR972e-7-(lPDmmJlsY4e2MYaG2{V&@q!G~t6Qiw zR3;74UkO&m$%Hu@9w7vuw}}23sy7k9ljOrw(~n6=6Phh(^~C7B6U^y#&3W8t3D{X` z#)^5yN`1d_{;}R%u>PYea&UF$AtFnGs~T4PJ}=Dgzsr*F>i0W@B-E_${3G)e4SdPg z_JF}SAkd3UJS2^wATI>Ydp;Q8oqV&rl%&RhR;Oc-lDJgptF=9^-sHx*kh$C(xM;K8 zikp&*v`b6Xb3{%Qxz|BzxogsLC#>*GDry)a1gjH|df{`~;#92#5Z3#_wD$(2Wb+-H z1D%z4$bVkI_73p6{OY^;AA#GV@8Ez%)$?8ZFLMZYM1J$HZl4zv5|3drTEc`nej--% zJ{tJWL}YKY{75|=?8gsoHtCd&y&$6}axz#QryFyp{rEP5I*N|D;f`Wt0e%h}7Iqlk9YRf%Y)ZZ>yZbJnt?Ubx>Ayr0UVX^DHwMNFQ z-oOr)co>hW5R4|O3^CS)c}k(Eudh9}`I39`dGiQo0G9~$S!DGBZYe`+9;jErvu|w=l1F)H+P6)XG$XVsDZ1M z|NR61=)k6l;g}+AVp38a9QKFD@I5%rrFaYzj4kdRJk>}pk@s>{JtaWfeZPLWGvi=% zJLlhRTdZu~ypv!TO5U>`GhYh(7|XYcFtkB&lTSAs2J z&`c!>C}nDvipX3%5Pu9dNHP#!Gz|Ca(c=mdjOcr^|Mt?xquN86*)B#0%x#19!~e_N zmSovY{vR(u!XKVrk!-ASI8~O>ios`=M!@ZpmFD{2j;{W9yvxSN;ZSn$+pZ?hVgzm3 zTy?gCM~i>hM(_PfE%COyJy_;mJB<`Jqacd>?69%1O)$h*;eOj^criF{Qh?)R9)yzx zI{vfE5G;20{?DT?j&mP$=hGIZ6t!hJjOMjWq^0YgO9TykeB29mZtiY!f*@_T7%}oc zhZ&$iQ2rIaKI)-;3Z?J2eGpmU_u3LS^T6wJ`J+U$5xsQg)z;!UOVi(5bZ+Zr_Sr$9 z8QeTT_!8t7B8KRW9-xG}F53X#pW*vIbv}DW!nVKfI|88kyu`??pHTm^6R~#OP{zCb zqeb~LEcaYF5*bW{xJfOf87XZM<9OAxsn=JIFKo#!z}jE9{5R+|8K z81;fG(6kg}>G_J1A~ZF;Ts^GeVakUkpn`&WPF2baUBbG6U-m4ojvB07_AYo&-+(~T zC-c(%MD;=<&75CFJWTjwDSed>a7O#8c`uv-BjC{A+vzN zP4m~ZLCdgN>4+3I1wDELf-5&#NTDrP;Dh%l$XjV16YB+2w(?D4yHMbAh_I+R>Q_yrguv$WuV zYhZFwJr?$|HBs~p3eUsH-rhWuUNjDJRa9JF9_aC46xcePLVu zjTecih`*9{^Y(TUn@W?+%MB-vtQ?lb$*!s!Km*przt8Kj%|z9eUnp;RistQnZ5ITV z7GFxrsihJB*}!!Mjz4f?Py-_ghyO9{2{D6Tt2zwfZe3i+~C zgX?`C5Q(*Ev@3@PXH(!qf~RT3=kzIn{fM50%Ao7V+DF2n*E)C?`mM#4;K9`+p7N?4 zYURr-1bXReB`9(3e8A4Z16V)V#uz9!Ds*qzy#z$36>MN9N7`|?Y*C_{xKrS~Vk#vg z5VaI#Yxw`S`JA7|t}|o#oiKK1k&>^#)XN4lT(e>zoVRo`X1YhJ}^DOuaQHz(R^Zt=~i@RUWxB7+J9L&`e{uf9x^b+_$bpVt9$_X&T z*p8ibJF5mPbXVK!ZNBS)-2pR6TcPPYoMx~rc`vPO5W%7VXq&;TFsmIYd3&E(QZuQV zoaQ{E^#2{)*37$)tHLw+`qOp|i$N8h2e7hA>;4a$Ba--BM!Vykf0g%+Nv9<$T$~pg z1of>B7GsSMt^%glTfXrp$bG-Ci8^qA60HHzCpUmuD&h)l5F^ecS2AVC_q$GI**z** zw4n5_Qg3s>EJTdFca^KOV(O8i4YCSRpzS5c(1?>8`oH+`dAfXP9oXe;Gqs}raTp*B zxWj+zA3khrYG~BJVXtee-+YogAGF)4&mx-mnfHRC#n{DSo1Y?$cul^?6#ZDda=g0b zBlpbA`jgPdL{u}U9?r>t#QWb17YAe)Tbt773>QAt9o_J1&>P)m8G9Q$RcAta{{8`s z&m)^5BS)(GG3j$7n#9E0E4zHjs@!P`QZk|ym$w(ct@gg}4}SG}#zsX#k-54C>GCSo zo%gflVPgaGcdbvSu14Ju$dubEmtIAQt}e`2xyLQHT?_{I7SF=km%T z6~Q*Z>W+h36%%LTqQHn-S$(;?4Gtko%H0$gUm5Xbwra~O;tGD@M6M`BetV_CtvrnZ zN<1*1Sy~1sUr*=uI_YP;WxoFS{`itWprhv2yP(?M#Ot=QF(}Elap^;&;QW_xCkZ}C zDIsQQe#7ULwG1!@Z3*bKASXu|-QSFt$jvW zh##)`{I8j+;IiixL5)b4Rha;Qm`>zsvaQp!v5XZp96@?jwJufZ;)U*)^mm0D98KgB z5){RJu<~Jxr6u36E3(saaSZC75(Yj@%@BCGGV(uA7`?stCQ`gzw2=P zDFEZNE%|j&JG-=cwTD@FNR1Yqqs(;#Va%&nHboWEq%(e!7jNhNPRLkIem-I6b%to{iSMQI*}&Wr@$Z{E|K7Qd8~^nM z<;T&GOVri-No%)jG#j2{`82MO`&Dt54?ozB1Vp2!A)ic)VyndxYBJMjtAURohGenw zfBWcp)oPym;}0IdpeJ@>SLu=_N`x7`4w2uTRVdy`!lckvE==8s!hl3UyuE1xzo|{_ zO9In4;(u(;&%pZ>BRoY~uGtwvk%7r(en6;!D8c`#Q_2WxWDFi!Sc_AM_93SbTOa%| zW@Oqgk06XQlw>|e;>oq9jr8x$!Z-{=w+3jhKV7RypMmflbbuV@vzaPHm0=k^`nqM# zQxna>;oXw7t_#aW-%w5>wPrUI^^lF10#d@`WB;p8)hzsglM-Q?0iU}V#dtBkfV0VF z2zW(jZU5&Ly^XHPyu&)lKGry%wgaBjiM@v{JJGzlv$l>+5B}4`;!p57qE}30!rzI> zu0vfDz{KmjQ4@N)f&YZ?yyEEB@EqU#FNs%wUHN%^K*JyFpwXZA<<1cE{m6H6qH{>5 zedyrfkt7E0g>nckrz%*p0$#PB-NM9o*}rnf#Hwaj($#RdtACD-;XU);!QquEs$$rX z`tV+*P@+86|9YZez3p{0;%P{_O{&7cC-YH@y09@Q9L#SKf3)*F0%1E^?2CGmv-9f_H&w#xc2>M_w?!E^3B7u$$mhJoVUr%yJBtk zXTOg3Q{eTk{_kLPc+9l$+B3J$Om8>8Br0&Ez5qJCI(THPPCc&0xiV_YjTNI_b{81D z+dA`$5AgxD(ii1T%Hkmh1A@|YogG^)YZrsr{d8n{Mp%CVez+Ol{q!0deVbMa9IQR+ z+DoRTg$hJqk%G0oAlhljoGH%Stu?!;E4?VyHbDTA`62*1pMd0-oFoW(SL_52WO#Pl zCjudD=ueIu^Er|(ET+jNq;MMRE7C{juPm>EKz8#Z6H{NXg&_i{%fNdE1H=94jlRNx zZ*L(#UhF1-to_lG!iK%b1G4MJt1m`(rdqzqyCAJT9B16*clyGP|C=;gUl6@xe2De; zZ7$G>L!c;_;CqE&u&puhLtb9K?5S>F>jrHocNmPSa}k%^r{j}BS}KE!I#U(@2}CFavy2 zq|FQe3uc+~%5mrgKFh{KaAZmK<>uONmgUa6tSk)}$E<&zzSq%epyx|a(&q!BB$jkO z8U$2ie$qMuuTR>ukYrY%PWvFoOmx3eGIh`oq=rp^vH5&*-<-7j!`7WO<#B+D@SGGG z+p!>NbHrzb5Bv&s&3{L&>Xp)Q-7-#0PU`4#V%bZe+HYTJs~6Ut+nDA@lNaNqp~?i0i()DPpY>Dp zsE>Da=N`x;7=!e}{jL#bq?O>9O&=`=4h$Cz?z>p5eOo zz?S_wY^p~YmQl*-PpqG#8|+PXYV!oN56Mz1J(voczew2&c{ri}=3nw3e5f66I-d27 zVwOUB1x~?)P<2wo@xIL}kY~=xRaaTR{AZ!g!blvJceLBuHZDxrw&Sstq2uMJ>0WpG zPK61P$sR||BYP%;>|ORc3_y6P7dXxbc1=ISN|=l!l=fn80)`P!(?RkTDF(tMr~h@O z)?B6&Sx&^-iP1;gr-v2Zn)XUU!No>npZnp+X}6V*gzm4-plxi}t*%87H&q9jdaV;z zuMx98y>%=m2gu(OyoIfB`P4mGoncq z{7izdfk0qBjE7ZWhcw!e=IMKt>XPR2{8wF!5yN3)$sSWS&vwtqW>1v!m1jLfM}>d? zugRo`2bMcV^wcXKW+LK@FW92S`?V75*^)x)1Z)74L}k+A_AnYr zhFsI|Yi^~HKkGkCRsskDEE_*Iz13~T z!za7*d&k>RBOO@(LLQ#KugaRv-pfZBlCchZyEs4h-OsC9!9Pdujwbt10Pty!&Bf(WjQ}WP*9ToHq}nV7wsDH>rWJ>k>*l?~MJbQn zd)6I|-LHmI48n&5b|)QAo<@m{U+-r2rN-_!aN z;Gz@|aXwFgTL2}HE~8_5OP|i#b$N~6E?@|;aeN9TR#NL&adW`Gx?0w_6N)wx!%W6qBZjQ0;64foPZvzl#}SAzUW-uveuCCuQJ@;?36#>Nh- z0W~AB^R+w&u>=h8)wlVmrX_q3XfL_vE97*u(ZpV`(+pE{eV+WQc~4IEWv6}1ilu+n ziB%HsMGkd29bZVtf>3X2(~aqCk4>H~AXROPf*xctTC>j+&;_7XkEIm29?Jhi=u zdL#^POF}(Lga|-{6!1MeesWfQ8c*JpRFOS*Y_|f~?}ypk_(q?BC9&bx25po+3oqRu zA}rfOH%4F_72tUE5m_B;F=+m33=jPhPLKEi_VRO18WI)*kc`6Qb;eepaeYbQ}N?=B$?Kda*P|1`vY3X0L z)R49=gXQ+7xwz6^eARXS@+%?3bBv?Jx1(=;t&I-`C2C7#?5@ug9Z}Fx9-9-z2+Bh7 zu^GQ(fF-rk)+py3f}>SOyjrqxx@^<7ab_=NLlL3C&>i{C92jBY#Q02x^=5o;$;vJ%{T2thB&?H{?{+OgO)Yq5N-2xQvyKXbYsiYW+K9Yuhz>kq z1Z%bu7Ad@mParn*Gk}96_4)P$Y={hE)A2tA1bU&|yB-#a5&AK7EXZdSU}NrF4fXMG z7{9#%LZ#`7DN$gvAnP+8k(!3B<1~rdiw~y`q=!iv1k(n@EVlMQf=dpG>qk<*{?kz| z^X;`_hDHP7_w#La$JlQNNw!PznZr5>D%d4B3_wCHII%lfEAuDDNi4O?k5UZA^?S1M zK&->YpY8M?Rd&1~u_*VGfB`pH8lLEpeVOovmeRm~9>R1##z6S=UE zI>C_xuH*o#V&f|UfAjwk_0@4zZ_U?-kOpa_5h;<74(SHzZV)7;q`Nx>q(MTuL%Ng@ zi9>fvw@4nEcjNOszxV!q@BMK0clOMhwbslA+MyU&a~sw7xZUQT|G=eATV%SA2<7wH zEn!(wj50OYiSZ6wUFy}6FUlDHILWE#9FtlhUY^#50EPyOfhL{i@lEO9oo-}DAt81= z1Fi4_m_`i_S1`)zyp8(eZ8THA4Son%%YpZ}MQChtmcb~MKuZvGGtYk#fKSBOzTDPX zRAl4xIH;n_m-gc|EAuZ!IFb;t>QA5KJbh(VeMg4#akW#M+xAwf%sFJ3ZM+fubf5#a zZa^y=fG+&Lu>EO3$6-IoxCW3CFL~(-1CUtKuyY+WlJEn+>Xz&Tw7OwRS;jysoUHJOhV&rvvd8R*MfNl+%dTIPvS2x{zSmN4L->w0F#26L&5 z6wsoT_oLmp=?dO8esl^dG)aMqTM|VKF~ll3IEfpIZKQPgWRhnt24>>Zrw`;$U=%}c zxdwQM%09NsZ_F}Cay*}+V#HgK(ocu`zBwA_4^xkGEHZChs!Y53SkL>t(E-6jRQ4yG z16S(_hpZ-*rK^TrAhiC1KcugbIDi?JSKjc%HEuS>3$U`YO{B(i6&_)PrGPP{CaW~W z%l$W6A&?)F(TN#HzWCMquVsDlePg5pooYIZIBG#1>?qGAj(EwO zNk-XAK1YMi7)|%ab*m*oVKpzY{lyVT&mtuS;w4lQ#)Q3by77P|x}v!Fy#p#6cIWLz zH$Hb+FjzX|QSh2Jcw?BZb7gk@R1$6Um)w!8CA zyhG!9#%$y?l5BiUN}aWKaYQi22-w({ujwVlk`w>UlPrXG6s27KUe0|^W437rQ!I+g z!u|gJm-cX9Bq5g@Y)hzvBk=VFxLFai1Ew)CEu3!#OII<29r-T+uRUCAtv*?wTbr9W z3}yTc0;eept6nP+_LY_H5u?3-4@tTFrHHsgJ(=e9I9uH%3 zdXf!=gccBZkF&I=V3u}FSr4Hq1FwOHL$L1P^8BP9&^}g;3uzsnKEZ?8Qe_$6tNyTK zy%B+z?}OOpo;}X&(s!PgrQc&}pm9XusLFtMaDqfoUh;oU>BILCZo2BOnY%|m8rg6C z0K8iUe-|%s>`q#U0aKzeB`rrc#{dt8mjH*D*#G(ySSAB5lp>VC@FsbON*q4(ge`p9F4DU7X5&lI;&V$IVkol})v>)_|KaZbtft0L zAFBFR)jAXF&HXw(<(QZTzy&=Wt!#)A__|J3LQRctWpwOPt|ieP?~&m5B(p!7Mm4r& zNsY{p6n)vp^F56_OkV}EdtBR^YHXtPdv;*UG+1c(VI&LtoskyBN|n|ByMChRH7U_{ zq(X|hYPv<%9HjG@Woo8|OFeGoI*I<+tMiKU!nq#20?6T;`>~bG{VdnO{XR}OW`xp9 z^OUsB2Yeuq=o_(P8SvVg?B*TzU>d7mK%w%30WY{a?BI&vp&|MAl`9E=RL|c=&z0*B zxmg)&Yx|5lKM(~zD>C<~N}{DrBbR&<4j!lw0b_?q*&$d<;JD&|VRg<%afGdN-tI4!$+EaZ3I%GyB9s=YHhZRf#B&qYp9}O<)%l#i+%;?SPDv zU?2?jN7+c#WMmvDn0r4R`dSXGznILQSbW}&`>%;?k$z|M6701r551Rwa+A^*hbR9O zj!Fe=ndTR;3}r<4gaOE;NHA{dnrC2A6A%@O+G#8)8HsD}yO|hejO^4rNXEdX8HH~@ zX4SQ2_%Q3?Zch@QiYLI<^&ccNk2=Fa?^v6No(I~)EOO@A#v8kX1s5I!Q0Zj{PM8BF z#KMo2_a+ZuH+EOB7f&g_do67{-QPbNNGvh#DQ-KS&gdC}=>z>sD!1o~uVqx6N@|LS zayhdUU$lOn8uI+AYh`1FJ5CskPohJ(KI}U(-GJ#cvN_u4?)hJR8jIt=M@DEak1!#j z`jmx+CX@H>h>x-gdFgE>liWw(EX%kT%$|X@Pbs|CJDriBwV;1qv4(G89euFJT%h{6 zn{4fo*|x6Qa{>n8)30Am>)PsYdynie;BW#|4AQemWTmOQpl-(b-xQ&bb~A|{yB-_v zSKkz=GqGe=wPl8g^7a4qb+5k%?>tjHAj-B>KR|@8E_scPEsFJ>EQAAduzvccBwI#1 z7pf?foF>4Sd4K{WAS4jr9^vrsS@! z4LJoR6aZ|8>JCv$9P-+@B8fsr>hTpY!!LII{6xlJ2pxKTm|)0d>>@rnQ?egm{KgI+ zvWFXvPDBVVkWK#yPg>;jjSbf97j;gj#SAk_gs6%A`R)eq{{u*aC#93knig3MH_-lR z1>$GA#M>*seUE&<4gQVKM5o zjKsEu&DYUt91x}g`aY;zEz^S4JxC*yIVVGjRs8OzD&JKh6ltd4dg>FupY-!bs%U~Agx z=S0FOSaroMW_JU17rA2{BjRS`pq5{+ba|7h1U(uI0Gyk{g;_4DM z`~~@oj;rOc*61SmEPDE1>U%PWC7_yRVC7XfQ-o8A{G+XhVC|%-_nV{~A)TYT=|v^* z12LXTj*NcFy)L2I=@_G!pQUquWRxW-Pjb`*1tSMRlL^%Nh*CNG;l3{**4;05@FGW= zKYjWelj8UJ^!UalJ@>65b60!d){7VPc2{m4icqb(x2es}6lV3zK)T*O%jy|2(}%Jg z2P(fTnWP5x(p+FKW%vnR~G_a`0kw!b4<{gNSqN9lRa{Eh#EnspD_0#bZf`@qa9RKG9=!hD4a_nk& z(D=KIA!y>=;7g}D(C96-2Ssi>cKq#n>#?hK#_#r7M|V!y^5y9&QhD#j&zY#LBBXf5 z;jiVchnLI+YM-`>JlKk#$r|>2MRuJ49Rw2NY&Z(1(+k|)aSW!Y{CY7EM#JY;Zhd8d zi`OVYRlk2YSn_Zt-S%O<&924{3PBeML?jBxmyy(eAE8Rk_pw~daq(Ae=1*4>X4~-@ zXQu@x-LiUn#mvG#f-&ihjnL+Ps|*jVt z{!Jnf9mT(g9UbXehu^PxQS9#m2ty}#nTdFBsVRqU&5<}pI6Ajs#lDvP+viDOXAiHm zgqMQ@oVC1;xF&}Pb9s3+d34jZIAtE}DdzKPo_Hs|$SS(s^E!)E%}R7ccoY`MXXb{4 zeD}5aQbstxZf04ir-#S-Y0KN?$*Rrd{Wz(qG9~Qn(ul zW7;i5B9!2<5EZqkp2}q|&BoBk@iJf_F6e2{b8VmU36KWR;Y+?#Eom<4=vX6AZKErZ z6X53ikxw4WVHn~~2&*z_xNshuYg~D`Yw>VK>L;!AkV5}!yW*gY|NP`x)-^CTZ&!tV z6-U01TVNd8=T7N9zaT;tg9IIKKXQ$~xAQLJd4Y?d~cpbLROl$)LTd!3DI z+Y3U3PQM4C*uV`&ARY&b6!rC`*6%tt|CN8D{KULv7*Qq9zVk2I-2v2T|2}%Adr5iI zeZ~c~H}`i8LE4QMf7;mt9OR6yiU9@QKg6JovrK0pXrW1!C(pBV;I9;E2Qal!7O2P`NvK4saj zziXI29ga7CZ^EwauHIzNDCl`bD(U_?+NH@ZY9msUDMf-*$msac5WkeEbby6*N|_2q>Oj|E?7E{NvZD>Zqr7B(*d9)hKU;*rz(5abP!EWJJI#vg58xX<+$J z*q;Ua{`LC84a-ERs7IQDFfF|q13^~dwebD$kT@!@mTj;ysy z(!zhOf1F5E5|HvcKJUznO4&-S_u3|JoB#(OjZnc>m$7xE8LCp?VPg{5Ps3R?^I`6kts_Anwz8NRWk*TO^s0!iJL+uH z{#MZEbWY8A!^&{_VEdqA~j-4mdA&^ zy%Q2o1sn4kgZj$J@(mSK$uiTZxot@GmwK)cZdh$QaoXda z7_(SONa$C~I0p3<_SuZYs2v7Mp$L!CiT=K2%^qyWQ4KD29j_H_R($7TnU z%Jsj}7nA!zJXhcq#ni(PKJ#Z2sbtzaA^gh^9fTy2P&9QKvOjyz5j3nSLory#DZMwX)Q;8<#J)9T z387{kiiuV18R3F#j))6EOE8-gc-kQ|jFdI7>G)Z`lHK;y&398vok}x4&RN z;T&vGKl@Xv(=3H4SZ}o#<@0=JhcEWL4SSo6-}QNCcYtQ@D|`uTkasK3)=NK4-VW>w zo2HN6ZfsM$c&hnjl2(wed`q4a$xE_*Q0sie#!Br0!*&a1#-tS<#D3jJ%-w$%)UL;P zZ_qd>kd!`EyFk9-Y=V32nVvzia}h5(b;u-zSBjS&5$^jiW<;AkGe4qM`^z`*Q);Zi zoqdGTS`VulGrEEK8#A zV8F`kzD~31KVdr3#x5JsN}yr4LPiz5PL?g=w9>+rMATY;HWSG3w~(LP#buhJcn{0| z$CFaE2#M(3w;^6a&d5vCodf~Q##~8-mjjFwj8K-8!ST0*T@~;Z%qZ{>1H-935cBYG zken1>>C%>Ug0?4pkrL5HTJpbVs!Tlo5N&HT3jgi6&pUi5V)aS8U$MW(Obp(7bJS#@ zg$iBDXmtoA_@1YG+I1k%dh`^}*Mhr+wDdmhhjQ5-H;s1+f_Srj?0cQNn{#C+^sD_> zMzpa`#1BiqsC|aCGYzyPuYNiJ20=ZH9KFED> zR80>LfB&wY@g`zwarVY%KlUTW_rX0Gz2?V5EM$F~o{_$zb<|E2zy`Y=1@N#-{Q;rPN>uFk@hHwB!g6>SKb zzOJ5rbo#cp&eX_N*Xg`~5>wyW8NJaJ$=$BjgMEv81k@`F+3(8m8Y(SRQHBOBCNxOx zey6n*%254=hjvUL;+taY>7L(AYv~(QZ_63iDcfo$ft<#q%xY>oOcR#ct1q*Hua&QS zzQ-^^c??s?6o)XI_=xVds=Uh!7e;56M2+0fv?`7TRW@2Z6#A`_XUp4W`i3=2R5=pT zb(Zxi1$pvxIZ}xe(sOa?ao|l&;x9>*Cb@N3yVpZ3pED&Jykk>)1}=hJ5d#`6E?c3k z@76u?uPAH0kZe;eEvuLDIoV$XyUP{g`l13HMkNSYNoF>k`4#F|-ymH(h=3=KXw1wI z;c_B1T|Q5GACEIlT(}$Nbl!z+@6;JxQn%k75zU@qF4=h=H2MWm++M!R6hQi6QcE)^ z2bGY>Gmf=}4)2#5&$N1L+}Xq_`QX;4tt8dR&xVczDVpvO<3h6o?Q0l^tm)gdwZ3?>HW zk8ck*d?0kaK?->2;-r$WxHAZl6WMX;ZC#Tvgy1$oA zdvt*FgB9C}C$q()Ju{eSCQEdy%H1M7nVHeLy)l=uHk9kJqQg~L!s;XTiq4xaOYw1- zF`mN9sG{K{{U~5%=bPq{p{rpBTtVL zc&P9+Q|(OT$IfL!Bm+GBLvbB`OMsOdXQ-{XK5evG;exXPStj zQ~|5(1r)Jg@%mz4RPPJw^_Xz-xdarxIQYUwLPAm|^a-PP*H%ZXNrU=}2zKTAmj2mg zm0uvJt(=?p^-t~!voA4?H5AS<)9VGv)5QJZej^PI?rHG?#I*Yu96m6=JNq@_^Ikza z9-qBg`kj7yim%D$POL@kP58YL+TZ1(Z6BoYX(oDq0gU>kWskP-{0vrVCvGoEt}RR& zp-o(BEfEjBGlzZm-@8c~i&2ngx9Zz@^=HcDy!PoIlKei3E5znzeyH&N=)K_Cnbw!@ zh*ueZQ4de(@M-OfwV9Z5jgfHTm2()IL`%7ZW4|JAI#3}hGpbuH&mIY1mlgW`ilkMo z_pw};%(Q$G9Jq(95MPW0c>=6C9*A)M=Pm^dpJjSd8$8x#Kc1NEwgpPOd>b{$=6PSQ zl~!-n_~zGknY4oo-ROKEmH+DFot>xmjllAI&)SRkGTk6Nfl6+}ncvFXb#-q90E7YM zo6U2Fv+V3k46N7wvLz+>$Pnd9Go+;S6ymC9wO;R$eXcL*6|#rCD~xPA-s=%2nrJ;! zn#Xrv{=BV(HzVS$Sv+9j;ca;0F4$u+*{hl$(M>O0*=LDrBbD6$KJ^>NY-_>Ehc4UL zQ+LNb_(a#mXTnv#rk543$1S9H7g*cGguPD5PA}RiVjqiE!5i3Os4-D>;TWue`tAE~ zwVJ0YG+cNDEHbV;-wm&~>WVDcO84`qZ@O125r|laJEFg$6o{yDd^W{@&QQ+0Qv^V& zGVG}?6C=%3i>edhppccTO#};T$cDr3X^?Jm3M8n1e%l-Tvifem)#nX-Yixmgw4tz9 zsHW-x-S!iBI7C87sAP{JdAQ{q}iN3D2V8UkjqVV^YS%wyWtFR@m^!kP5$( z>G=1MG`<0Ks{{wVQKg5gh>;w*I<%=`e?$nx7{44ZVan19Yt&xg#EN9GfdCmv=KZZV zvjz0{esH~w&1$soDm)=di;}|aa>i%B-{Nm}C*%6kb360@}WiR%N^hgH5RU-3hkaU&~VS`@aCkwMFt7;2vx0pwEGB{AAAH|JA=+{Q*X- zNPk7@BO$@bKB@Gg`!19>Rw(W|Ow_RaF#1-kF7|hALypn;P?g+VS=AVk?ek3mKPQvK`;k#h|>MPtUFs{(|x-+fQlb5esrXM;Pp zwkR-Rn_!mqxlN3_wfT?Bg#x#=GtX$La#o(~j|@Dq13(dIm2zp7RZE5_R}jmE4skI|txHT= z24mjsbSybvRxWVeMHl|`+_UCcMyDgxNZ2Aw{?I`g$Pk~=U0#zB5(o$W&;*)XH48ZO zC?|Yt@hQ$~iniNOT{Zj=+=yor+;J3bVQua>HFj+&CTx#2fbEXL%I54v6NKx1qbWla zKy?P1xa_#ea5>2mvSPTgXrTF-TnIR(8l@Lyx?Q_ldRxb}(f}}0mXOau;>Pjsn?Ct7 zeno~zY5=;$`=-_0_Aijz1NLaS!gMtnpUYAcZ`8Zbom>fYKuW0+-z828%(hA{om&Q4 zY}cT2%RLjFE58<@m!hP}8+;XMkec=tox|zuw7)BH)eRE{@OMr;?4Huv zUZEc^J5`zrW5KV*g$n|@Tj@UwN+SX{2<`UwvSRh-3~-IM zrOc)?%wBRqZf*D6&&Q{?^XOy7*YK&0$oGM$ zzak&yY6=@xR$2&=6wHi#$xTv^)X4~dtYJ|dZ-kWkBu_*TkU$`4V;=PsOXAen zA})X)DZS8PhQeLPNDC?W-G&+E{IJ!-@kXy+n9@4T2QbUeMZ^BKt=3B|PFm4Wmts7imIzA02(_w;=Ebz23Yll&Lqbl7_+j!$7&AAd_T3 zl7%X(gHBscVo7Rt+FH}9VIkUU*T(GAC4Vb+#jeo%I(C*}cx@W4I=Krowr41y5D-4L zL&53)KWIUkR4_;{n6QuL_%LzknmE||yom&?HbXIBr7)1f279BppM(EUV_JR1ANY?~ z-52dV|E3%j2;XSsh*R!YKJE8KN$X-V`N_?tm5B6`**CmvQ5%-uT0W z>FLoxIe2${VB4v5f%xE%R&i6#m;#UHBvwKGbu$**F}d@@(!0Mm!jn7AI8*6AHa<;a z6kg(%m?xQkHB~7|t2!1>3YUYXlP?TD72d;>J8QBb72)b#myv+K+ui-C+EP!20$;aB zCXw>WCi7o3hUGDQ!;cz6uWIkAoUo}=G5t#U;|avSv}8Kp2QqzoevSgKJuk-|LG^6t zPdxcqpV2M6;N@}m#&K$0q^Y|T5teiOeTOc3-RV%{Tl{Fg-Nvyc5ye)g?(EitS^a?# z&4Kk(0KgI^JJF|1*92INRhyF$11!dejYkMwX8ac}dx`0a3RBAy0vVykh??4F>5>6L zO}jdhhJLu1fD?Ur{Q(8899bhh%DD;i)-j^DyKB+=F!B7gUPX15_#WQ0W3vD}YL2Sr zPd9vsK1H}3%`8ij*V%8u$-SpkP5a?hmE$9Hbe8%mF{MGnMJfq65Z?!<&bM*G*QAr$X=glUiQ{GU7mzZ0&JjG=LYhQ$qm zyygNh8vDD$@ZFlgDfdzH4dm{a(l-F9(N@x5v_45Y&?7^td~$IO{j-6`9Qa|j=c0S| zySY+s2or~>p@F3fuTNXqU#TNjgn&62nuehE_MYZR0&NaS)zjdA?UfV@QCK1##5qjz zd4D+*(H$%die!*F4AlY=zb)kht{rKjJbF!>M9 z+GJpZ5`l-OQbO@Pea4pntwg_M__ky{TjJb=irOS$r-8)iU57!!4^2i}XCCG6YFC#L z6Myn!L%BVTK2W-Fep6{5EW7u7S`XrKnM&o?uMsKte)fQ2E+yY2diUN2M z%AC2r<0yS;`@Z%`5%*G>yVmO-^4u?F`Cm|>@CcM`M1sX3RT)@^D_?J7K5xogDMLRIfFTu+Pz2_+~3H>ALN3E=(#A$ z2der#^!mG5!N&hfPG64&{U>^5Xc9TW4m4lS3yeDMB|DyE`rybbl0BSY_`(sT$5f*{ zd3(Yh2r(Ab)xsnP;zlV)S#>qOBzB~+K}Fig-_SW2_>|xmvsn#-uN(6RY0r8u=SM@u z^6)f8w1j?h>W>8gX*x$#JM-{R6NN$hE^GuM4Q&(7hqXXBCbPeEJy6 zR~0>Yk4Z>ksV~+{>=b(P0j;2xSeJnDmGAnoNB_D;_K@W?%*?|K%6XHQ!shp7^rA#P-rA9V@Yo-?P@a$3~FD@Yc-Qnc*I%Mh(M zZ!fnQNKZpcQ ztyy+KLCWDl32XHX-+A}K<^yvnXNKgPp!}`5ka<=fy3{6qe-b9fkK3n!*@r+FQkX1W zrs&Ex1j;CKwGotSDXh-pbCfORNEa+uoA8(MX|c-H$T7xW`64 zY+Znt5B+z%QSMtgLs9IUT8p0mnvvw|I`Ncpbwias(d=Bu8Au};p-JfVrApS*-3V2g zgYg-!2Wv;g`%ToBFf?Toer>K{%O^(CCv#cxWI$C746;_&yFY5jqCo}#pVhnmvCtOF zcK2)C;X>GN!iXy%QH*q6Fh=OOmboK>9+L~toAM>4CMJJWf1``cs5RxOH0MAWFx{IIBpQ!*iHXdXRulAh~r zf{esg#$~JpV}rJam3jQ=!6}JwJZzKa=iFJ@lKYI-uSNK4M9*N2f!sClTeV_+b~^5y z_xjd7SF-vdc8JL|n&4%j4jR0RQxe7FZO@0zZiCyggXDlmzTWRQK@StxWm}WGeeH*) z?BO=9g3=f=Bu;tevaxZKNRwEd{M-ht>)uYKH3>NXTClG{p3zZ%b(NR@G>(Jg>w@IulM`d2 zUSW+B%ZCeTz84Nglw-oH0%IA;$>X>T-5GCin2N)fD(^L}0DceOv1?eF3oI_W!;h?$k%B)QTMO;d`!& zc8zxQ75=U)LqpF|jQQjYbKCMh`2-!c-G5P>=bJ3zkCQQd^M6dk3v>yPpGXDmK4Z4; z$7XTe*kmkSKK;&=kbW-G70m^WWlf$0WE{hGnnXTORsRQN8Ih{!lU845t?o8Yu-1AF zH_m~<)wth*xl_B|xRt-qd1W9Fq?v`W04j(YM?6aV*-u`;C@m)R=vebj#oBcwifS7TUjP29Q|9Jr%W?h;MBJ(~m4FZnGrAF|y z>@7aPRz8Uebr+`}Y@!OQizkO_{ozs*sZiw6?t|0yirWh$0T&*mgh-iTtmY8@cs-aI zDuO=topRKDt0zi4%xRHOp{}x6mt~G4Z2t`XBt`BQh3p#!|BA+f9gQ0qw90G&uK7u*jM8?EYR^W)NwzV{!@ zxTjZ^pB3Zc#^fRm*qcYRl(3Mu?nrce#Dg|Xb6|{|=uSA9#UR^>NJu2Ashx%SU8S5g z3qNpp-X}eZdmTEQ@i`ACGb5us58E&tdA##;yRGA<-F|xC6ah&_rDc!4!*55i3pgUh zC{c3Iqc7Rh?-yvuH9inJ;TlAbuqz4BQAZY<(rnFEvGh}yr2Wc_fKo?Fv2~wX(H$O8 zC>s^bnb#5f_U@*vJhK>&UHDB<_QSK5upj!@vl`xr`Dh<-CEuKim5y5Lgh8VJq4I

    pTDq;1n^D{&4sF{V_G)`DC6X33RwH(Wai7aVDH>}MpKt_< zaNwLDP3yCy{Gq=?SacNrTu~Fr9VI}>@V7jH^{(UoSG>5?Y(d{g^?-1cG;-r&){qLp zEbYpG_=cQp!mp?rwwc*q%C3&FB_b9x(UH&i0RU>Fh-GhU(YdY7q)kDu+k||Vc-ldz z1eiFq-!#TdS&D3=O&#E^*Y(N0z8YO6>NFalPrfPglQ2nMLTnU)up!^|%i#hHqhfIQ zs4b-qgFCKt*DcI0`@UnY@qRaqb8$wx+o!&QpEknXcVb|(XR9wfd>4Jmg88Vd>55gH{h5p|<$li>Ra&Kt z4VKOWigV#@=G(hgyQ&`}6E*#)bcan#6q%V2AhkfZE^~0znDDzvaz^^xb}C$%eN>lnoB>WJR2?m?z9+(ebUC%YL^dHQFR(2rVl=azc@jw|m? z1TIAjax8fNh~g_D$m=p~o3vfknExpNl0(ud;Y5g@f6k%~_F0=ZU!Jlx;CFsax~e8yyuDQM}Wq#7osj0C)0dRCHrkR6HN9G{l z*Ao*<7e4auGj*EKPiiv7GwyD8>A5X>lK+K=*AC>NXQe`ETudDB(&TeCX03nX@?dDg z2`JXCv3hr5U_EMZXxfJm=gV>6rq7|(r+-Zd2u|xsCpVH6J0}J5jaWjz23^qf%$tt~ zO{*y=lj8vQscIGytvsV=8)Uh_#Eg+im_+3&3-))ZF3v$xt~}*%LV-{HDaIK~B{Frp zVe}9p1l#tL;)vg?cy>`id5;}{?2mR$yoU!@FDEoCmr!Zi$Vjuh)WftnGmvp<1SCBP z3Fb%NjSRmqk}~N~DJQJ9WL*CU%;A4AO|&WH^lCTE%v4r8P8$DXtH6ASLin0Cd{eOM zS&pvLi(K8h&DBHZOwNJOHi~fo}!^ z;fbe-2S2gUcDd1>5}YVe(%CjCnlTi2I94^t1L9qsnUwX}pM1Iu!(n{{9iow<|@0Gb8WN5j1Bu zLqn5OIRad8PeY|CCyy9cRnL6-h z%Ge+kZs=c4rMFWk9<_2szW87(W8F~g(DWfV{Ne@fW=%$Z0%;Ub0^2WYuvJQ$sj{_v zieg-z$Qc(^R$_@l{L`yF3H&5g7$__>t8C%nU;NI&Z|C85tJx`bO?=Q&XSYLeFx3os1LV+kNgF0oXZ~>E|d|pLLKr_wJ+9VU1H@bVw z2Ktj$w=3^+`Q(%*+DbQDiog-VI8JO0m=TdyAqDmVorOn>&bj>^Lf!U7&WaM)#40T< z?D;9Q;VkLaD~YZ*#|WufNVe-uYK)~u$z#tM5s;c_>Fe^YJNs?KZfz-l+0@cXSqr8P z_eyDv2cBkj<$N5d#iSP9OhzPkw&vMHiX`*|jI}xFz`QzM#Q& zJ#HG*82bYK(2g2w}p^75NG2-`qMZug!r5b z`zGI?^b6-m3;7C@3%Y;uwRiq3pl`*h2jHKs+~>|NtZVc7BC2=<>z+;3?4cTxnaY#u zc-#y%)zCHXW5gqMZnY`fy=CwvbxPjBS8I+);eKgmOc>lujlp?(VfSt#jMF`7>tA7V zZ#Rrutb1*qW8sb3d#S&;Nq|U(wapv>g(Q{Il+10rOtb^Xq0daqBkJYtnhrj|+9#1j z$zd)Q`gnAErVoXEO(?)G|GuqZWRRbnlpa56BhZ`~O|>KcJ&w^{YjP@=`c?6j@8H-T z<3i*calPxEogYCcfB63+QBqU?Q#52_oAOHfmAFY;x^nz#Eb&D_iWt<4qJxCwab?cZ^{k?6cOd#r~W-EPMN@<;ndgZUOU?`x!B>+ij?08atAURZBv&8Zy5q{o5O0bo7k&9q6QVf z8P`^XvXcOoA!eI4YlS5*S&$X)f7kme(aM%Uv``2x3Mg9aJ8@i(Xkx3mRuw9rgmfDy zNSyIf!&_diNG2Tmosf;v zfSNkbY2s)U_=Cg(2REsCl9P~LGsy$s4;fAI^SQCT9)8POYHe!ymhxXTD3ZNVthhh# zD}!OB#7~lyD5%yIC+6!DmEI$Kj*(?-G85lo;WVNAZ_3Rz3*>V;D^X|e38BSex8 z1unrs4Tbu^jpl)TRU0(+!)5O8HW_>E6x~0a=y0DKsy~p29UH#JopF(cGUxuC64qPw zYF?5k>)%%>C|eE=gya9_7q{$Y?+0k^z^^uf?xgP(zDfk2CkOP4cVDH=r5}Y+>p;# z>*7~dq9F*+o|XPlm(FSpI8dY!hl7ZGe9RABAF9-EZ$Q}}i(64Lx~^DhDPVVcE|^75 z+bGD!rIFDwlps`U6{;J=D+)J2!7-cPf?2`HbxOSKa4i4#)sqLIB&fQNUf^S0OFcG7 zi_ViWOQebKZ~hL-x$zMp-NHtx6NxAM`YGY@g=yw0^BUHJRPp ztPC}pLhya?lK86TtBWyg__tlXSVI&f?&LK1rrgK;eJP@oyxh*m7 z-o!+xknf=|(f?GrKg1M;twPnvKMaoMRIwRqJe%k5fHkztunP#EMuL3L7RBLm*k9G~ z1{zaQ_#p!>$5;$iYU;^$O3Gu{H?D1;KT@+(BfiN(4faO;ofCUcl}C?QcR@es#5)U7 zCge^^-{zX*)=7R<*`f6c1c9o_b#mu+o!C@kh@>j8!G090Zg?bl?kfXCU47hw=uZLl zUu@S6&VR6X74Zq(UgmtKu%)$C=jzD$J>ed?x3HNRF*0OQ(C=lE)`w-#{KA&Jc!4|a zhe`t>NSgBhQ9Z&D^_%%hxH_LrNJ}RWIf&S^voDV1lS`^#%j2}g$6)z*jj(Hal z+d!J9k0qCOi0bhc^7I&oI=_$oM?p4Z4f9)DemCJV*W50hn7hasIE3QXNN5O;{7Q;E z`@Si;`B`^vejx&AALg2>vQxI<2@-x@dm)i{=|>BVaUExRof>0%Tt9IA!g|@aAjZs| zN5bJqw}yC5;|hL+vcofU?>;zeSMPD-n?aqo+Zk2`Rd)M~o~yh+W$}bHz?m;>u104} z{+F384_{XI#l_r7*VSwlmB(U1BDW{JQXEV}00S(JWud4gL zZgg)Yi_g^~3E8kTIT;Me(5ITsD?7BBp1aV-iIV%EY3|nYYxRU0cmo}x9xm>V#^jz5 zWDAl>$5FhIiu1m`j}&fgtUF6W1Tu$1H6-V3+o<(=Aev))Wz6R0lGDB^_2eW5HK)FK z-20qjLv5vzZM~IUvVVPzH6Aqjks=|Fjef{ds!IEe>1=9k@wmLihO3uDV6v6#^GGU7 z;+3neGTH@l#rZauzLw7Ir>@ElgE#%__R@|{I9B*?^dCAZP0ZrrSABt?=_^3?r)y9M z{l|POAug61IaS^r2#Z7BN4Bg3UuV3xLq^7$rMR;wak#C(4q}vS#!(xeI!G8VDGXR{+{hH^;Vr0ZGhYg}0)c$jcqG)Adj|ZZjvdH+b{l;&Ks8qP=^#qFgowPr3hPJ= zLtJ(TTD!Mt!GJCu7tH3cz|X^0-s}P6iGMj$mN|!}M_+8#P(%MZ_l5iR?0QiY!!n8dt=KMu+Yx zE|E2O{Nv4|Q+nWDP!km@;p~yOBb; zG3Uvnug5Xx%e9BxKhw}e@Bi6qm%TgmdWXZhH8U}ZFM=)4XX(#aLB^;;*cF0E-Gxno@m@KC-M=?(y^W(xnlYc23cT zjr*?Kp>67(%kjxV6EpyV@(sz7ZtqvX<0|D_q-_9GJCUmP@ zyPF%TSSs|Z+>X;Qa*CV5T$4Q19=#oH6iZ4MlJ{RVt}RdkuKwXb&PW-N=Z6>x=~V)$ zQ@WvjCssT_Fc9vLVFxtlt4}oX}0tIPxqf*0b%^ObrLuGBHGPWqh0KNVL?t@RBn zEBgv+f|<~dy37l@!a|2}I1!JL9~g8hk%6v9C7=>4dKp(cMKNGMyq{>88V4g8N+~D5%^jfR57Vv< z7S2<8cLvS@=uq=)VV@h&-H(>CMQZA?ov9S~Bz50cKex+f?#643eFKcq10C*8RhR;( zo{0be$vtOxdvCKxMin*~^&0}g!D-&#!$w5Mp^fSroTQshBI;c3oj$l~HUbNYj3j2}{QFtqr)YhS`%0bo(m^syayV@W+7bUpxmZFguh z1%4vFx%O2j!MgLbia5fSv)JKO^QW^XKi4nZ7EjzVY_QO5D5QG9epB+D!yV<72iYVc zx<`iDOiAdr$G}a^E6Ro5ErJ?%`Fp0OW@6!rbdj15r6T^fw*tu$5ue*kic<|sMl+4d z?p&W9&R4czPOpb?2@9zv8~Xr{J)+dqj2k8f`x19{pXqGVf2qLecCBvVhg-5csGFZe zVDTNS_rv|)=SVE#Xbn~zT7 zs&)O~wgECdM&`RGFxH^+6BloKsN)$P<%%;m40zuG|O-fEpl_}T(wnnr1_74k?LyBjk&NpEVpQmTm zB;k-r{c|?<*T1wm>`W9CIxidfW&Xkb_sDT}{oEgFLHp$}V{Cm}Hd!q&DZX-=c_(;WC__=U*|#uZ+s7ZQ8z&P61K6ySux)J0&ktI;5mq zx?8#%q`O4AySt@J;M;h=&$pJ#pDx(WIWtGh%+5t)eDALKAJ9hW8p>&M+~_=TYx=Ny zEM*>O;A+2hlyqdBJ^jgSS$s*Ag2E&RCG_vA2)Zj`)XUeSL7TM0#(#V+uU-O%(Z2co z*6WWFzp*RMM9Pzf3gFjGu}ubYQq4FZ2X2Yqi2rUg_%3eoHk{e{`1D#ukU7mu>6kS>bbUMinLcfy?d##Y-776_H`0A`C8+%SI)rrdD!{8qxK^is-ulE9 z)znN}ve?%HWG9lPXsIp??FSY$N~1dc&EPfbWB`z$ce(Q=rKWr0q*Kmze1t z=~2YVud{-z8&!kS@JfMd+v>R)D6QmM89)T>cYbXxUw_zI~Qb=Z@aDbkh!qv*N&D-fuN#`lN-CB26G-;;4+&O_kiUnB~3;I%?e= z21f#ApDL=wee+99vysNTg#4;jQ5W1gXmG}?KNT=ZGpa>anf^tZp4Gxy)n^r4*JJ?d zYSGX@A33*+UhxrZc!UJF91QWC2aD^Y>}=j=lIh#@w7*hc>#O$+QH85PYR$&u+jfk+ zfC4KeH%NVZmQF^NEQg;RRB%Me&dJHX(Ff)05~MRDcoj-s?t1r@fEpfh@OjHrN^n6! zvUD2XbRw%PS|Ys$ETl&tOJ+{q92Ymm>y&Mbbx<1WX>VC(oukT+mR(UnzQnfI*3HmM z%7n4)niaq|-e-fX<1fApDdjYF0+iE1K2MAEKAn6%Xp{s@-7L)COq;T$8Bzxnwu;j+ z*Y4BaXh5+y8c+!#d%mItS(tLDFQwg;_S2hh3J_ZSOGxnoAm+XrWBcjBMnKq1EVFM* zpl;Aeqf-NN)EB4mKTNAPe*AE@Xt5U8R_y6-olp=~>r>3~DMcghd~@P#^B)$`b1{P1 z?CZYG%eYSK6aXxkQL^plvsFl}6|zIqK7v4M>8%RStmA(#2gWz|3)iXJJM}ds-SQZr zK=z4qvuWbOY;trvZF0?R<>{w~V5N#h8`|`}M0UM;PGyXsuUUYN1E1Fw$h?}F)79em zU=p-&iWwh4VuFBf$5lXeQ{ejxdhW+0Y=7+h@Luo-4fSQGz}0H$S?74( z^8wXp#4P=2U}wbOPjnz<@M#F#nEdQ%EfWPy@1hBT0z9rN z5aHh0P{qnj%9LJ9|8P55kj{`!0NQz1H*C`nUn z?0EB_ulN0g;J4@ZhdEET)4%LrXJ7f90e}4?t>VOIuZzj>xb$)0rP(QHR1ps6Vr@L2 zm&!64wER@`@(3ckSdu|P=nYh>rbsGVCIm2!bY<*7456iplobb~UcJ(62&*7Fha-;X)DoGJ1EyDmU=?U@%HgBehAtb!4=mp4z*)&6IRmJGbeUk8xN zI6p<;+vbyF%%F_$wfO=9B<2$M`WfX_Do3CKW~Pv6*dReUf157;=LJYvk)hGP9Osyw zpO(BmsW`fAfceWM#j|J6Q`}DbUC6hYn&G^fTs^u@^|1JUtpIPkdu{3ti;HE zs68XmuzwCe$Wy8FO@4tsHLiw|V9;D$+&`24<;leQelAR!Orc``|a z4RuHN0GUNa5w^4y^Fx?K6-8Wj`nM23O<}cO-gS%}*Ni5@#Vb`TXZ#ts4?i)M*as$V zR+}2%H!Io6h6WWU`1(VOv(IuKSb4hI;TAud|9pgO5s;vjcKU8vx)?n+Hrk}sT@6^g zXTQ*mj9CLoDQ(cNbYkNdKrK0PJIP;STx1=<0D85y2H}Uw%BWxu&s5uVU|Kd>7}1)J ze2eXaa;HD$U`{n$#M6w20hj*TQMkc-$0X5M3|jfED(IGn3B za_yRGH14VnC62UaxbP8eWD8np=DZNcIlWIq$CJ;2aq(Q2dw`R|NhA?W6)~RI0f{PG z4m`nxHvdIyXu#Q_cS_y>pbiwhnke3Y)L&99vl}Kd>$e=A!6GIO9_dE9)XZT!U&}9@La?GJcOFJAI8mW8VOyP zlP7zlhzz!bRTs%H8rc$rPgQ(6IeN|+@3bepQk?v0SP=X&#blsTf~q7C~OcU zOJPz%+*%`{;RBj3b%ME}Vm;|KQdR>**dP#=HXngGkJS19tVx0Y49oh@R{$|PEfc<) zUjSIsudlI3BC;TW8xSbTn|h=SBOM3 z!PJv2C;B8+R7W#W$)cBitjMC)XlQuFK^{U-C~UiK^;hOnDg>|%BnT^G*lhI3hn5z8 zj}aG0zLigA(bn{7QZX5=dhOtE?y3K=uz*elD0XlxUGhg*nh;YTV)S%4YZk-d z0Y{}`8xaYdQf+}4o^Ww&)YvHSd&iCbly<=-sd{b?S0pWIR$2AtFJ1n%d-?SzOAcV{ z-Ql-T_2$2Et4 z8cjFfvc^dX^HNIONdNm)MY=)WU&meB&mXtB9x0B~iJ|t;P~2`%CwoJo)N=pzD;Hui zm`^HWbRuPc+*jq2YWh!{p5GdlQE*+c6^bD{G0Zx?1gSJh!L&`b@@?nqbG_S>Ylf2e zAAg~+<0RT|n+=*NKMCQWQt03j4LQIa3|eHELh#RrJLng*jT%WGVu4d&KM+qx>5n>( z%hXUs-b<@YetkzNpXk0~KtfV#XF(P+9p-z`xAC(AP9#iAu28RBqyS8im_|F-^FxPq zEipBos^tAK?YwP3j!pzv3bm{#Y@V1B`DSd(XE5*c#RzCIxowUHUMU2q@85xk8&U zG0luS1X2eCaL=`Lq%l0*4o6jsZ~Y1sNEMhT+H&{_sqZ%+@p$tzNx4RKb~R~zm-5!7 z9Ky9OUJ*pk*QyV8Yb|lQk-(j&W{X23lS(sw&S&4%>Exj-pk_1?Ap`jm*du9}X@wf` z!Ljj4R+Z&q*;q>g_j13pD61uzsVEKAknrnzV)w1<0dr9rI(4;r43hptOqSNwZirW> zSMHJN6TBSV6eZY+X$`EcsPxSi8H1;}z>MF(N!?xI($wMqlLM(}0*r7FJcpqD--aC*l``3wilhOwEKq6n_#nYp*oUsfa$*a>HR&2a- z1n0MzS<+-y&5!aJY$RLm9P`tLc8m|l$BTk__53-sqFdkc1j2S zL%g9n-UMT`>34)sZXH>^X|e$OW#LKcv?-6!`V|P&CNB$+IhRU5bCyHzW^p}EYrR9 z^{=h(Rzo&y4Vhi(&wygZ!^uBd{v~-h2*T#W=Q>c=9DwrmI)2j*|C(yRY|$pRT;$5i zPAxmyuhBAs2i5P=u?njq=74Xucfv5znR9~7b?Q+!(lu^Zsxd92T zh<#mwj9n9KVagltI>MGjto=8$lq^h6<7xZo$l|{z(8S&Q$sOz8_~D=tJ2HKuYDsfZ zS>&NPquBP`%L`hC8zZNX2%SwAXf}-yaD=7V=YM}MJxYQ4PguzWuPbuy_jJ$20M(wg z8t?Pu=u5skndaK}eidpuo*NIp9qe3ZiXcQ$(TjV)!e3|_C_@H(28>`vk>(a2kLv?w zyuXoI&>!IAYLh?v14`O>=C@eOr*A&2{x&LLj{zt{&vA9PFU8VUW9`W^84dP{dpZ-_ zwPhfC(xSXuTI^F4p878IY#HO`&F6%?^rMai}SSGVP z(g{*SCL}`SI!kW@AJbYA0@;n%4_&1)SAYa5|FdeXOPl}@uhbfWb>>J{?KW!uT95o4 zMYMg_bvG$9Be__HbUA1EZK;~%=YxSSr4yHU9tYKD@oBhW2M`(110g`$gC!0pR1s@* zqwbaG@Z5HiKt}iMT&Kj;MfFn(3l>z(BEGL4541m5yH{%MO1cPz&hjDJ$je zJ)cjob);+3`KEy}xo&Gv1gn)giMluA$AEE{Gng%}qbJ{Hy3$Svkd|`E?2rBA8~&Wu zS;DUF^4!PZ0e_$U_lEwZ*mMlqMJ&AOfQeMiOxImvC`ID~QbXx^RVvlw`fv5ikK)A2 z7%BBGgD79DCYtpJ%B^_b=09SUI$v$&US>bcg~cJtKFV5wm64b_a&6H|$nxOeVr<8W z|IuFOlb&!2TXamo_y_KaC;2p?1ep+{G3{gVWh`K##ezP;J5pVhU`UoEa_QOaxugSu z=Hvghb(Gr3x3^P_t1rS(Zje`#1!b?9|M68LOK;;mN*lXeAgzdLZ3A_g2m5 zB~z!E!Osu*8SLbe+-TD1pdW(a#;2tTdLPdm3N!*f)ltzw%-_!)Hh#fvL+*wUb>KP) zUer*IvG1Z``ZuLCQjb$?y7|-$h>KbDqNDUXRaNF4-U=ZBTrg$MGd;532SVCmD%HM7 zl*gy}yvzl~`6P+Q3iMvP*Px3k+bI|bp<12fJUM@^Xy(N`1E!MAYygDRF^KlgFi5<| znlBa*5kr9%Qi(UfYE+9rPY{5WKpbjih!R0`v29&&O+$qgK6*Sx!V2a@0OR>K+_6N5 zE%0XR+|Q(ir?BseD`5s^@N58kKLtSKaq9_?kX*9cQG}G$V*1vm00wk ztJm6+Cah#7VsXLE?^|FWgxuvYTdscz-f! zF(SYk;RYyxab`a=uS3pWs9YKvh?~TJHRI7!YE-^Fd|v;SUPy`tKK0}?D3=2TtD9fQ zbkC>1+)+d2gnMbep zLgMqoebwjqn2_r69OPk~55*$@40*`Z2fmF6r&`1%(&@4a16#0|d80(z+tY0FLY#0} zegcCdqfA(&dq^#>5+5wAs2>hr+p8$86z!2dqkhFz*eW7nK&W^cTY~*S(hvnh?=Sz5)GV89Tdn(tHDRKMF7sA zG51`>dS9w$tsBbKSadM{z3tT%X#2#fyHK^h!_tq8X`1QAF6eb+edB;HE-1$`Z#?#a z=HfOV{Ra2u2d=YT7SbM9*e$;EK*C=Br{n>K;CH9&PqOE|?ffpWL*@p+0JW+h0pr8| z-D&fv${<-UA{Vpp9k7*0cb4YpBQPjUdN+jnP865DN5Z2W@FK>^BAM@(kZ+o8(2EG) zB&Nxh_=iDN)8LQCJd)iwhtiJeVdV93#BKQT0S%`A0Yv8#U8Z9EH@5fbh9F!y19>2bvk&IR zAk2ByhZitCYB4McNd(UbB8BsK9FAR)pd86-(T}S97DBd&Hu>`$o)11X1>ga!5;71% zyH_U^EDkO%*F(`O@~0H?F{a{UyHq%ede2vHHkFr%#?*#$$L3%Aq9Whb6Kc`nKsNTT zm+b2*IS(G()cP7CtZ1bLrC;hz$#Ix>jF>|`YKW>`*5vI+Sfn+4W<6S9g~Jq z9044Kd}}*tihGQ#!^J=f$0ktHp;EVeD$yN5v$&+|@ghVQn{S@QUvPAl<+0c5yjM{Y z=kwC*`ID7;MI)-i_9hZ94o->rl7~rSK)9il)p~rsb7az{0^HlAp0_INdkmL`i<`N7 zd6T$F3tlg?nyEk6X98ssHT>b7Ku7u|J#B>;->B1d(u8AvU+?We1C!?Xw!I@&4S)h#o>846JqNDLdhfxrS|7%h_8jfAi5)a5>Yl%BRgv)mZTy2O|pmXli&=T&an)?V9 z84#2m)G4&{Nvwa{q%?aT>)>xx=cf>;db|_82y8h|Jznoj8DdadtxWU!I0lqo{dnto zx#(>hCJLbVD*ZqufP%4@9}i}@%&)%|zwJl%5wO*=?04jng-8ViOpW+f z7=eApBg)58ct~Gmfc6BuPY7}CfVcvs34}vHUF&-1a4o-P#s(zacD8gzJJhJ?ArL!*GwzR zv$aC7^lh1; zNpNi*Su?Yfz$I`B9}`G!d=#j!?dHCEQMng=vx1Z=)E+?R20mRrMFE$!gM6F05a|>v z+1GrZhcXhH$!k(Srw+nHfr3e7u*L!3it&RpS?%WdwQB;$nVOA1sX<@*@-2RANxM_s zkt-ewWl(G51gxN!uYmpFwD)_P1r222^_S>e5$C3R` zk++ZfDK`jlBA@kLric4?fvbnAi4wx-Z#-%%O$+qWXurFS9a6(kaVG` z`9bXJI#IM6bc%O0{RGa{se{;*?n+U>F(QrqZYT#d4bFS?F0540!h)QJ%D?0019rFV z1O}{j9o)IgRuZkyV1leu+NW}dH8IR5f$zS z4sD7|aaq78FezN1@aQP6(>p_j-%32LVSq+aU%2z)bGydhQgPgI_ZNX|4J7TG59iM& z6+YEK{W~dxc1qqxymqzNHA6$@Z_NI!YY(3Wr2@Yy<^0{A0#7`fcBA&RLejM7U>JYq zp2Xqxn3%#h60Bd z^#ZIM90J2xIrvSw<;;9pbKamO)2gC=;{q(8UbcZsw^ zaFF-U$ne)!Vai8NrAyq@Xj&kiEm*&oUomygvetYakUbAi(}iKAp$rGAR07{$P?96<8qq1vOSqE@sWAM`C`1{0B)_T32bNoEQid z9#D2ddzM6=!=jLCpXr$KmL(rO@&v>8@3Kz($~?4Y;(gR5Z2AsT*s797_|&R;^0xBx zg0V`dVWA)I_#e9hn6M))YTZWgn}b!CaSi>GXF>?@y z*`{m9!T=x1m`gN4_{`mFLL{9FbPj+41 zXyofX^ujx_MpN#l#xH-@g?QslAs-zMPA^^$_Bt zOSy`-2uIF5TI?PkF)Ln^#k(Ux!;bQOAEbe^0rqZp8W}u!wvN&e;du4#KQ}HH$kolD z-m%*A94gVInPRV!rgJbi!&39-OyKS9_j6~@ES`R~cY6=|QIZuUUe<9wZ7Ek}|Iy=S z2R>(ASyOXRNRx>VN>*x9ijvxD0!Jbb0@&h?dN?T?W7Ic05sH?rsE!@a3gr9<=BBTA zf4SQ{U-0B$dXYoSHAPAFZWIpY(RvvW42@;*@@T3osZY_o5H`+!FbAl z5&r!?WY7L(#4c%67(UkA1}s7ntE4WWoSBx#Y`Vufq3%G>soCP{QpO-EHejrRhaoQK zy54$zK%<54!hO7OsURsz56_hT{p;RzHdRaY!&(;peYT*Y@YUtM#ybsJ z_tg&=?8%(b{I!~{%2yE4MGf9IHeLx818E)O8z_n5Nfb}Lf`Q3-2M6cr_hDfoDw zWmsMG{eFO4;F3p>LKU>q{_iX_VNHDj59y+4!Sw6#3jNdt~+m^3T2v{lliR{OLqd zkcdS5tY*0&2Offx}&LMQL~AzM8sHf{YBiUR6> zCP5ek8Bzsm{oUh|ktPdlVLNu_nVDgF35;2pI7UY5fsq~%Me;|WC~6i45}8h++aL;z zFlt24o}o~=YWCe0cc7>f5)<_?w-j?`njdr{IF6S@Y*gssBssC}*qJ5~BM!QH%(gQ& zF&9;fjppc-kN{l;Wt4HJ$A)D~QScd_@9_^oihPiEa-ELcz2fW3vYpj#KzAPyXix5MFL{&RsnPOQK2f zB=&4nDHuC$c{A@8sAA!^_jREU?GvQ~CCaM^9G=E0Ge2evG0q0&NX)cgqsh;BzuHju z<7TE*)#)_`3pn^9R|Ljx1`_liLc!Pd%`AO=kzwzXJi>ukJ0Iw~o0TD=4=NxP^4}J( z6CDP`5^2!+quZ9JChsS^yuK4pK&3UMmd~9qjD|rezPF47Lojq;lFLxWq>d+?1ktm~ zN21J{l{YAfP6|6P!E-fa$f;yxA!or+iUq^Fp%Zsk%0~ zR?UO-j(#Qh_UH8VqvD-69!FW5Clqg^TPcI+7gr}R8KutdrgwX-W(}}Kp&ktZ77nB}UibRdbTqxc=!89|d+>vCoJJ zM~ibPHSG^GTp%h*@72A`rfR)wlP=TNwo|9xfqg6cY!>jjKKmS9Eu8%F@%99=$e7+` z?Zv#IqZd-_1fJ`<6Ju%F4epC~3!8QPVzW}eejSxVCb}lj2iU!5{}kDyVPal18Y_|P zp?u}vt@&jx8#|KXEHN=fjfPt6>shItZ?8d<=Ws{3U&cu&aHFld&dT?(1?S{BQ~$v8 zFR`3F>>t-xJ9`J`ck$B@89YwMSS=-!5Sn=(+}!N?z4_e`hOmIbn>|Rd7~%8vCYeRk zp=xk?NdV}!f6v8X()=acZ`pOPIJv1`j$oJdn2g6Q&pXxnaOQQQ&p}7ao)la*RrtV8=^`rG7o*z=U|)XEIxnFdK`Vx z%Jb7gVrJ#cb^B0M5qOIX?)nJ`Slhv(PFxpz)(fkij3?~4%RRZWbsVW>LdvYwhDZ6X z-d0vCA-7+2!!`D`*d&y%U=EgMD_Xuc)TUX5simF)PIM#UU9W@6Oz4Ut?K~LA=U!v6 zQHl@q#|e4b%n46eD|;E}VHU9ZkhxWE^@yFKX|@*_^|y+UF$WYHaB z@(K8RExjJ*%u^V}z$zA+wk@MlYAr(+XS49G-l;i%W{QP`;$euaUo40O9T|w29bukK z2`V{}VFi#Uj4n_+yg4CHn}N8|ET$>-u=9+~9=g@+Dtw9z&CAsjVOrIy4RO zv|O@=o;XmAqI*Lf*dA@P%U|6JJBo~mdx0FqbI>f5mY8aY8n)xuSgxs<^-KCBhE|~{ z-j718mYEX(dAaN|^i3t`ME29@+5GmX`hfdxM>Mb34{&UCb9Vj_Z~L<=*!$e-`PC#L zG!h}5l5$OwPobN962+ta@p-7^V(ToKJON6@S#Tojx65EnS+?-@CE`! zYeHQagZqJaT=|8JWt$*HqnRTsQ#&dWlD^6=|Cj|E78wWm5;dHwRHRa8zTui*3=l<# ze$bqwBAHppQ05y}TbAt&7Iw#K`oZhxCPeVWQ>f8{K?wIpC$4Xg2uG`Ex?5W|dBdh} z%V7k{Jo$M!)b5?Rq(q>1$f8ZKa-JmyQ1?+qq%N>hQ-ng&kA;snOYOR5)LpRgCA^LY zmrU8V-V;7jQJ9160SGMN^&urA70u(`fgcAS#o5hu?cS~~AcWk^Sb5=Zx945A>Cf_q zMcU(XQ5rT%;yB`-8EI-iENX&C;m?EY)q00Zi;;Cj!L$5`(^pgpdktD9qyge`y{iKI0_*Ge`z6XsXwcEQ*xEitF`Kp>K zIs?1Gr1$WUhgwCP|fp0ip=FLpQ??sh$-95VF#$&2}Zep#U3 znd8B-QK@#P{`aK{j2IllFZY6jak1?|hK^vEx=mEz^PnPyFyo@=zxr@hUD8v0SgJz& z>FVs-W6Y7)dn(~(PKm1vnXgLSc6a>k?^yej#;Y7p5baBe%YISduRzqIy|68Fj!1Fi z;+$e`bDVU}vQO;5&&p01;^+lK8=fKxy^NUA&|}+R!P4>E3!oLAOod-{NvM-2OC2A( z7}XM)nYr^?2x3!2A`yquo8rVGE1Y2^36|z*TZ`TQf0kY&Aymte{_PUsbZDN=p(`&g zw?%`dnWx&Yz@8dccFMg$E5}QT4&TC%1Tkd#4h9lhSe7~Uz76DibVLK=hY<-hNC#UF zu;)wez5QbUF#rJ>(CgRN^we$Z+}<>H%px3CR#xtC;TTB!doVCLBSu#8DmEztai}75 z=E^%Ov$3nqOjszSi3&L#mA11ix(DwL)d#t3*Rk zp1@72VKb)WFP`yTcY;UKrG7B`Hh^sJA9NvEG_O*RU(pu#jFJ56uZIk}OG~X%M)6FO zXqT5}i4noM{D7s3vRNFMDF9O;?e6lH5qf#tC8wPTH0 zT?+1V_r^HJ1mTErMa6I)W5dGyXUB~i^PXF#FRfmOs4NOu>v`HR$A~i(%$^rNc1A;x zq>1)H$ojx%q^Xu*sFYyfGD-f!P-CKAIZCe_5I2wOInaBT54DmiK$^opwj{qc}e63!+H9Z;%9`DL#!mK2N5MnTshPS2c+g zfpdk$%raHB`rWLf0!eJT@X$7AMn?KsI-<8rhncXE%D@Gv9GLYMPOBaZp2||(5~Ov% ztRlsNLem-%m>@DzRP1Ot1O-34)->p(K)1y$%(kn$vWDmY5FnbKoDhS3IE=z(^zi3^ z@RCQHpu2eG5Upa(sz02vlSp2A<&fHg4MV8ZsMy69BSSs-p=SfM2Z6(*1Fb!sIU(gQ z8UsazwrB}i_|1W6*<5#Y>7yulv50DcYAo^F1r9sY0QeD@#FL|zfm?(lnfd|StJg>c z^+G%S(ffH3FBMWVl|0G<6U}y1l{^KrKUbNmPw6cD^9QY++}0MMrfq*w&Uz=M)wubyMW` zC~p;D6FQFi0~MlqdS&8A%lAe5P(QMsp}k*Ty9mH-Lf4YY$|=)!lUOWVJ4ol#6AgU{ zo(gZyQAY=;$ie>W*He6apjjF%RZj*39EuzTSd+|g8pzK21NRA!kkKU=4Oq0PX(&u^ zI9otfG;=#xI|llJx`G{lUcNYo)hWHlOrNq@o%-{o0aYGy;l9IST2|r1$_U%hAnfnv zvSs3E5X8WRu9Qq<1cyJ*B<69*i;Td z$SI`%a7o>1V(b(V3GI&|L#ig#y8e85)~J_F;Nm$Jw;NF$Dao-5U*)%Pa%~ERN0QVQ z5#_q1YVFa5X{Vx-S+8Jva?BN@q-X(pxwTZ078U~<5;$pBbUvKzcM8NX+l!xIQ-I~w zGqWXjy+Sd#h=DO%@iOFS5n-}Hi<_?7kZvmu+vibBIP!((v}8c#+J2#J{QI;sg7mU` zO>MLeRKExh)HpSco5)Lq5ag8%Vw#Pdm8pxh)Cl0_uRBQ(f69(TX1jz7!0`m>zu$t$ zL?9TX8=A}MGwH!&g{Ov|#WBzg|Mv(jol7v;DbX9xgstT3u~q9kqtj%_gWyIG>4EmJ zRU$L(DP$%h?ZzXZFuN)c!^LKlT|@z8u?aBV)M0I%_?xCy6%uo zG2be6jHB_0Wv@rMq>{RlY@wRAsnxSA2Kt=}kCpXoYYatv8>a?|2%Q3)cKV`rjW)i( zMc4US#=(KJMZWA6{e59k9gj(;$7SG#IhBc`qiCQL%D-A%!;EuHUKL;hd3;?)%%Ung zS7V^!8D*?dmx`|ks<|Ka_EWO34d}!*2ZgDHI#_k6#kCBY@F~U6>bJH4)kNWnDH=&E z&-k|RjcKpX`c%guzZ2YUK)mI~I;fXMt}Ogc7fpMY@q1L6Pv?mF!iAKGhIa8# zmmSpX$U zESB473vPFM#E|gXdX$itr)TAOBOY+cdK(Z#Y*FXCJe1VcKjN0kS-Q1iL!sSWpc^?d z*(X8}rxmv7w2uGPVhctJQsO4=0d~DVZS~{f7N{((FGnMC;hC^tA)L+F%v&V2{tIG& z1qU;z=!6_UAb3=T{$(LI@jvhXr^NMMgAZQw9#PqJ!oG@k4tmo>pD5rA> zhJ#%%^W#3Ol+Dq-VgaBG;_eI{+(@;b##CGB4t zdsSvANADi}?SSb~p@tzDIrbCDS#dMu=y29wQD9~1^tIx9aEBPh8 zU$#I_7jG}-rVvV3v31(mlK{(Bs+}D-f6$1SIq!r7+IC)D85An3r2o%1S~jZw5aJk^ zU5s&d3I9X3%;E}%ev?0M!KoIU2rG@Oa#S`{CzA!nBJE%0Lz>NrnpV1n|Ee8zIKhPlVe1WZ_?k zBMToQ3Y^tso1IJ$L(Q)=W;Wl(S0(eYc?3{!3wTvr3Kj=-02Gt4?N5Ok{^3+|u1ucLbW| zaK9Q?_AE5$w=cLnmU=NDg+cW<(pp+M7c&GPvIizmCNpFXE}yrJ30cG}HWNkt{loNf zcK#XTD7^f|J63{j!tVc+%n!@)E<@?HlM4fT}Sg}jUCE!b(4wl0oeqlq)OgrRc1#qjF!+U-loT%!NW zS2h~wb96oAO*4I!g1rq=YB8)2Q#X4ehRoKp1=?~HQgw?xunJ+=*~VbBiddNf>_GB1 zw>^@8AIb!t0ClK-VnRCvu<_{jt1W+hPi{lJ3~)m5wIF$_a19SO$kdX0bhrJ{S& zkW%ZdzH0G#CWULReFGFSl{baVM3F;6M@VK`29V$06+RV=eib-P#JEv4mxPd|jQ zd^Bw)z7(1&nTBjS;2-=UGjd>dj?8>jG992Y#|#K!m_P&-Dnq2HuYe1>*hNtk1jG zhX=cj^OqNK%l?rFKq~F|T?*)=Ijyb?Pn<1m>tu-vCM!PV$K(E+OaO@`v*4z#uAT>U zSi+Qnre=;SMT;%4;M5@ihQpPJy#XR&(4lj<1XkQeb48-CQrO&k#}Lts zWy)Az3B~1xqMiTu!Xsh4hnz934&JEqs3B7b;>5t>oBnIB;BGRrUePBHqlOgI%B?q@ zB#K^riyKQ+X)6dy@mK)3XF5M^%cw82?h%rSUl4e*vKFRl-bO>&c^Rg^ErZU^L5q9O z1F-e9n8kn?2PsRFWs(2)Q^a@{FLLL4h^OE+C}RwU!x26u6LIVB196+12kN&@*FfV* z3$+wo7|_Ynd~0&2+rd=Z_lpv0Qw?eAo1>u*N^x5pNtp_ikP1LHFAkI#&DXQ2+~%N!(3WY(XR#d~qp2xD4lOz7JQ zmQA!r89<1o>PhgPEMyW0cKwEY07EB3ovy$LT& zYJ1yKe&UT$S!jL>XCnL z#PmmBGh-5>K5wgfat&Ku$tQew@ibzLh^8MmF#vZCT~*efKiV*3RHf;H?a?kAe+Na( zqNHH5qrco(D-8c%7W4|PP}4b>(G#iEO(Xk)|L@)(+Ce{(~SVtInh8$G-q$6;r%)%_h>RXxs!U3Z_z3ka^E zY2t*o6!{6EsGIs7Oe#~>p@Ae!sqReP`~au2eNtkiZWd|)OMkl{b#3sOS&FPL^cIoc zYVOcEZA4;1kS#DJS71PcwvH;|M`9V&Z+kjY_0*x7e_7zd zhfGfN1#}-z9xRo&e24a{;DQ&b8I;g*hWrR5LG#95BgXQ@bn!e`#9&7Epac^Z^2)>Q99L735)lVjNY0|9Ue?WOVjZzoI0IX1}qM4a4X zof(S!{I7}$OR75jM-}RI%vxPwl#<#hd2y70i?ep{3ZjEf> zA|uJBe~Ty85ZTLJC-3(v!5jDb*42-muVyURa`(?=13YisIbbz72f+Nufk@!BF3@U3 zjEmtw0-2bavB%kp!YmkID)^)E+wI{`mwzVYzrd6Gjd;Pd&;XmNBP#V*0ds{lpR6!R zNd=_zp|egXuWOEe8bp`XTw!sekA;*AHqcRGY|Du0Ni)HTlc6FZqOm*iXYSk>Bx}uh zeIC!O*7>G_6A-q-b#PHX7a18jUQ79rFbYQ|@EXs3WjPW@&PHBPg@+$>KuZv(I)%|b8^%4uCIy(=X5_S~K=lgp>#Akt` z=^>Q2EDeW0ZZ8^(Dq?C>H|@uoj0G$5%Mp;!(c!;DFB(r$*|4uX=_3LTq7_ejI1uSlOmCn~+@-_X`u&cYB^o*$6DSF``sCA%G9B zHkDH?i5hBXKsh;B3yME)Q?5VH$VC2hS}jVBm>!UWN;0`nDk#Y72u~{D;O_-s5BGNf z+$2c}E5Qa7PGqATs=V^W6QxdtQv1w=m|9VJ@UnQ}0Hy36Fv=LK6qvi`@_%^4Pr2(w zq(li_I_3M4)~hVpOe=315{z?`E`p9CAeCI>IMaOEoI+BXkqd=mxdP&CchDsIBvBjq zcf5g2LZ&pMx1_+xE=QSZR-02bqB~&4T=Mg&)BeyKxCWBnQmIB0sYat;bJ`N8zp5LQ z5U)^_Do_kn-{A6&(!hj>j0`oyudF1}jXlHt9gGb9eOVaQ(^&ZlERg-j*;VD;XI9l7E_*$fatDVWuUhy@`+4G&m zTdyo*mh<$oa=5;tm@mDtWpt)C5i9qhbCKyTJXyu!Pr<{13DmK&zw(`F3i%d)t_4nV zaJHuuO?+uz*tW1C!pA2vvBJbA6#e84Qd&XkHPk8JjP{-R=q0~&h|Pi*LQw294jiP` zMionh{$|0Nv2<{hfg>p@ny817=ev@AIGE8JoNRN&e!LgWYe~>{lT|o9{FdE^9|UEx zJ_xiFbl>On91kCR2pPo{5jC4i(J)q2l6)q-w6}R^-w!xc4jZS;_PZ6WK@Vbr3ob1z z=w&HE5$R8mqQr$JJ!lt;QgWh^E>fhxR<#NkGzAOsH-(h{FAFdc>1E>2vB0p)y3lYo zDMc;90^{0*w8T)kBVw!YB&4}bCL^hqJl(`esK_UOk~<=%YLaD` zo(+0w=_-p6Gmf<0~FgWM~CqXQX5&3JPqs zy8q;&pKE@yx-+E(Dh|M2#)tduyu;y*X8fdrT%uj=C9Aw0whj?+S^bxRLRS?l0L zi>P5<@Ir>Ox17Jz)sP{x;vmgTkKFuWy`X>9X3iHAuxT*2lR7bu!a&As3j3b+B)cUH z*u&;7?1oyB2;;>MAqVH$^n%B=r&FTY~JxpB}H9T-O3< zo}n2$r#2sJQOT9~2o%kuB!F2LnX>$oXL@ZuO^w^`@h{FA&sqBKyNVQ8RUkix9{+?- zoDMTBK+WMkJ!=n{utP%Hk|7Rbyu9rB>Yx_(PqFdKGIM|&dVLq-V+Nk4HOC}sn7cbp z6$_lM39S$)n}rD@=Jqo_^`eh>Wg>ZSAO^N4f(VJVl0GM}09wbUr47S@iQevSpWUWz;a z_!a4waOrex%tXDX-xtw>86ROmcq;Ua*UfE5MO9lmf3P?@2rb^609!K6!vEJ`)p4b{ zrE|9+{gH1k6@T`;+2G)y*^=f!K>jW%@Z^snYm}}$HR)72urxkf)!&J)0B*>X@yi(^ zwjU!RJp~a%EKaWEU{`9`1u_8F-S*FS>&I&CG!d4x;0epnnWdUjU2{v&ePBjb;iEbP z18c7(H*(T*yEPy_ezcvPOR-9u-3dQUW49t64EP9u@koi~tAqIx-TZ+|OpW@PKSDQzYv+U-$1=|;Emyk2Dk zXyv6z8AIJv%d&z3mWrSNdZ}lJZewjE8e_+;JRKfLsS~!kx^5rRxG*#xT<}FnFkgCH zKeSv5vNb!n^~GQY>Vl`edj|`^XlaM7!cx@osU2Q;Yb2>T?3?W$?MdLQ9~g5UjUEQv zo*Da-qPx04LYVJ<#p&iwDM!)^m4HhO9WewYd~p6@93*YOeT*Ss&X{1zXgQSyciS;c zD%BtYrP2VcXiXzXoln=%A#A`{gl^JB97r1EVuyKh(en8|%U=?7CCM>*c6TW`_VL&_ z>{RJ3b;mzZoUh%7oy@yD)RU2UB+nhY_9cjS|D4|XtfFXOCHZPT45ZCK>L9@J5hA!J zcjzDz+qS>7W1td#Ci;owG9Q3MA#^$sRRcpySahWpZc{t01PvXvqM(uHrnHSR*0qSR z&4Fon1C70K0zUGt(py}Bs@S*!sTp2`Z0n|)WGPiKIGri4bxD_GZ}e+wPP&%}^H{(x5V#ao| zu`vd}*C=rWQEg@dW~%8AsR;xOI<;LAO&7AHpKGBxq*FY@LwJF#nkRsT2q_yNQAv0iNZGXoFs*$GdOs%krv8zwzJKSzX&$Ld(~ZnI3 zempy}qg&rZSG`2T$uS@rMed@pa4t>sLIs?pbscmjI~)qMv~kOQ>9{J!k%K0ucI9;x3XLhMfLi#apjiW{}1J= zxHq%tkiVcd2uqVHBTyT47U#PSnN=RfL@U3uqeT`Jl?ltBI=tkkdY_OXK-Nsf$CEKj z4xwD0mSK-3lFsC!TY}C!OQo}MuXBG7NVryVDsrn z`{`ckDP-h&HtFQ9kTqC}y#16fCKxsRGlJ@Ma?Hs4ff33?+>algj$4llD=19&0^R?l z3`OitdT;X+p)S}iRO$4 oUGVj2~x#Inru9(l-t?g`r(Hm9I=PX18du(BQSu#c+ z#LZ_yvy(bMvZf(YK0LVyy8RP2&4PWZCrnEcVL=g66x)(9TxBa5z&|emnkI#bqp3vd zaPTlwNuE^lubAPapTWb!vp0npmq4PhpFL-~w`{PnQ3LMj#C6W0b3-Yw(N}gC`5pzWEoDJmOsNvL-=8!lAJeS z0}(Qa6$gh8zNFw4C>HK~gbRcj_4POPjRN(DxPENKo;xS`XvyCC+^9T< z=SQXmz)V+Cr|gO+89S!cXz1xgYqlNjF3wpGE(lyF(Hfj*1O?$--kvs2@xzq&hu(Vw z*jeeMPYqy5)=Ww8zkUf)Bf@agSR>>x#KGoiXCt`Qe{#bTQ6M;fxQxmE=WfN%vB#q* zdWtp2&?azQ4dyFEq%Q~sE7cEouqfjEdYh_)Vn<`le~(t9qxuIz+2PwspV)6yl>1qudFA3tfwjaA=ez<_Z$B zhc%nZ`YdcGlvoZUCkds^;5G@lYrSZFrKO!a0$J}QoGB<6d@YCEdvcvz@h)BpCrwtu zz2!s5gq!WM=hzf>$i%wWE%h3~xcoT(@AJ(vyN8g5Dx98AaPj8Wt5Y4Gf5qg=-Z~8& zIRAwu6AJ>7dSLB>t41CL^6a0A!?-SZc(DyZ223Myc)z|jz3OHhHN zJ8iHzT~!N@V0$(8^XYHKB0@@Fd%hkT9P}GqQ&Fe3WI%c;qvmXX#jrKd)e1Zf#zLmy zQ==TShoj6-#dWEHBlrqKY(=6$m^L~1)EA%X%BwD1jF8N$X=I#U1M+aEum?Cu7dtiPO+-&4y}UXMe$R}{Eq z;F}2T4^SDicu)PhCz6k!Jp|Emy=3~;|Jdw(3n*gtuEt`E*8t7nM0>~lGZF!RLs7y| zA5TuEuwxKYU?tfJ3%g7Z(|#9kMUL^g^0O&g`Sko!%-EWOiit7H0*;jQ$WRgYf7m&2 zspjVLlr^RO=657xlJ?4qARApF0kE0mB*3fyR?xH?(Ql-|Q54_)Tr5#2PMop~@3^Du%J9e65v!F&zCK7s2;u=ht#? zr&`HOUR6w)MfpjhDv05iy9>(Aw51i`}=U{ zr)9woO%&mCMXZ4dd2eIE?8UCGeFqOGdm$c|(h0Axf)>4mpPlfvHI%E|d z!izggU`icSF=K>-2_EA(``=M&D!Bi8+p9A!of>$O@qC=Q#OYw*sS z-Wg@EPnO2u_q?6oE6eW(e{XvmmGJ4yV;dG+$Zo`6esGCEokaqKh}_fdaQH4Q_Gk&J zd@1;ZkUt_dAqT=+-yLVl_YXIp&;Ce4@!k1Hd9q|(zxE3-=_P{w!^+aKW%{Kt=ZA}N zhf;{qPrQAL>5zqChb|&zV#tOUFGa4LoF`RhhXyZR)6x6 zks7*LAJV>Ta0C28=kO|@X5$d8+ZY-t6?+Z(mLN9VpNLW5Vh~L6+ zqz&wO`mK2=Fn6?t1b?H+2{0YmA`%tABUUPtooREr_BX-|J4=x#Pa;xp9 z03CzIhkT9E@^M7V_cdqz^VBaU)%hy5nS_c_uV zE#`Dc?K5_GNFT3|zS0IA(_3QJeY=s=;DS>Oi^q;+M7PI+bI*R`bQM`W;Gqe|GKcBMb>GS; zrASfBDxA|c*c<`a6~>QV-xF7l@=erVZ43md=Tube?Q~IG|BWH4uh~^YLp9fJtsBZ{ zCy$8Ln%fTZJC&Img?qo?pNDv&jSoIKwENeHh{)wcM1S6zBu*Euz(eQ-zW*FuU|QQtJyhuHh;Fa_Dp~X$70>S ziM47y%3FAdl?5lNn1{o+?WZ8B6eB$U3yit2M5e#WMefe2FM0zdJ`o}g6!r4CQPoj) zRg6|cEw9Mm=t|()zYJhoR5PO~0brgEwWOU#rn!@ly=SV+?XVYvtbdaI2u%Lh)z^HG zJ-D#q1t1M=e_f^9eml8$G==>4&>{qkc}3=)}uzkWV@54-dq(3v;w6ei>u~M-M5atI>vs zPhf8O{W!01`P)iyYgF0$SFZU4(_dS*!SGA3B{K=0l5wRW5r8~6nOPWcfZ`x^Q<;F# z@?K$zku2*25)K)1yii>|`lBr=E&>x#qn_jp6!uTEy1F=s5`Z#>uRkxMyI*Yk1y}JN z2ToX;>9dL0R6@P>eMWhaEc=|aLTkLV6}Ci1?-q2H&z7KwLPz3qKAZyl{K5!H@bo$a z0J3?lcfX=klR9gH!UY5ovm7s^XZNk(Q`a}2MZ(04K%sewJB}277ZABd6d4V5rUii^ zU}w>|xVHLWB8ZdW!W%k-M2o|be25z>09b$Yg~$g{cMz zi8C1NYLGADb&IFXJNZ8hO^OD&F7lh;HRK@Hs?;vT5gg`>29PDzUCwlvIUU0)J8d}m zE-P3-x7G~?{J&XyfJ&EL!8S6;o@EN~aF z`|xYVxm-L^_9l_(ojhGyH0|Y2-p$U9CexObjeP7mwmgB!AY5*9HS}7LBTs|}lrJ?s z-GBW=lz2FLPVsU<$L(nF=-UbPeh0=&9oRcwK4~U#H@7wKu7AGj8d`t%NK^cGF_j1$ zelm7v5aXqfrAi5M`O=FQi=oToiU_);tjg+?_TQ}~JN{5AfjXkt!zC!I?8tlI$`~ak za{E0=4(Vb4{DLIOZ$}_9ibzq_ZCv~wiA3|4CDS-D%I%UefkF(OMdw1FG1IS1hY<6~ z3Axvk+J*#hBq2sumMAWljujz8Hw;?I5^4n?fVww_Fx9}q@dFYdGj5;b!{I?#NaVxg z7Lrt5jKJz08UDk|t>IcDe2xuwCwmn6!}Zt+BnJ&Q;AHe;T&A&)Ysb>!fmlC$w6P6I z2+8CX6=p9e!_F`10Jg{W{&b4#1cj6H7?AEgfKG~OVuQ}o5Hv&SLY8ZWzl=oJxlSiSYr z3B=_jJ|K)7S{}SQpqv1`)qk%E2||b^O$ad0vND(eCnlyKsU*_3(>T$T4c}byJ1Xlp zM0Ukl(xT!*+#znd3Ee81*Q0I@1A+i*Gl~fOC#C-SPO{SFbqU4%@~a+C%029Co|NfU z_#8AExf|I-qmzU+*2x{{=YLW59$R@b!aCVK^GD0_=7WLBz0R#VR9V z!cU+?O1nkmg&LWpES9Ib%_C1p*EGW>!AO4_@_n$Fs*sKuFZ%0%as4X~v57L}-*>Mx zO!c&-gRJU*vxvbXcX?e8^KKMDXR*(%gDLJ4T^|@Dr9_Y9$0IUH@b#}s z`&`{tkIv|QJ9U~8ifp&|)`()JhxqCDeQ51}@*Bj@)t1Jwe_29K1(%m0lK|gQZnDu?ZXX!4Q6_#idyG7%fufE$!w4fbZ!FoRTkVG&D!-^V$wFmztV!!{fz$l>r;}Er#1t9_7 znO=OBNRELXQbbJYozu9Ld{c;hC=i0y2c1#dEEz95f$WyFcm8>6AKKN$F8K;isfPzeyyY*$tTR*Un-<<6qjV!TRy) zpJE6^NuyNw$zAQMaw>TtRBGjla;NVT0dXuL$6o;yc{4(J%3qHW8NS8%lGTfnNJJ?y zO$!U|GdH)?->&jrSgxp1rwo)VVhnyniKRryTXn=Od;dYIvw1DrP2kG>&pY)eOR_Vys1L*Tt%5 z4Gg)x%Ypu4f;FA<0}9m@ckQ1LMkJdrKVIGGiHZSNr}}?PWq<%$gSemX$-CB8Yo+0 zZEX~GR6Br!mos+yzcfftsJnjeft0BCIf7pQ3;9u#%lzaM4U`LTtNH}9Z+2K5oG24} zZf2F|`-ql4p}{}w-~8z{tOj9@_u+pyNeYR zygQ6rh@^t@fz*t5du_Z?aVro|6IgjWjH9o$-RefUqu1sr}jjMr)Nma5u&rhCLTU}D* znTe;Wkrf!cIXph+X0RQvkoE!>mk!j`>6}}zux_x#zYhdfB|AD?6Y5w!dGBnU3|$=t z%vtwd$Gj7l9kHvs`(ZW2^y_l#gOATQE-J zpLk2;4P2oj_gnb>l$UciQ53F7m&~*;z)usanZ2a$;m+0Vta^-@grvVb!&-53A-Cb- zEfv+*ENv?53?35X{0WX@&qh_-L1zyY#b7t4ASaI9J~2FSS4MQ+dL=}Ex<-C9?biEqR=hHX zm*;W+)H+^VqbD!0ZLex;&lH-HaGLulP-075i2OOy{+M%QS8P^_4O2-y8w$Ey-CYZ}osYmb|4FGYnnr{+z?oJYNVRz6Oz)@K^Ab3yM+TP~ zXo4=uxdEQTIXla3$6~^dsF%=!C%sM{SD2NRS~6rypA{s7tOo&BIy9qg(>$w`yT>RZi%=By>!mZPT$2B%5;hwb1ry|B(?$;DJ3W`r&N6kj%GWG(Zm zn1#oRZHq+VhI71ZNdn|L0ETP@6`gnEmqe%O5Bj4)Jfh9uOhZq4pul5p{!Mgc3HK@34ZvOtQ#a!Dkl$t z$U^=CSl5K97?Wo8DL5(W7Hmtxw6^vD{uCHotRqu~(^}R7%irQ|YkF97OEp%0LWmM4 z1+l2ffdX#XSeN{_Md9ndZN~*g-j^aqoQ_VsvZT!8v^*({iI11ocKPte_If(u31NN4 zn!Y^u-?x2kp4PkEMf=mEp}PFwj%>25mFuqB$UhKiItNkyRW$onP;NAqp2LhA1u8~; zUwF08F^%`hP62@bOed}Fj$6=RpV(ExwHW-5qeKeTI$1 zSVf7AUmP%mX03G-lGQ6eoRbnBV*y18o9~@k;46|X3)44Lg$>j)BA%?mik@iUe@8Me zZX~aPQ2eYs|NCXqqYVT-){Ux_K*%!i6rf_rIG&Vq#T4PXo<&@+(Z@xs$QDe_chBty zFBvDP&SuIKp{k*QbxfGcYhb~SMQ?ue1q<*|pZmhndV7ASIXJzY}FKF{LTF`8) zpNjQS)G&Bv977lH>sKypGKAr;jUZ4S|^U{TGErADhcOZT-yg&q#t^bM>1hZIwPJ?Yo7Xc2Y4 z9df)puQ#&S_|uzXG+&Ya0WM)M%EmEo>-mMh)#e>B*Dc3h*c;#=+mMA<-l_Xh_~cR?I|URbw&ZoyR_r`Zkn}#Ih+>Hr+CV(^RDyT z*Up{W>~FA^+5H{wy5vt=Q_t_YCW;vI6w8KX3xe~azi$bR%1wNH>%!%CfLCHfcMucy zV{636tDnxYY1#Vno|2MMF!#$A*IGX9Mo6C_BQZSg8$o6TSvGciA|}Sjbn)zn&}b?d z-P93DFLXB=ijrO9gdf@H&<-iPp9wR3CCe6nnwHqWl0A)eJ?b3(IsBzPY1Gkivnu$A zo;lK6X6R>z?RycrK6I|f4Z+?QR=0NPDU&9PQY7=4BNa86JPjGT3=PiW(-(&QgYA*R zUteYAt7i12e|5Z>;`Vg2a=J;-2qxsD{8+@$xq!fc$=b$9V z_3WZf9}b+$-WaGNI?G)sH1-tARh_ne-F~uJnH7=}Q(u&hQjJPV1y*e3s03OAn0Bzn zir$ssm*bh>XOQl@P$_EL|33W#ZiD}gx8a9EMH*#gskSx+8Ig-i@Sg=m4{V%!(d33# zu1mgw(IklZ*j2I-moHzSxY@?&jZi5^rR%##D7I9|TO_W5#R#lN@ZsFg4$Qv)c3!)_ zpCaP&7v<;YnqQ7|^O|zx;mlE1RR!;j52Q9gJLAHUc{Q3Q{q6N77P<;_Jg4^)%Gb+e zWz^vP_~asm;UiX&aH}Q}4-eO}oVPryUom!qZxmRg%m>||g~LvDsNZjUBQo={W8+WT zLmQDXAnLs9)_-P?ifu-T7Nd!)KX8L@uxRbk4DHFdbvoYpc5f^E{mHPjQue$Ir+fBzoM5{XX|I0z1b8b{TQ-ZCANM+37<7l)K}JZoB6L z*QCzz>kR5lBOebBmiMCS} z!H&TXU)#OIDj^Ys_sh-e-w0!nd0Ug~ox+HD`E2UL{gknoq_4zaihbM0B(N3eHZLmN zCcXuK5F2S_WeI)XY2}GmRYo(L-fR<=eSUu`tfx1>Zs)>bd%)MyEWD1KEF->D1up_^ z{DaL+G|4oRuf;Al6-+L3XgzL*hmU-txobkA(P<&`bm0%jgM>v9iGQT9xMg|)ZPhq&kAJp;#!ACUo~Q|-QjS3b4qu?q z1?6gQwgyev@GKP5h-ETmc|Il!p+Hj^T0)ZuYgf6$z>4p*$B*qeUlQh-42K z)A1;y2Db9$p_^oJ_WJi z%BXvv59i4|_qK%}n=?uzz;r0)u(MqG)bkiS#~0R1bNO^#*CQ<@sfXy|ax!AYVrtSJa3)6l^a8(Bn{jD-Zfr=xaPEp0e`v$31 zc!W`)NtjG5AVM5yuo8`OwYTIZKFhF(lk|r~<(dcr&|gm%BV@J<>rX2SV;&?AEa&4TM_ zNg1Y{H$WRW99>t(W~;<5B58BhC8n;>ij<=W zr+$WL<(uSqzN!9nx#Fny>H z#R)cc0xK=z+>4|N^&7?!nH1gNc7Gu#U#-VSP(TZZ_7*tFkE|3)Td*?1!5qIvC9Uo^Yzj08_Tt>t znqAqlH@@U234y>%e)D`V9NFxCgy-viVb)Gxh`dHHurZ6Bm?hqkk(U=_Fd_?B*t-G0i-@(9Ky5HNxA5x}Y%!s*^qJnoZLW#9zfBxZ|^<+;~jV=;E zCV-F-AOO0{GgS_&tIZ@#TiCYZ*PHwa?@5nct+QPuARQzU79aCP0^%fjmz9Th;_@bD zUSe`cy^NbwCNaB8$9?-oqZaD~H=|NlkeL}b_sb|D8oM28Mr9|IP+RI4bzvWoFu?zt zqr{vk5y^yzA=(Ug(ntE#t$C$OM`xSK3v&5>_R#h31ji|%T)(kx4WGX@V8*3bUyF?S ziAXxVg;q+L2+xE_*5b%mL1q~fsm_-wHWf@pqTS*NkBRB{HOfVbTq-l3u?~}M z4?S8YxItIDbj|ED`t z$%zY1OJxc*zQp70XEF%cYj0lsk+1JY z^T92NFZ58wOX^CI7t*}b3s>fRQ>2*W>bvSGT_RGaL^eZNux#RS!>RqapH~1bI(k!q%8QVihVI^;Xyq~SzvEJ7jW-5FZb;tm(UG& zTYG)d&PKRnYQ|r){JU&ZjsLmD?7hA?-J8gI2jd^O!=p}Kwq7evZers`39bfBy!hYS z+up_!t{{7DZ}IJAR1?rkD>(5uY1NsSVXWLm${!s8AAksRpz)!EjM4ViZmPnlySC`g zc=qCy3NBtattsqqZ6__iy=w3?57&`uRE&INV;H&R8Y#KuE|znCQF}Y2jLBKJgWv&C zZ^#qL`0Kz=%rdiDvgUSc0k1RMK8ay%40I=N*0#k!%DhsX99rZO0RM6>FJml+f3Y1Z z_R#io#K`JL;>1Z}oR|tnE8m^VME9M`=$TZpd^+FLQLTM*o1}Il(834v(b>^&Ns_;G zBE$|@4@6JVJnAqjAR2nn5KENoHuCvxKwP=FY&9yCynx`f$+42$7Vzo76Tq+!zMv$h zHJ1@NHTxJZr;H}XjBYegza)B?F$M4NN%f0x9yx>Is8lyK2Hg3+sm6HCS+j9}FH(8( zIrAVDWkAR5vEdN!Nsw6xu}7uS-+u zwZZ8}LhhcSVpk(g-4=oyKX%N~;M|bkQt*~?tjVi$W@TD4q4u48f8LCg(zvFUQs3=K z&d=rO?Y$|?3!WIhM?}1)Mb7Yk!)CVbDZG>j4j)wL9=K%@Q|%5Z99CDc==LOTCgr>2D<;E(#(BT_BxhG*BF6 zU^rRtEyJ5S4^nJ5z2u0cgwxgf7^T0O`L#HdwjULs(A#@b&L0fF5IRh%NRTO*zjp}( z1-@;&^Uz_+z03W_&aMTY_t*n>=WZZLyidVxmZyrB}DMi^b z!QM($GX0%ACd$k@D#XhX?|1|kdiOCkBW>XDSCsK;N{Tuf(=t9`4JSu#QGv~eAq6Y; zQZSB`b(y4`NkzferC+uw`Tq29TOLAaEo9>5h*z;Y2M%zCJiR<4*DSuC@-E~>Lr~y|DPOQNeSE~p=$`w-srL9$ zNtE!nrPZg(YO#(1=mOzTOCJ-}p_#AJieyge{COFhPON_JjC}wyti#sEiD^P!h*x2+Ak<%No=&^6+%{zzvD0XtNHI zOlqCcQ5FDN8VHw1O-wN0G!o=K46S;V)2ykXslzE2po_(mCGPX;Ti@&wzB}+1cFtz!a?sCik;6vzo5@ z$Qg&-2Z5-MPS_qJ#&!8)SaSAz^;Ugx$@HDC`=)Uun)EN`7e9TY{ormSnnkRcWJpC| zLUAyw{S||BFj2fy^>ig~=+w;bEY^@-x9$IG#&ixpx#i?PjN-2|ZbHYAva1oBbI$yE zsF=ff)aGZu&ldxXxDn(1gP$SC{B8Qo3Z5qv0H5q#X{5aoAxSy^OG@Z!vY?@h_I|HV zyhWX7&Aad!1zj2~WjDkSC6)#8+N-%vF*fKm5?Op$-`;iaQTFGllaTcn z8hxoErD0>1B-)R}7d(WBJUWwpRFoy`8&%D>YGi%x+bPdcuj0cqKq7d6N#SpBAUWDn z10$BaP@eK9aTMrU3YG@k)Zx!{Y{dShElsVvon6>7rY>m}nOnpk3dtjWoH7aMjM#V_EJi*vqzgx{-?pfm+uDV6j0Aih{LD*g8k)QJhu7`Z z+EPoP_IuGZ60sh@5*7^_w-#@m;DUoSmMxYx`@1}LadkP=&vt%{5AooV@Kdh7y8(OA zTlrJ3LpKnhnTgYN%{R&O5` zp8$d(#6v-9q&v>9`Al^1OtQ!tPah8cFAHGEs9)c|Fjk$@-zE6> zEy2pS&|_#ip6kCPJbEIPAWt;-cfR&Zp4bpXt35bM+2S_d3f_ zu%M-wcChohb{kaoNvc(EBwBTeB<<{Vvf?7TKXt#FJRX0~?R0>~I5ch3(;tiyBfHCS zG89$ofY?@idb>zoY}%gxT{|jfolr2V%lRmKo%cvpy$N@E_EYHJzdtzq!)4f(If!=s zJ+RrQZiT{Fzg)RCR^C^jz)K3{@2(7LD8q0&sgH*wj$wM>^X=KO2=Oss$5TfN-beZc zs}{7@j|J(z@pffO`n%;#p7!x`K58%acFd46ZSwUVWdR*OD#ch`0#@wr%N3ow#A^-f zIZK!CmM%3mUA*vr&OJ7>vox{z?8Nsg=Jv&oAa%?WMt)$hFWc}k36LCGpT*GgNP&02 zkSoy)i~q<0>wa)@vL*Q9p&@Xbc?bZg5cO(f{?!^ToPr=)mEnQSH3t3#;+!)&I&{2_ zAl+bK-bWPZcud0;avgJOADZ~LCMFgu#g>a0Q1HSK5C;tn9NKA!unmO5RH4+VnLxGH+{<^f08`>V2i#ti; z%YL!(;D269EIHc@XT@n{`SjO@L<}~?=JSKGB-U@jaq8ro#!#Z3F5f!~ZGz^{fQ;c} zO!^Q?PB1Ob%zp-N958p`@u1%xuv&0O)lNxK6JjW#(>DyPw(dUfgU%lNc%)pfe$!{V@3?S2LOVatT{SJYOHEBBDEKmpgvP$da{6t~4Wb6a>^UfW2@84;YU0kii8(84IeH#B6@tPnz#hX0SMw}1)i`~Qbg>F(~7knV0I zq`Rf1ySqC?LQ+7wq(Qn%O1itdq~SSyzWe>R$GJH+=jJ{4zT;H~^@EX{T-%&QG?ls> zG=;g+}*(W?w~P0ZrZmhvi+zZ8!qWiaU-^E6yvH-x2Z9^&V@yNc9z)0Ot|j zV}y%K)H`>@t~;p`ZavOr?Zo?;6@LvNeVuf=eG6@6Hh>ml64xH zG}>tE49Q5Wp+NuejOY@@+vbPqgoYBdlvV>~fF=j9y{VQ)DS%wjZ*w>KuCHU%#J4Xq zoBacGs!H(umm@<{6^Pwq^793uyh@Gqbq(C-G%x2|QIg|-Gz!12!Q33N;~&Wne&b4r z7DM9TAe2fb%=}#Ndo2hvzXfYYPf4$P@X3e_GZe(}7FoEliCk(E&iqyrwVl1feC$MR zc_YM#sJqGWp&nqLk%Ss>MpjP=?u6#6UL>1&6>8ZxevWX-p7fT7hmp!_8R0ZV=Wu~@ ztPY-`s9K8Z>bSeh%9yCl1qIwTy1R7@@EAdf`7GjSS<_y8Dc~_+hk>=N~9w9@_sXPr7dUj_b+?>nwTH!CYcgjRk(Uy z*GdH^OEU)vn6du%d_jp)DOQ!>L%SWJX^+-q2tY^)6IUrnGFnm&K~cJqId|YuIM>n8 zQBhQ?ksMj;-9_F=4@{Lz$GPRjVlY9I7{pIyd{qd~SQ zVF@`FYuH7265WH%ZEm_GnXhkspHe#)3b$JH?=c9 z$sh|BFdzR$E>bo*2R_5+VS^VA{_18tFrY?*!B$x@5~4iqCBi&LyO-yHCxH>CeCbe7L;%&nvZ(S7HT>EjTR)>KeY@YQlF zAhh~u8e9FmeVG`{9Pe;2id7@2x7^MCvcb%z|j>`NrZh*N3G zhFdZ?5=~k^aMp2+1T|vipdi0FcWAdc?i3a!ItSirS_oKC(c8Bh=m<%omNJ1fL$>c4 zWSikXPU&WFm$_ue`}mGr7iJuSx~C5}b|ejJq>0n=DAkw}xaq~{ z1j>)pQByE26lJWU08-^(!*x}t(GKMm3J4dMu(EZ1osYnKlPng1t>$i9MD-ZW{GN&Ig@$Q^! z@JU8&mi8{)9gb`0-S=d@B6BNfd-+6Ab^D#RuMo*N^B9nX+aB|*Jb!PM{Ag);on3Po zWcLpxVm;E~{zM}A0;rA3N5C=(zW(@d%xY1ik({aOGFB6BP2mS&Ods?A&}VR?OUw>T znxcx$Peb}NH({v1`>KO_4cd93trG#s%Qnnfa=94Hm0L%HlecF*c!+vGSSa#h18i=Q?+IK;J1j2MBVA_fq8pHPDh&vGiiU*G1tEiYOSl2QujHQNKw%;>`k zT6_@?{m0G(fv{d(?j#vCWrS~Zk`Yp_T$>5YBg1cZKhI)@_EWDTz-AX*Hi^Ye5Ou1+ z7$2YD<}1GmCeMg_7%B8bHQo%2SW%09i*n+ed;A9GdAr6S#}$Vb^wN|{{ho3-9Q46* z9;o(91*!Aa(`T~fGeT+V{L`sF%yjxj=w^{HES-JEhPa`0q7ZL$Pt*# zUwdbKmzDcQZ$NCUO=I+TUhF9{fe>kCRe+mIgvqHVH#qe+#9w&1pLtG%r(pmp935G@ z7Nz8;3@QAox!I<~>4vC1z@+t1^UOH2Ao4K7QpIUgR7f$&yu&NsA&3m>-30WL1TCxM z7JfFadqX_-STgqW#QSlEDR#5f?-^oZ&XT77M2e)(P2c?=u@VQF03F>>l>U^ponyz& zFXQy-=$%+~c6Qz$Gm$z++<<(H;98L|IE50YP=Z$tbnE#IRC+3f?rDiXZZJeXM%aJL zzat2Q7;lxD%H44VnDS>MBgbfM%S0Azwa%S6>+7&Lsu4}m`5FI=^E>b$cHW7A*_L_# zpP^-6)H;WJhc3^pCQdBBTf8kIF<3o@MYX6D_L)_q(c3Qx!kCZJx?V@9eVsgOLKRy( z!mo87VfU{_`@6NhKqmNnX$m>|fAtNXPU=H-fyU6a&sv41TY zt+2$<-Tm?KtB`Q>?uq6jLmX1D*+V_$sBA@>zn6rKv zoEn#zT~rQ3+3oON|K*sCp&Jj3%!+|#hDsk-TDoYp4j!k6U;Ld&^fYhWb_IX?N9ZKp zZoWJ|Tp5yzizF!l*7r^FZ*68vEc`UWaRQ`q4FU*=MIz23iIb^Ahq0W~C5a68r)+?1 zDCS*!{JPuZJhVWHXnxPwxw+e4r&>6v6oL*(#%-1uP_uXe=8_fG*toMYkztyAa_`fV z1*n*`rhXF@aYE=O4m)_zc#X4D5v0BdsjC3^;`&4eVq`db1Sat8PAt{g3%vcQ8Rz7E zjJz%%eCwMM^}V7n#)v!-!7flY| zwZPmR(I)!Fg2MAew-w2n?tsF7|2pD(gNyvgU^BHp>_Kv62kwx~e)9IdhOgXKDdkX{ zfD{t3_C`@K;|kEUVeJ&)(W}1h>C*%>C9Kh*&yI5_UBDcsmKJ_KF>QK`j-}P@DmQ~# zjx)&VOAmbyr~fpcP5_^l0yvtGl{m&9yAxr>U6g+|9=&zZO*v+#1C`iHgNLJKpk#fH z3;YO>q$KDq1-&lV8L#zw3U`^5h2bGrbIk-fkZ0>+gkjjlRK)=d!@-2JG#l*Xdk>lIEfEaVmr8wWP^BRPjvT%cvgGJ7G7d z6O<@g6{xP>#hCAZ>XFK=`s!p=Z_O6z2;p#&cjMt;p8OU8p_K0*c8%KA$=LVk+7zy9 zPl{dR+edxW4f2GK-IF%ltwNlIp~lrC!LH-J$$T5p5~ z4w_G&F7Y}gM)*i9-ahX`Lg^+L+i4T_S76d|E#3W5wu8#sFylp!lI*>H#C2HjAvn#g zym_0O@R(HIXWf-J=0gt(@a#J>^&f#|y!yD!|87Kg1rgYa2QUwW~k!8A)EaariUg94t zZ5sfy4~YK$J^49YK%xZ#yy{H{;|^WUo2rUg3Wd)Xb8&kjzs;W#JO}M!q0J zMC?%pW3FJ@e)pr;#e727kJfer;ICs=zXSft{9`N5G(HEf7ja+W>LdP9Ow_fI`<=FQFAqV=%2FV>Ztv$pI8%z* z5T^d`DJ{#hffF-+K+8cSg@sZ_Ga0IzSrrYc zL*TSmVa0>M!1EW8g0rhlDz66_CUl-^m*U`Z6)ouLuD)4ZA|OEfn$NCVV5}0OS-mt! zS=vDw)%)+%Zwz?JfSS|R_F`ivm0|h0OuopS1-36~e`sI>ySYO%e8bD6^QKY=hlYpW ze6*tQ7s3t9gP31UEdE9*KB86uh(bK{jr$4fZ~%{tM5Ooqy{5|F(RcU4;;@(>OXp`~D7{QTAGAl%OA2 z#mlmFhQPR;bg0CginLO>IenMo4Fc)TO)bpEoq&mUuH}4P*Sc?>Pe~lH`$H+JOp&5- zInZt>&|{=opM%E<(GD@9Qj*{3D5MlEr^We;kKBZakEFjMSH`%WjTj-Oc~_)O%>4D* z?hV{`Oaf+RyE#gwl!u&|r>?u{_S`)WEF)(0ZTCrqvOB)WQh|Z;sy$lRMPF^7*yoz~ zdR{9XqyrO)L2DrBAp8%v7zDpL$2@n*=o52f3YRZDz%}K4g@qn2@?Mu$4=o63+m28m z;{gg<1lE7K=^fLf8Bv9gD^z#TEE;mfiI^q5i@S+|n-Uzr+DUIo`}$@-vB}!wkubs| z@Aw4pz1*j~sFkWR+p*=ejRwkOIzvL4n&K@np1US#e6$;+LZyp_;LHjaD@>4-tV|}7 zM_k#Wj>XMR4PI6Uxp~*mVTbT(8W-*Q_bku1alRxR(_MeW>?ket2TO&#FkX*VJv8a) zF_2w%dxOC=XEFT3@np>JW-FTgJ|yA&mghRnecn3k{it3?{z}yC)njjqex7z-UrM$& zp@Q$F6|+{o&7(j$v}Fwb#K&*8f#?#&sAISh;7fy0ECqE^wWwxlEnUGE?-R1^#xjV& zV^(5YjgJ2Gf$#b29H)@Q^wQzHz;0gTpFnWN&eSUCY19yVD-@PWPX7LQml=d+kaGs1I9PF4d-mhzseW|C(PI7HmC+xk?c_4i&^+ZzwZjjW zWAf`VfYbY$USVL9_Ci8zcEz-(nyqlyEuj;NEFR{=L~KV0;;M?^PlnN0 zaO8p2MIs0~0EV2kBzQ!>mj6heKx=b~fj-5yb?gD>#{@Ig#22@Pa$KTpYy}2Om(fnz zOrP-YOkav+;oAl3W(b^WRCXp7(3P_F+aj~1NOtNFU(RZ{YMxJS%LhMXoA18+RS{q^gG|Q23@AedQdn zP<{vdajJz3d>%rtbDSdzRSyJ7bHU6>q>>Cj$KX~p%qOIwT0S z^LucG0neOahnM|yDM=$my?Gh#>bZJr1@8MI-e7-g7L1Y;x%3x&37qurh-!fY_G4bJ zQ*_s+p4Zu4(DBWq?+jlYph~n8_uJ$x236tNh*3_XwzKuxW3#h8vTqL6i&e)hrFEsh zA+s)s1F;`jrl3>W{h#?c*tP+ufx zIq+=03D=%lvIW{~IXSslC6g6|>yMlrW~HYPhB!`mYIGbNm`d!80)m=yQHkBkIPc8= z;zcX`UjL;NwQ%g^W@W6;8zw2{8e5O;M3gZKb3$)DW9e*RcNz%9XYdjZ`6G3y<&Eb& zTwMM}_R7h9!T|?b)|ADc#NpCEuHD`_*?&@4pMO$Vs?j8gslv@{457=!4jrOnrtiVB z=6~a7{{|t4`E)z&+!G3o9nc3IhD8OTG~tAB2$cBrl7Kb;AcqzV8D71C*;?grz-BJ% zQupSBXB{KlR${Fs)%CLcL*eqH(eO@JVs$kl(DewC)a%bAU&jyjY)5CDUYO`8+)$`@ zusD1(m8A|582(!1A zX_n_&Jh+o1XG-$ohwx;h2zl(q5U1*Lh zc<%3$I>#OBzq)JrW#b0xW%tWkU$5$}p!1~Xw&&BtESty@O3gf7@da{|?rqM^`!=7m zVi%kv9MN^t^J-->DgFe^G6uF4379Wr%=j@|+OnuRU{aY+l%bZMl0!u|96H7_Z9*TU zr|vB<9$gVM~=E=vT3LV-I&?#`ymfAC9h_D z8>rtdedQWvRes%X467+xXlKg%8~?4F=RpZyDlT4k8|i2hXt=v)I`NI4yaOZmdH>7Z z&G{>$GdZl0(mTR2E$O|vUpRib*X>a{tXr8mK$QP={b-8t?2gKze8QfcUg;7LCnQxFkgMf1G-(yNneCW0^>nP!dfEpe*4qU_(%0LzuT5-}pqu#vqqsAzKlp5%Iat zGbGy$7xvOv#`etxMx})?n{J9BBr0^eaSw@7bTW{7hs#U#6}UV2FuKZ2Xtfr~ zPT7vUa*!@L`h$Ih*iP%Xp^zhYKQe-;Ji3q1%lCd^N_p3uLsFab7jbCdm@-7viOo%{ zgv9=1Y&1VDxUNYpzI-i2+rB2Gm|Z{!)~n*xd=82kfiDwDpqV-Z4qNLAME=*DHOlbv zmFz?n+}k5~GwQs z5gv$80xxE7cPYk*#9ul-jz(3lzLeYL&X@$JDH(a%J`1k?QA9=M>7kcRQZ(|;8H^YU ztMPmGc5vgX+|?*mo4X5<)P3|_#NPyiNo?SrPdols14>t7*ho$pB{%G*@W?#9h zN$zDgIL}OEa0Ecq2gtbawj;o;G_hmklB1g{+5F(vjvK^dN+bNK(MS@5aVy$Ynv6k||yC0zi%k;>d_GPbR-0lwABB3Ev7J6r&;;eA!lF>|HlM%9N@vwe(UK#UxeB}A#-pXA& zJT<2Ce_DVB0y*N42y6aWE`@fc@E=91@EJr%i=S7_y0RbpS9|=PqOv!@{+v!M zmS=Y6wd#Ry6B9MLt;UNq=l-@W1gVT*wwq4n%l{j^A|GwMa`=-#r~k%Oq_Nxq#{D*V@9lJ9 z@)Uo}SBXu%-37xMd5W2+YH(D~)Ahv~EUz{}u?SW86uVSNhH+HyWTA>SClBXGM-FA?cP9dC&Kn5V!p+zL5187d z+D?B`*p0R)a!z^V4K3y3$q3P@mai5Jp#eE#EX-Ftbo4H_$2iDq>#>>c*T*+3hg$7r zFeHav3A-q{+NF~0_8L9b6)eE5V@T$Fs`&%4VI3jlf|HTfg;4z@{ocG~B~V|C8y^kW z&?u^|aUcG9PDB=sEXsjw6PPoFeg&IbqEMxcd2{6T()N0Tc-Fc4*-fvPlZJD!AD#d1 z+Nl(*LRodcr*-7i4+F(gt;;9=b*B|Ok{|h>T+Fze@$pK^FN&ZYpU(Ze7+7095^B7|=kpF!x04zJW z1Wa@SkPsFee-AKZ)QrU>Bk!pCs1>!02s%7}iyzOlpn$OsChb~>L@6pQKb2KCa{Q2Zw&O;PKg2y2{llIU=b3v-CAS4+B0f*Inc(+lJf)6Y>N$pm3`)Es61L?4uFaX)|OF4lsn>hG=`p z3~JO<4-kG2y-Kw1C?!h)zz_8gE6Gw?KQRWkv&$DtI^ScZURR(QB;}*QLR~r%<+@m! z{oJ1VgFWYn`@_#6g|rfZBP& zC2;+K@ZG%7OkAk~zXmQ-0A;f(=;5=SGv@QMfoSdzBkksq{K_k^U%c)Pnk80e$(fD#Lp z|I3Olan#VUFUXKPa=~W$E6yl@q;l3)$-QBXsk}%`SpV8K(}_vfX;2cu1d-tTlJnm>SXVVxaoZ{YMAI*9Q1L1tAy11ura8KQE0a*eSzvduR>+*7zrIYEU@$(ty; z?h9koJS`t?Bq?D`&VphHzA@Gi)z0|dzuPkdgL~TDE0X+Z)UG*bz8mR8Z*EwcD8qI6 zViVLja971|^Fl+G*@$QD?gVr+j>KQzaDb^yj+)J=3is_Bp}!uE9natuY-}a=eppj! ziNu#T_#OUCFbhQsLQKK6IVd8i9(xb+@|6$s!Y^30C${|*55K9LJ`|gL#s5YMYr7fr z9w8=ehpI-Tml?=1!ux)1qt|Y&@&B*7mO_qJUpN+B@rwJD>ZO)CM~w#CR+4}RV`_T0 zD4vH|OdH}EL+VXc$HCEJmr<)aYd^}!wt0=so_R0I4JoPh;ow0m&xo7E*maZwuW$z{ zKw<<^scc{yo-%Q1r{kUAXNeJTcyHSzV9Yr2gS;%EH@g`f+EgUy048C<9mu866Pak& zA{#LFhSm=MpxuE8Xq7=o-P+wdm|ul;NNN0g-2Y+hF5jf%*RVLVK$2T-*`C!Z9)qdu z%9Te?x3@|gxHUy&iZCL%pw#6*gb!3VXwSr@R}3Qdv&FhU>Sq|SZUx;~05c){jB3qG zmo{HJzh^l$h>varj0iBGC~U-Rn$zw{u)H@ZMu!guGJ7zxmjGk{B1r}+Upd0i{>?gn zlTS0?k3eIK0aY?ECFFLj!k~X&@H2EBh`Pg%34I$v8tEVKOh2x6Fn+Jdr}irSbwEkt zE#CrnLu%35ujrdg_+&y!2EDOtMV{z5@byiSf0r*Bd%oY)VrHS7c-Oyy8x0d?%&9ad z;Yzzi4`wq)Bt-ktUG50HYAS#m3`E9Lvf|xjKn2`EjMrYbyD5zN$Mkme&Go*lqA}Je zVb`dzCs5(Ky~_Ur6QD`t**1 z`+|^^K7~w$bau;`nu6z@WQFr7S{=AD;{O~#T!X+Tp&tOq3kcz<(geDsG<-URZz+?( zT8yvz72nN{)$X@cO>{1=7T>*6XJ*we68oOc7eP_CK#3N?gC#atl~u}0g50%kA5P7} z84!mgX?s&knUMx(R61Z%ZF*iYw!3+xm^kgj@gGEvFedm633iEk?+hS!7ZSQ`BQ;em z<+zHb3Mb#JQDDq1cA>%K=k3J+8nRxI|F&EOCEelj;x9{SX_BV-$jA?_sYuX0fuEN~ zm)iK$)#=7f8jP$hIhkxnv}4?N2Sc!Rz~KX#S9y`w$rGv{Gh|quy$iMiWrAEjDUJg* zmEeMlw-NfB>{!3G;ikhvqwq)cCfxw;ek4QQI zaBT2hV}07#LZUim9^s=fRskjxhWSGjhG0}pSP{lbpcN9$myeOL`J73}gc7~BJ*(h| zU50TNfC95_Px-!RjWKf&Q$k?%)>{~`nD~~!p1;2{2icTcyK;x*YW{qnUg1A)EyCRB zZ)h)a`^KF-Ktmy`V>46Fy~Rpl)bA7}!2l#IhO4ql}so%;Qn~E6qVz= znB~JaW#G#h#a|{}F@v0|>)T>-ScoY3kzPq=+%8~`5G_~EX`6YQC?8hc{M!sjr;q0J zqt5ZxakiW-hkUEWZCsE-b(eaq0~CL)&7#Fhel9A*v=QJdQy=UJ2JHn%N%nV0Pde*c zkue$yipU{@Q3BTH&PH59hI=Jr=7WJyBo~MEoqxYTSo=fg>e}Qb4(&ihStC2MKQOie zgPcQAAq=o`aFej1N3AdG`&REKr)b3AL6a>tvS8BE!DtS1o{S!L8&ACqK^HC$&D%6h zaY!{OBL0pkAD^VMY}oN3Rk~yaV;mQ^I0DINJR})rvkn0dg26KJ>cxwi+&<$9bz-q; z02>5g4vVG{Rioe1<)Z`BVVrG4e;7&21@@@HZ^=$Qqu_3`4h9o%8cGAH*GL8VH+$$U zW!~W~%QY$zr*t1GNfT1W!CWT-cGTTVvP^8>l-vC_S)g6!u5IA6nq}oA?k}Z@4f=HU zlJRvIi_(G`Hg`=`^_vRSM?^f+_^*V3D;6K=VU-NZv8eojAGLm&&KUhIsk43rv1S6| zE^>se4}>`^12kNX94Dq!4KbHx--Q1%OcaVqj1(8Mu1KpJ_|LL}`w;WC^2>lKv-5xt zJ0?M;hIEX&L?uT_89V#I$c>YMj}?e6H%>2uDgIZklJch9>BDIfulNVQR_%XjalU%5 z&*uXF>YgboG#~bfjCwcg?)0UitPHF_ZzY55yZ(W-aypbwdM3(iwBf)!YVc#{SDIUU zP5ojX^vFKwlfxaO0V5J)3@9!w2FU*iRzW$1z~=a(J7i9sR^kq}|65dh7CYC-K6DNd zS#Gn(Yg41gEGIgO=BdAa6T13uu=0eP994i_Us%Tprj>K5nd!R(fm|`RPpqmq$ zf!R)+YneKAWGU0*YXqd)&+z!+K`0iI_eqF<%n(2m&z%Tg+dTx`4Mb|RJ#DEl?{Q{l z@cmEyA+j+HCb2idsBf!Zir>9DPg?qG9>0%mN|4K+>VTcq%jZ5(_TcN%Z8TfjvshKHz!BE_cw9N?0 zuf>>KSR1q zO}$!>Ob%i~#mik&22B(vVx>fT&Z-D#Nr)8Okd{eLQfNM`BSa4L8yKkPM*ZE zQV$g)KNi^Rd5q^$Nik5vnp32_Kn^!VIBx=MA4a|_Q6|cB5rmux9j|nEd)o^f2n*O1XwN?P zba?b;I^EU7v?lzsI0r@*bZJL%F{n2eAk^$b`bB zlTGVxV^`-CEufB(XS@3#yn>Xyb!Qaync|6gj7;06^S5+~e8nAM2}aysv#qt{o0Dor z%}lH#S?6%VPXuytI50pfk;y`HT34k*U)u8d8=z0j15DE%JfqtIXn+w{4!MX1m8)Dk zBu9jeaj4nq7qia&jE{)h}o+MQBCq!v)V@|%W7)S z@Oz?2;&gO|oI0qmx0mEuFL&Q>*3+`OYT|^d4lV)yHufOi0Gv@Kx z?F49R05AZg24@3pwxFxqucmeV*_uk$%}CdFwcSGnjti0Suo%c;2bU-Oxz&kMN*|6a=yC*KPn7t}- z2Wjtd8EaLX_~iq6M1Or-nu$G5))( zpTgRaSAO4XBEp2hGwcVxjJeh62q5b(^(BeuwLf3r&>xiu1V?fkl#`40KUocx?ak+J zF)E7IfypproElQcWy3>3;{t>cIWkgX+oIzWivU&SaU? z4E|Fx67nO#w_ofW98V|#2~_ftIANHc*>yPPIRK62lpVd-iE~x+k2=s0Ze6D$xt<`9 zN0^W^A$KWDjfEA>)3g-L8&z!#sl~o4A$JA$Z__C$i7c-Nt}1xG11lmn_G6$z_|0nL ztHrbZ`p;)(87iL?D9;X$w*dRQZZ<{qZC?aSvIGNmGleQLli=7XY*J7TGZ1fZ z=%Oj+Pj>0*eJEyl&pLnKWgAw9T=C_31e#Etes>dEv=e~$|JAUWa-Q_7v-BA!;+`&7 z9f4hA21tbVK>^}8F=;I&Sh#8n3uVGCDkr@U4A*tTZ_R)Vu5awr5O+Z))1uPUyC(z% zD5&Q#3ekWELs3FBeR7ZoAyB{4fCDFea0#&J!hlX^{f^16LTZ5czl@6(*8|KfA$tgr z{qjSp*xq3cKbOHRk@9uLSCGu1HNTB^x*i0De@w~s2gi^5Ri}&B; z&6xCH*?alv5fgSAqco^=<3Ip%rB%-+gNq(^01cvD;3)w062Z5=k$v*LH`# z7HLK9Gxvx`e_GRBtvr){K{XTD;;qGlmpF$VyS4YnUJ&6<9QKshP7&UD~~dkr<;!hsgqTyB~3trrfwwRRm=0^M$}loDOJ;w2#1#O;u|lf%>;= zQ%86h2Om|hDm?Kcb%NYZR-bq4r_E^PH(GbgyMd8PW#|lS(aQF3oL+?;wW(NUD>x7k zkU?ZX72jjTko)!q2JXCO*(gAs;@Ba*CHL*1DjgGOFcqEg!@wT=9M8?l5kjFfVH-Ys z7Jp~-IAa1Jr&ay2JKX?7)PHYh-1v#Z)MbsWMFYqD&?=eI4lO&2@YvapA@Yn)8ku!E ziyFt=%vte*gK`3!Ii$MLt}>hbWm|F1_wS-4Ff;&ku&hg{NcWwuYnRT16|cvLrDu~t zlat#0U&n`j*5QphgRG5XcT0{|m59ggK5*xz@mH=|E9};f$`*bqibrWQ(^`_4X2G;zgj4@_3yrq2M4VOhNpq_1KgI!mm0U135V&Mr(J_& z_B6hG9*X&7Ng+w%L7`uC*1dhGN2r*jU*Oyw;6FH%eQF_FRQc=NygGi$)4b@~{N$?e z&pXApp;>zVlt*}-eW%C98lFJzZEvhG42IFK&LZ@=WYfdhkM%zjOr)LqzaBkx56o#+ z`~Cqp-+Bm+4#Fi%-uUh~3Ayb&yD#7Du3n#Xx=r18wzI)Hh-qnQ4ULVpD`$|SN4!VJ ztz;JRr>P|{fCXka^695L z^HTP=`W>7eVoPKcq&=sY21|?gWl<@AT8dKYC}o?PnudmkzS47PG%+?fIyp5d?oMG0 z28uT60;KGUZ$q?tIH~mOS7lDZUqw%0c#aSq?2zBk=nZltXg&_rlm*L;5g(kkS7_%k zA-`cwq!Z2}Az@>k@-}Vm!v+2lzQQzNHPOZW53vG!z6E*o`91=I^3%TD8m_Lf1qDXU zQl6{bD0|6#woX$I#3Td?L!R0zcIt-@FBOwC3)A<$PJd^jO6y%HbNS=&k~H!rEaXry z-1&(;__OG-GWz?auwo=94;$Gl{YBEvjGkf>zD<>h7`&`Sqg*F3F-6F7J8P4(QUCYs zdnug0MbEDj_*t3iCQmNRBp0-6v6prM1)UpR##8FpK8fP;)Wj#~ds* z)!?-T=s)z@T`e$W2ni_aed=w=MzrEv#<;xqJ?m=kd!*DBX_G3&c3(?59GVD;m_yDr zxE&m;bCk#*{Ws?8R952sonQT+G*#m+rLT_Yofri^qCuO8`-XE$-*M4zv8RIrf!#)0 zY1{c<`dsDu#YB8=1k3Uoww?k3>M9ssy{UnZHg;f-Y4QV_-No#tfZMQuVr6eYb+4FpAT24-8Vw&v` zZl6H8Gd16}n6KWpW+n}R9=o1|a|-WQ?Sde@$HRNRS{NF*Q~KoXI1=j5Dt9vqLsC*v zCdyT*m$#&AE(p0jBrVr`j3>(387ZUH)KqPpibY2}owZ4Y_W8_ROG&9XS*0oj?|zh8 za7tH&=;0zvN^;8WU&c@}lkB=CGYvZogSc&lY{EzDn<39;(O9ol3=E94)YS01H#_GO zESZAyjMBVL7qvjVI^|fawd*-n(tetecW?4#o^|=b>*i2O$UBRu+g?M%J}V<*>h?Aj zgb8n;6MxD-IwJJAWsK?GT?`?>HvA6ExtljQJ8B)K727?NFHeuM)^m8ZnI{u3XR|^r zC%en7ReC{;bOV!C?d~+Rr=2>wMY>_5awKtd!#0IpS6vFeS!eah?g$**m^z=UvXAca zeXZ0!$+TT2`?~XQ-rP*ENbKp9E zqxhQvk?l<7A0K>Zr}qr+$MxK7l|tHe!{T}b3AzRoNlF_Uq^PK5E8)2NWZ5mPEcWh$ zj4K<&SB$bZ@7r6-M0?& z4riBh10UaFZQ<-~^hQ|358&qaimTu_C3>N`$GpdU7(O-oakUi!krUh65hBJN|s~ zdW!R>z_GLsKL{h{@L#qxzZf|xQ&8;gGjQwA5zof`J5^b)^vy4bA((3Ptdo&#iSnHheU{}7RI}H=mceUIbg%g8R15HnFgv^106i2zel32afu_S;R}v;U_+OzI82Q0t$tLgM&&+N>!1Ok(H`;oagsf-ao~D@Zh(e zzq3nBRB;L&+trq2?e1Y-+;gWS!}=~I**}?^nx|5~jv(Z*jAkP+IbF!6=VQ(Or$G8I z0-hItUmpxa&*a^NQfoDhFHD3@pbFuP&!P1cGA3(oVx)=Y2JAWGZkoWdHV&dX>=pNIu+kZK@pC@*4IDJ=u zbr+nDfWvqP!CYzsx?)w^;4KUUx7zCbt%6WW5$YXG|C~PC-QFh3^x`bhrK60uY*ISk zLx^KsQeimJV#s=2+)J~s$65@YpSc!sQZFq(5&iH*&xZk|8cZy#;q4(cZhpfa3HiAG znl*$ji1_MLsglJv(jfUL9|4EjNMC->T61Err)7rAU9f4oYZNJ#>ZZlbp1r(Zu8l?m zD$6RUa#*H9pwD^N!~jmrpml_Xx`5r;cb&}IE{7`R@IFirp1*0R!O{G-N!BB4N@#$~ zW&f-1n7jbe~WbmzqNTnHR{GLHSy!-q_t8ie<`{xS4%&v=*@K>Z0F0? zc`SQw-rFwK$1D|eM$T38Tv3xvF-UVvtFeToNfmA(4)nW| zYQ8e}yCgC7D62ipdndG7_;T;}$XvcMxp3W{57Qu2cHal>8p!@FF_EHjmZoyHu&RnB zCN?WuXR6Nf)=;>v7cq*W70>A)KRz`IM zi=32{Bw>02c}k&iD;PFR+hV(F8?y8*_hgMyB@uLw(E83 z9JcAU@$mmS?(R^3m}1bYm?3Pk7qKIGFx0PPV$v(=Cz&(TO)`^~K5hunL<>`NV#l8z zKMQZ^m4LIc`t(Dl-Q%<6XH1b* zQBjeE3CWvyPcj4n!L5<_GllIu#{43)+$P!!0s?|^^2}bdyL-LXov9d}BYh2&bY4H- z;5RX~yWdEk*P48f?*`jPZ~6SxOl1~1c^w6JOm)Nc6^pFS+4$Tq_|wAA&GNR-2Ml`U zVDWqq*|4WWA_lE|cdj5D$%Xig*K?|Q{|fUHYp0E|j>g4&xoI=l+cr3wJzaYCSZ*ON zx-gZEIf&vP&O5Vr93wheynvckSG5?^Y5zM8Qt~Bi4I1>_R;vdGgfDB)KlU^hA72U( zZ)>UlN%|RMi=s|aOnWJJE>a{4^~#-r?RnZM$SNi7R&F=mHKHu*gbjTECs?8?*GZEo^sgH+|> z%8$b`LYYKH4CvDXd$)C!QSwFfQ+~^deZ2U1;dmFLX;{AB0iB>7N_lEUq~9&7YT`cZTasn9kJW4R@WuGL_+IFVNrb) zXdbP--i=)jOSZCkdApm{Ws@}WUwTWlrCLr~9$N^WpF75GiowuS(@<`@Uth4O<~Au4 zgBW9RgYd%d){ePlnZp z#urOV)`E^DZ|7@pbyOXVyjzVDV#*%;6&Tuh-6|Bcv}D;i>dxB7Mn@-ldP2Sls2Ukz z{TW7K+G2JmdM_m8H&N5vxO^g^CXoHxS(>D_p>$g=OdU+2p&VAuPEYvTJHM4@P{0mF zH!wE2_y3Xg6>wE--P=b|kQPxnJd)v#C8li&v|5(DRc=dnWF z`ud%6To~Wq@hV^qmb}RY8GydN{u*!(2D-c|DjU+FsmUkd1pXuj?qA2&w@_%#cW62b z;P!mg+bc9834A=QoYV8CR!=I-2u{!FZ01&)L?<}wdXscNgAJ0}xPJroCNCl~dM)X^ z_}uX=`@`(-;!L;001Fj(MDVoHVek8QhI>VsnPfNwci$R!DKgA3o7?Z_B5K##81)Mj zCgP9gU;K1A=cZh1i(_T6PmbP+K`O7!RLfHy>4^BA+pfEag^q?P7SKDi*ZBQs;CSoz zcT7UvRFsq-w1lm!-pNhW8Ym_Od<|gcW-QHa(r(D5T~=%$Cnsa!;D}SgtU1I)Ti3YZ z9~gBu*P(~&A0}Nfs~Cx-jb3ui`1y%^(E78w`sGinNQ6y32UZO1KvHYAL8NGBrllF^ zC$Lb*O0kI)BMYbY42c*&Te^2^h`CPG$ZIF_MjiK?cW&Zp49849}bP+d6MZ3{7 z4h0ou?7nW_$c!}kzfS^Rh_{CBdp|$WdS&;9Csm7;6Q-w<0hdH&VT+rp=DS+t3vVqQ zyU&oeEh}pG%kGCjM!~jhTQ;k2%X@Uc&+KEsK>q!)&fSga)O9qta@E`lYWYpIg2kI` z@?5mOQa*<&d5i#s;=`ory&uF#vz&VCZmReX6j19YB^*0MyBuvy>h@Y29j$yKhzwl#dZP4 zJrk~3a;4||sb#kvV^&_^KQk6rXioUVSHeZ>%%u^p(STRrL#HlB?l(LbaoLoHw#BFH z8VdPJAu`|is<8E-@|tF{(fV(C!j+c}DI5mV3sB&7mA-FlC}GEPpvNJWJ=OmbD|e>Vm>yrr;p3O!e+CFH z3ysS@_2yCXS;LGjO}>{Ur9sDi7|h?^`bv#}_tVf2oJGv(#dMWGrh;+itzYBQXwrp# zn#U2fkai`0)nA79##DXYQY9?Uz(PfGIWbvwHD3Q&#g^koa2XiPBeL}AvwFKVYyQVU(B4`zpykG)=!&qIy@pUVNgua&x4nGVfIHG8G0_;OBOrmauL9R&t;H zu4k?p0f8o6)&Xmqk9fBf8QV7eyu#(t-}}J)7$_Xf_3oe5J%9Cem;j|ccr4h&nxy;Z zLMGxt&?;Uo9HEq2BFfEOxPJ7Fug2oTU>Vz017#&R zm;0Z~hH@l63l#6%7`u1y*LLW=fj>Cu_nKs~S|p_NNvvG=c6cz1=pAFo_GbO_NB{Z{ ze?Zi!%f4enCTkJd!)&#%o~x9Re_$ynXDbgCak+$=_jdmN^%vm3XnnFxBTH~IiIql~ z6VOjIm;X8leeG)Pm{5yI7>(?4P1#O0NW)(9iT}4<|2?#$t-6^L@6ZOBBl2l$e$oZ*l zZhSBTre?-weJ9bzi7CZ2@hG#>g4EOC-|f@spOCK5KHCAHk2RTmU_lAFhD5lYBemlB zl?@4Wp3cm=m%x#ala$#Es~BCng!W4M_}I9?r$yZL(Ng>Wj9l55u}UW=!F3E@=4Tjr z1AWM)eYTW* zYp{CXfZG|H8?lrau>dBd3n2Mot*_Sz8-iq9(&5+%-v2Tc;z59x-87(Ac&IvP&bRQjU4*$DxqRwj%^%}$0#Ct3@ zry=uYH5-E(pKzVsgq78ULBU^dfk)5k+%qef{7kCR*y80kupdzWV$Il|MNevFwn2Vo{wNb zFfjj0M1Rsw_~f^ZzA642;Fv#C?jPm}1|o51H|!PX?#K&ZhHHTwW0eJL$J>LRRTx<2f5%By z*~G>Zc*W|X4KnZw1{bX&$PfQBOzb0|V~6Jn7mo>XzcW2uUAH`_ylBdm!ei~DfM#Qk zpAa|_eKrW+*a=m<53~0HW8paeHN6L6X$O^2L(Z1EksafIfGzgPd-!RInL3w!gAK=& z%dBgr@+rv80CavU1h0%Ov#H_V?Udf0&1Zi03dE7Z)W+n7XVCH6Pw>FhKyK4juZ+=3 zVax;OR#lm7Wf{JUM7!;Yf-h!+FQAj=h|!Nsq|9envra6eaRaf^*zU@xK>o&mzJ}qe zCt})j1)Y|jR4KpZq`X@h2%C`1m$)ONcsfjM$Vi-2J4!kZ%Qq7~)f z>XQOZ*fSG){1H6oleOKjG#lYZ6hX;)|sBzU*N?nkTo(sY= z06G93rmvy1#ri?R=yt}fmzyQi0nrk@Sw_0~hO~W=+gPp7L~uLRe#Y6_dCJH22F3@K zfc$hY$4$_8mO2F7_6&`lK#%uw=3PZa72YWCWaaSGfYY+k_J5rG-Yr6qY;vz1v7M{~ zI9x+RXeeD_Ir0&7n!CPODxv1Q2ekxEe&L{f<%p7-S?|L^eBxA<1g&Q6(%2t>>{$Sm z#wx+kPh5|sZ8kt>hrR@OXM5U)1yR0|o%ft`^+t<`=6aCfe3`5n2(jN{J^Dk%Yb|~H ztBPpFQ~=U+L`@k4cPfhl%*$8A?go`{%mdv$f6vqUBd-?C*!<%gO?%Cp8(vV2*0&WIA0PDJd)vAP9SDJ!d7NWe&zK&tL4y=KLV&V%M%1uc{h2?n6Gc%|Dg6ieO^Reo+Pft5ki4>; zdTATKAao9FQwUmN*34Dq>t_UX@e}no1;99pl18$m(OGWd(r-G4j<2?~ukN#j-rlMQ zbV*rjIt_Gp;5nO)YINoFjiT8^v1bo-9mYNYz`)8RfNsK_{sBOmt4MO zvpvU#^O=-uWTv)TOhbV%ZDy>lcL?s9la^-E6mibfYJ@=iFxxmX)zd&sO;x>9>lVPQ z`T!)|R4=~GWoiW|rbsSRvGG-%b)#yh@hb*26a$jLK~~%kzk^u&r=sBXY=QbnbWW;W z+*HlDQUC0){#!8U1900YPMdtLjCuHOUud!$T-6}#wr`Kso};a!TPKW?7~QtPQ&%UU zJ;)?m`=8r0Fkbo_w1SWaaTR#`{fpTKFjOcebH4Iy{B)wJUHqq=kbV<*QSu2~T9^Z0^-y0adhlfnP z&z0X(Yl7&LGXeFCeF(4&h)+EqB+T-On=UlfH`EscGG0Z zcTF&x`(R-TA$O{%4ddF*4xh^jSK{BiV`VMnC?hx+z$;07J4X7Xu9IP(Qe( z(lsIny^Ol^&=VQl2`21xHq686uxiHn@-47L84y7r1pl;%2M*FFQg|9vQK{pNMnjEw zb^aTS^E*${kV#T|^K}dN=%>zyOS&ne2~9?$P4#j0YoDD38=S7X8z$^-TsLoHKFj--|D@>n#v)-RYlPvLY|iM8a(7t|5SW zls25 zej|)-Hr<(Rv?D1Ysno8zv`j%s?c0+m(*37SkrBGbTRki+8Rysbjp@0|Z^hJCKs;6Y z)wQkzT|Tr@vL_VruA-FmS}T4Q^U$GmLE2v$+tslKw=JQ$3d?jB@MM2A{Jg&$=8?IrvUsmxfmsiYAt!QkOcOtG^ z*CX+te?CAac9GNVfF@>W>8#NE5cS-4y^yLx5yf(J%$1_^)4qN1KsQknQKR;?ZI@nlxGbz8L0z(VH-6h%FJw5aW5a@y)c9GrBi&!<`};%Pigyr9AIT)tz4F zdO)~s zW7XnYzz%W8D}&|UW)FbW4JP(RKp~h`gqtF9@!Qt4o^cD{hsVNDE2{4d-tEpqAXWa^ zl_LuxC;<6sYZF<77OaM|1iJ?J`rc}ko=P(lK<=5J5e`_)y5b-}(MU900Wltc$aGze z5(t45JD*Dj?mk&oH>z^2vd|?x zDJelHiI%;!-KjR>_$3g8_N zZ)Fz`5(aLG2@oaLTvsE3dX&iuC^X2*H-n%C(|-lTChO9FX}wf%x}ro_9T!3PWZ33t zwWkppok6j^GoyxMY_9+6#+b;|=$@VH>(@M_0JtZLR&x(-6D^EgAG=`mCTK=xqga#<1; z?@5^gQ|0Vjz~Bkzu9E0uY(;rPM6PBHz#$am60;H$saucU86j62b0UWtuqu30>0M@W<+lqaLn^RuILk`g>nPSl-e_bA!!$7 zz(&XkC$e{VoDy=QaWd+8D$OWVkYHu&41;?WM#73F-NW|6c`y+K~N6i(vm!P!ZVIp z52GuJ;$oYOZM4)k(*e3?=siS3i3G_VF7l~y7S`ul|C)Pc z6EOGlui6{L)Bs1ZaLeQbia#*}!5)xRgju&&;;AfW$U-2Hl*v8LcP!DaZqbl}%VVAq}P= zR6%$1$3HN+aRrJ15YfcUrg#*juQD4cI;W+k#J* z^;~OAQ&Yg=S!Wc?_1qsnefTli?j-XGva99MociZgJ?O5Y^etr>K+@JM%GMGlawE%j`WtvBEK|FFF8*wEuc}%A`nle4Y0E9Hmqu22-ny0LqIDLO z;0@Wv10qpZ8Wj=od#+l1ahrUu>YQi$sO0OkOy|t~_ zV~}A)loA3W6yl;^5Pe~QNn@xM1@G-B({Nfy4LZMa9?8r{zs)B+Hr|@51D^gny>Rf5 zzl>ygrRF(4)0k6ht`7~DDkkY|%1Z`rq6W^_Q`8MYrg>VZfb^{|TKG3adG|_^e=jTvJ zsZ_v0lJYj3{VC)~#Ml6z$=Hh8hy3*WjZh6$qt_5H!0%zh@7o)AqR}Nz zf*AQ}wcJ--Eb4a9LP;9-*OPseaT6@QsfO?KfCaW{KmBUNla~h~LR__OE-h##oKI~A zMw@{1g{K2Gu9yKv>oe|%>pidJ}5XYs!nww0V2sA&9bpWgL$9X zL$VL3Xx^V^q$kc3AAiggKL{$wp->#&e`%WpwCCz2Zgi-NkMd}rDX0gIa$%>p5AiZ_ z3{8F9=fBkpB-x%}YycGtS-W>MUa6a^k6LU-5EIYfDW-c3SRVHFe8t`59SLXLkS&xA zGc~og%%^U+5tf+Qem1}$I`I(M{LL6uCeviayU|%ikX}m5MQ}X2EB%daq)}`K?$QC zXeEC%hgivBt0+3Ut;e(4;;v)CsN!ybWx{2e2fO|MjaUgSi256=zbfw053#X6t^y#zNx`23} z9wTKE8D{ScYCB{RNNWG8MCgHH$41LNW!nh{`7Carm>C?hH3M-eZHP2-yzjQ zSsVvCZdQt;G#~-$_cCGW6>)-X-a_xu-Qb4vyGNkvW!x%CFj-lYgUFQ9L9dLIdRwB6 zp%PF&zuH%c38|@;#^~BQYPbkj3Ia)P4xq#~8bmdk+_9W7fD8W_UUs@@DXgZuSjv(A zTfHLoL~HUJArb6GU8iP3QVm7D6@@J43WSggSSzPuvH)gLuUc@MGh0#Q(Cyp&v!5#uS)q*#2$lOAAEle?Y&saHc@5JxJh`MuF`4eatT<^N3H1c z$Vcm}-S#jbKt`yKKNIM+;f!@bBnA1$YalHS-Xu4ej7xDg*9;4lElZUrzC{GJ98^Rp zo*QH4l6RR}6d#%GJl?t9CT}*U4X=>ZD<`80%rM+4X%FaJ zM6S*OAlFB2LYSp@Ujr%G=Fx*jjWeTsJrY-1Vat5lT#O z0>PBBv$TBc`eF>m@1?1Ue75efKg>rSi}vG9ijrd^?=DDqIu=V5=1=klc4B&0GHRLR z+!_yWqgr8|c~1W)?U}%)uUfGKjrP6SX9_nge0<~2fuQmQP?3aE-T-jKzo%H*#&_8D zxc+5-J5^JjnpQds3+Y6Cp*R3bwCr9LdHMLz! zj?5TsErGN$-U1!fD~Cr%`_MQ8YC=hCNw;p1v-^Yy;Fy@4oOd_KBl8oCb_TeK~>N!A^2`+Wu|veitB3OPwi_lTSLC6q%eh|rW)n>R4AZ9 zq(@1E7mskXX`3%KtYo!o#U|?<=(;1(wozg`DJQ(^!|FsfRGbVfi#v5a!Py&|UyccR z3;qo2JDqkOQPLdK7Z;Xt%6?xY@V3%4u*Za`KzJ(G<8XqwS=;ysE4STx^2c%{;q@kO z1~F5}B3eryU5A>y_0=Zq{6LSO5-Hv^J0xozVTAs2s2&EoloUzPA_vq<+K}IGUq)d5 z3Ez9Mo{qqPfe#{RIQct8kQ#2jomH@}D;=k|iVT44j!rYD_`zIh9zy3JTWO{RKQKQr zWXU@o@}LwpjJ>XCEwK^R(KABMR!w!eoSVOEz3EwP!Zn;6=`1>|?_0YO{Ufl63yeSy zo0=gyx;96V$%c$m_L<>lX-#F0bKx1jnJkdZueP`H$_&Hv0C5O%&W>9Yhw+mU6iv4s zA}p4r7*4T2>q1jW;ebod1%|*pswtszC>Lk#3|oePuv*U)lMXFu_7$fSDCET-AOP@NK$`C_Y#YWg7iltO6=C5xch4n&ama zNqL5snuk9l-RxF}5&=;!Q?ind^hJy>!l!#nel!%UjcwZ4vCc0h7(Hp1o7Bq(;}=AO zoY>+L)~)e=VQnXuW3?BfR)m?#?=Z&8_p-B%c~G&)2jx9n?IX0xMA9T=!reHhm;(_vLYQ zCz57`!J>TP!MI13#2@F;c#FmbOvtBCS#mzPWFGM(E`mUatZFW_HSkv1C^{W1MK(>m zCuUb%1B&$^XE(Xf4H-DI42<*YR8U8R875Gy0?g3D;8J$MwL{Ddxeq1O$gS|GGDNjB zoXkV5jmr=o-1TU(3=2PzG)Pj0FTeR7alY1!4Y|*AzL|aM7!XBqp9TN2tpTgKpala$ z2tOoeg$~eAWtu9vn43lcSO5~`NF8AUf(r3`V8_;N-uj~%NZ7(MS#Q}1Gyg6&Tm5o> zeREs7?GsxeO_p`UM;-R>klYGH1+f?^S4e%y_|3F~4FJSwD!H$zemp+%80b01Kt!D= zf8P?=w33RRE^hzYhP0mBbumnr0M>>Na;Z_5ZS`o|jDUj<9oZ*O+zb-hWI;tYau>xH zxDUvbKaI?$tfD~>QKV0EvizG_zDKbBNJbn>M z&{!f?pDAHCo?Dx~Xx64g1EF0**Y)oza>kb~AJnqXq`@QstbdbM>dO(ZKdrXinf59? z9mrUKzEwcT%EvXskPQ?YNLNj%*q`L7LL45q*RpUQi;A=(zzw+dwT-;+<@?O(G$s8B3&<#6&8$B6`GKL_-NZQ0lGWuF$*JQQwh${WC>e$2f}3gkw}tz)Le^iqm>Lgwn1=ztVYmr@qUw41JKIOhLbhdmL?brf1KM#5&p$^O_` z#g6ww&c5?2EG|J(3(y#1Cg!+-hY^C^f7dm6pe@+xw=VxV_eG7cfpZ5=Vp})Dw=nC< zGc%X`hI@hjlm+Y_Bsr;21?*`yP|krVLjt~-+{7ARsQpJ2q6Z&lX50HO=ot6r}BNd-nmdc1lTF`MyM z!6qin?Oc@CH2&}@peOM&cPC5HXv6M0gJR5+>EiRzh>+>bEW3IkXwZm-S42c?-E0&H zl9Fr?3-^Y*1!}CzR*ohh8~e_bzxwNFMHon1K!1^Rx)2dgGyQc>bzMqwcnhlZKoT;H zQ5jk*HP+vMs%<@RSR-Z*pIu<-xY9tzAf#+(tm!^zBCsV`HtOjvNVum?EoeH zGQC&EgjXCn?x*d}P_kf9uMsSmB^rDjZ|zm|8yQ%A zRg1-eXbXuHAWfz|S#C8`U1Uv#8v*^hnvA*vP?d}s?x?5Epe~j^+hka9z1%&*5i@9O z2cX4a#jhC-gle9>KH;nBuRDEvusI#Y&aaV%n(jH(1*9zfA^fUDD+0j1>f(7@hh88IxS?c$v*m6lzoUJYr0AhW0;lZZPrBFAaJq9NHwxOXq z|60qhQ2C!3}h%>oO6+ny&FVy>4sTZ{y!xUv@+ttxnXcE((t(vJ>Yex4BGqnZ;7a9-@cucxfZ!_WZ(pfA+QQ%_b(lFnQ+TjEE}$p;Nyc zuJfMO2KVg0njXI#GgzYEffy^B6GwSlu?u}4a4>D94R^2+#Bvr)M$4J0hy~Bxh}y`} zT`j!2s%jeiwxZ?euH}Aky~hg*FET-Sod&Mm*qCNR@?0~iUavgT<8mJDy9l*OG&nN( zvEAwFb-C*|*t`Pl`|bCL(JQSva@PpDShJi657s4e{M-*wUzQAaFWan*)6)m`X`d>2#soV0uLLB#aPE=7M1 z!Ll@R#SxihcJ*8HhP;5lix%c)VUb>wkFW6$J_Q_nJ^bZ;(~x$tAZd~HXUkWnla+xZ zRom54v_*Fh6Qf$AX5Rts?oEd))g>@DG!&VcnP~$`<#u3Ukq5J^LTK#Q{FR?+D5tJQ zv+lrC)NQ^wPW-TZvs2-B_>Y5t^caAN`7`65GK~o^g~=0pCSKyO!q}X1tK{W)hKFlb zD_y77ciTLeq;`7Ce6jd=nTXdu>94F6AJ{A#5=Z>1lPe_wzMaQ(=SjrMKz~du5`NB* z%a$WR_*kOOPkHsZn|?*AC8Y+zvq&G#ox6f~B?Id(H;OVG_qmZLM@vh~NW}^@Vl)cl zUimMkEjn#wupO4g%=DecK3}%?*X=E9vf55c1T$>7U)5;Dy_=>Q29HI{-=90#c9Ufr&bPAB{xxuYQ8ksfb2BKvzPb@;l0ZgA zoBi#Z?Ah7b!R6P5>X4AIu=i3@9IqahlvgX@jWDkVAE`fnU8FU{$mztzLP)>{=SjlD zmA#Q|!ZLea)w;<02WKOVsr3wo1pC1cJQ5u(B(I#Eu3&bB??zohBO0>F=>{WTx0~dO z^B6Yu#nLVSz(D-h0!7-8JILvt10Q->-Y@hj30#|IEXC!LAp9`RZ0TY0P0m8-0cE#! zqJWP&4jQ1GyT+WJ6gAxFbI-QlM<~@FMGo8edZ?O5fE)%3WJ_89Wqn_j zCPaNXiVcHAyHL)wfBuJLYY@{txrpa--Qev8%T`pa%i;Pp%av0=Ng+IMF>_kQtXhk) zxD>CuUeiB1K~FDF0Z}y@j6_gSQ2WLaP4=$tOLPnj66U_dn4NxTZff;A{W`DcZQr$k z=lJm-n0)$~7^oCXB@*R{qB?RJKzg;8!bdA+h0Yohh-NZgdg?w}Jq?zjz~le*oI|9U zJp$+Zh8&`8f6=kUb2>kNe^drKLnEsk@LVoO+67~8$KcK3XBje*F>Yq&?9EM6)##{l zD+XTP%!8F)u9sb#R?g*nnY~6W@xo>r2Q{%VRb%uv-=}^Fg~5}3o;}_-=ea7u+FB)I zCHJAzEc`*_FQ2&sPG`Dc5%C#v-%{|t?~jri6d%avt?)~9TBmoeao(MeNAySLT<`>|bM(-zS6xuJbe8clMMDczJ&dbWoHDNpbqEu6G5_Vh zTzQkyU>{zYN~v{^#dk8pB{{ZLcZhoX3QeFPKPe@z9Z{$}+X3r7zxp^=ET zEup=qke!+Yp8fn*9mR*oK&0S!#%A7Ijd|L+pJ5;w44UjfuqIF7c=m3@cntC z2eZ%ery6|KluXS>5ti(Mq9lR@DQ)bWbyM`ut%+kg2e!xj2FnlL3VlWJxUW9SN9d#s z$ky#z02P>y^T1=K_FN`Ruefx|~wL>_kmtuFh0$-wTC#|N&ka0;(25cq49f5T+bFO)n-pI8?$-P&W;?r_ZAf2gsj@YYN zpxO!4-pV=+=6BpKHOD47OLm44>XF|q7HL0}&O*SIVl7uA&||b3jYC94yl1=9V6nW9 z#ipw)LsVPmL_%&5-L4m_^wC2&&!6j${LLZTXwPqnU)23 zGv#ZrM^2{YC+7w??9+0;cO z)V{{Y(Cv8q{Lrc4<8y)f8MniuntT2Q?~IBME}Hym(wTJ&lW=CIJaJC8=SacZ8Sn=) zrDP^fIg(3oXSsfQd;bjBdex6t?KBk;GxqI%Yn#Y*0`UW{ zXX=|SWqH=t&X_fv*x{b<^xlibS#|Z&jcc+yb+9f}=PNQ*yZa+s2U!0Jnq1zO5?67# z34b(mf0#9k9uN6ry%2am-LJ1?>Opk{`t;q@f9l`b%X@?0i9WQrfz@9j=z!gpTo&o( z>+J}TP6&ku&!U$`IwvtxEMT0P7(>Ptul4-|y)A2e)CXtwgPMMMYil7FwW4M%a{hd= z)R@x=ChhQ@oZJZ2(?~ovbCLqf zh@4eYn0DBLYI|n_O7JTryi_Yrf(O2c*a0PNroSUXOeH#x$DLjHX0A@#2p05$=ZhPS zX_SH%WzDR|_Pn?F7H;NK+X=C*sG>T23U=iMx)O^zTN+R)WovXe_K%hxfcH~}<%+%q zr2@(*TqoDyZ(Pn-ZhTHog{Y65)f%yyPLF#T#rwFsUb)}geEV%ju?WW}48bD|Nf?d& z?PqGL!Jxcb%M?H@nUX6()e6V4OPQOF+pr+gbovU*Zry4fH$b{0&(H9Sz2Dt3 zmPA-zeBm><@WNNnKSv(*jlI-EuNN_{*OME6g76+7dV{WEp&^EK*$e(EK>Hf~xu|9G z26|=Su0+Tr-%C5PRHiU$;FBum6!=GFs4;bWJtE4&SDVefy+7;g_FDrl-s_UD<8nnX z5^;g)rifX6vqBXY{Los^i}=@X6%|;t?v4YFWkHL-Xsq@tu)E8hPK>B07M1G>Qk-7R zFmA%Cbhh9!YHvmfifF|s@SZ_|hi_08>nD6qW_bOg`6|d7Xwh2ui+Zt!NLcVO((*cA zd@(5%?|$E@Z6Wv@C%Uft0&HKLHBVo*=*?L?o$`VI^VzXr^{D#+ik9?eaClzbmef= zXHv|uyRK~uOIpAX&hnd+@f zq?Ykv_9#hW^r8>i9ca6on;!%x8xtK=iO5uhP#Gsn8pQlwWPd~MrAeG+@Q8Uf;8~pI z13^&*V~qQQnSUx<%j#~L z_CO>HyYAYI&Fjwfy%uk80X;(#Y&Xp37@z0u>gG-)P6(NGE0IS&q2@0?t?dKb8w|i& z4)2Jr#q8UXblIBP zIXP%Ve6o|t#6TYxkk6_vBE;AcO}_W-2qvEHAPC;qwxcxv>m!?so19^OTz81(3e4Her#wa{LpDvf+Pr~j3gswBpVvz`o)osr z21ZGk6#qqYU$Em*m>=+W{2<}^Pe(si4)$xy*l>fsS5+y8idkf$#^3p&Ar~N`Z1#g{ zr!m?xpP$(F=?mXjStO)a--r1gHFyTovK@}&@7qwe>B;kdk?_rU(7n}gy6W=z+p0YMB#VnHx6>;(F$)qY5pk&+`v);%J^)$6a0AI~2%mCbA}2Zb_b;dVy>ytr zCMDI0R84cUYu^^6XFhhJcoy(u`|#V?H-aPUx-$36v!s`()&Xa;4_1#6``k zgRMIk>Z@YW7~>>ms~QvDy^i#1?2X;zu1#x+wp68RI^>@SkVd$M9dEiIm=)Mp$`77_ z-3lx`D_nR-%+#3HcY=HoFP9fF7c<=5eMg;YGK_oms*VsKnBpHXFYfOI$ zRZYoD!+Qxp0GCnM4%wiKRzTf^E0`dk;E03jsg}jfm*Oay#qW*0F~pf9lq{dKZdU9c z2EXaE=BezS1mWS2|04O$X0o0C+g+aJMKk5T4r;wghrw9o#K zU0xF1(9ElVfb7ld z5K$6KEA2)61x=c7hvHW5O7y4Zq!Xp+>K!8jAdeq7rEg5O3r$Vq#;57E=(Ftm5@ z&pv5Hzr4_Lbrwto>mD47@xKmlC;dq`i2+P0;f2BeZ-@u+@QgNF;oHTU#KP7G&xoF>)X}tK{%>D$oKseI6Qt#|#S4FHU>C?V$$=ip_3NUWb-H5j(BO{x~i z>6%~(gFWgzS8hbl{NiN$sF#r~8fh`9Vn)7w61ZQ(2zD>fqX&);{P}ks5m7Vv@#Kre zufhvy4f6E7vjm6#Y2atB=ZZavxi=`jiy3l7Q0r8fmbbzQws%bl(uqMcAy5D){Lxy=MLRp0*tii!mbG4`4lg%+mBe z_o~%J|I~~({8;N9t7Qi2yyXM%4?hgW_mOc0E_J6E*;jaliSqrg4O4RL+xSL|c>ERX zB`fdlbL3j-1}^U=zK-G4@cKoX1y?WO@~vt8$gF0p@j>pO?@j;8`oM@(RYAp7^w8#_ z)xxQmN+%8dQ(WOI7ga?L{3L1Sp_G*ZH@7AtKysPm{iUb?wVvCnCXKoB*MF`OgOO23 zu519Dp-W$7YRabZK1ArWi?}F`b}y~~7kTwZaql4t`uC!cn;Niwc7D&o{eB|lF-x%r zpNHD_YuLBn;r>}#<10^ZUP zH_FlwHHM2uAeoR;%{prZ8_0A>;j?F6i%m-kC6wGHc2sVc`v>*N73NdbcZ#Zrj4KSL zkc%d_!V_a1!^Q&?B}`H{*U&?4m*GAD7CO=I7F$9HfzT(!Lw=sa<{ zXtvUrsQCh3KXK1n;1MG#e+~tXBj=L<^zo&7u!iT)mD)z>ZELsO|` zobLYzo+@y7gnrjjOmGe#4e=hfmDJ|IW+J_C$qVNxM+M)EhZn)xxMeP>iSg=NKflBq z$&VL2u##!-2$yep6j9Gdc1>tPjb*_}AC@q`#XQ6oyf%Uc%Ns57NE<{JF~qU3J#?5_ zt*3~%{VP}E8fY{hx*&Dmyy}?_@!+LN}_xxJ#O*eptoIg1_<4gIdGY#L+ z&iuG-xUf6ju>F0oP|){l?K##z)FY63>63)&$mIPBfJG=-d<|F#M^_ z;%}S>^A#;Pd;Mp@VNFr-pGw~Uo_@7bo9RNPX4>%aqZNu;%*>3|Gc;kbOr{WDkfZbe z2mu(Bvppn3VQ!~Q%la`aYcbr7=p{s~%(QYmDu!StId@DbS71NBR6DAyQtOQbD6H6d zGPQtRiH5%yPNJbbs0yvt+aCMSIHz+DhgLg<{!hKCeCw5qv=s)R{n;j)^~*b8@8P3i z>mRSn9QX<)>^>Pi{R%%OoYAF>Dvt|!7-I93g^M$(-YsQWC4aIUk?v}8JJ#pzBGxV8 z(OFk$A#mT>uojb+)TK$mG^x4IWDwK$8_N0u59*75sF^pHcvrAn3QS zSW(Nxtf1RJXssEFUV(Sr8uO0cEcc^sy#KEyumQ%|eaE);LGp$o?s|O!Ef+U(x|M|9 zlgDz&5pj}lhgsEI8A>{%$k%j^U?d#-3a=w6n&#ptL*)+&PVe$28kv9Ds5+~?6mu;C z_#Quz;P~XDBe%IFK9a8>2Z_Oc_59JXM5g9}t)q%^#nZ3dBVx#}anTrC zobBkakbv^t!0)}oY&m>S+z?xX#0eqUlb9Pp;B~29xSd7Mpw+6C#9+pW?=;cuJjwKj zjo+wsGIQgtR3aJ)M9ytqD|T+gt5$Dbz6WtN!p-wFsc2i*Yz54`pQ;!C4g ziG6dcgog3oac_DSyXb_V><;wj6_o@=@Zvojc9FDq&G$3|Uz%tL?331^Hp}WQJhPXo zCoGpciv& zg3PUcxB+k^0MAqAF?wY6`lJ~uHRXt3yHVE!Ux3+MAk$9yY*@)1lzD7WzrSr#&&x;t zb#@1A=wK^3YLH6SFgv@?EO}S&clCrTdXu9y(zWF|dp++?pN~>TGtN`xc|2`5{K12) z49T0*p9_>972?Adzr?&~{;sy)$`u(LJ=CyhOS-#3y1S%By1sec-~Z!U_u54lmYHYH zx$Dd$8(m!3SYEY-EOar@N{`!D4!w6ay=#;?wu9+T5Th^2Wo~=rrz8IBu;K8WG!jtPZB~&!e5kbKMCz8^LeJ^6pI+1NRkwx!Z2aHj z7uZu`# z=V2mp-HP!rXz*_&G9>-a&9}U&8n?ai2Lw_>*i=WeX><&w!VMDcuYGOZ{U*$QG-vHx zqI4aS_>)ToTE0O{PYKYJS@8U1kn`#aTZ1uj+M9)Zl{s-+4{&P2LIB}gzq-5YG2v1z z74Ofnpn;krsbm_$Je!2hpWGj_g5F&YwL6K zpr^VNP7@-86-f1^-$pjx{t<-_OQAs1W7!9H$FmL;-Ex?6R&$-jWQh0X&-w23{@hLS zuBm?TX-EtH+^27;-uR+|`0IPC#naVSSgPJ@i%FU#|9(1UIvhpas)bM&K>=UDkWpJ7 zQnga?0?`bAHJ`MxgT~tFzPx*d&3C`F*Y_AXx7S#TY8<*Ae}xAI1*F7=(N2WcA*@geomc z^Q##hVx`Zl){NyPzk~F|V8=j_v8sqmYaFf; z#osZb9aVkk`g-V4yQ4!Sb9rv|kK`J$4h4uRO|L>U%yV2GIj6R+5Ls;GY2)p*7)A0| z9X`VMPwf3JB-{G-zg{QM&T18D)@O-PtfHddcZAN<39yd;xA9bTkH>@lN!hhvKO5pt zq@*V)%g5!T3@Rw67cxMt0Gzm6qeXRTKvk9L&)TcLqJhDSfFX(!le1x=od5aP;?+-R2=$a zr)5g_l3T(Zd5)|DRr8deo6AnYw5RTTt6DE@bcsStgPUuPj`@c$tIbht#@3Z!z%49Q znQ`cpeabB8U9IVb#!BCWznc{5#PvuRoL5x|x!k)D^MMsZ=F6M^0Wft7hte*cz3gyo+g)s9IM znJGO~GreVJpxZHgzgRAy64c+;m|X8_Rd&q$9Jr%8fMt)FlJ94fC)l23J|NachO#o& zQ?2aZjdsSJ9{Xo`#E`D|=K@b;h*~}$JS;c#H%hTWHanVF(dH@Q3!4)y*%w$Pl7-7O zBnyG3Pk-F);EUtlgd{_-qhVadcsCG?KPtGh{%o&9T(P#Bx;*DUV8;tR?^!Ghi7FC9 zYtue%3!M5K_hrkW>43i6S*IJI#@JI>4{pgIVZWA>U96YM(t)M)+^4()R%1``ttdCX zWH(LAl-5u22vTUs)7mNV4(nojyufbhP)JS823&!H-QoN$Cd_x{J?J4jzdNUkHW4Vg zHkg2C02HE5&1ZR{$e1X&q){rj?JfvoK#fZY+V0eh4PsCDm`YEeo@Q!&D&*i^k%h-3 z58u9q0{*Jkc>R5+!|vnDy>mDif446JYC$_Y--TN)CKKcY-wnt~*t70a`M``4QUuk- zi;Qw!tPXMrZAw0Bfv;XK-`a!@mfO^#E>CksVg&LnDG9zC$bnCT{&Lm&^~2x2w`&&7 z^uxMaDkQIm&pGp59C-|$K4+Wp7_Tb5R8#(K_$}Ek@vWX5>zaiCFsXnHRZIY11_gE{ zi%$aftps?XuQ>LKXH|j8yLZeqn&qKN8zGEVy^K1~PD8a=|Mml}NKRS5Z~S?;VE#Y( zUR=@|dlP`Q(v_66z_(DkVroddPUq4ib}365^1@(JF>DySk8+VX!u0PaNx~BOqHk;C zr<5zKs3M8OK>#CBMly5Z`ive3B@V;t4oG}W@+D-)HNsXk!bY%HqJ0`wZ-ODeT-Q6HZvp;yC6%(510~O?cT!7QaL~X0^0;Y z9>8t~LT&^=1J29mOOmn|)1-kET3>M_iy}P{sNabG0$AMFIlZ%f#Px!?OVnVu_Xxg? zb3%dFuOvvmsZ;mt{~Eo1I|Pk#__5pP$J@S`T~87@ZR(b=Fs3~EuQ6-zl*e;I z_-TVf``a@;gT02LxZ~UgNu2FM0W4!<0~uzfbwvF|#rL>*gvsKcZ>8tcAAy|O|D$bf z>nb<97alMsjXC;`DCcRJp#yGh&2nOaXE=W@C9KO)-HS0#2Wy(O^t^`kU`Nz)c0v z7v`-(iLt)Ds&%&CQax{?tA6}uD!@NSvU+XTU`l<6weu)7UuGrY0a8#F{4=? z9~nmL?SHg=&f*rJ7+4M_Wr=asd~?~@)G+jG@3-uuE*0_#KluR%*?-&RG_;$j4|B z)NYfs()>U{`@4|*c6GT@pW#Sm{D(s3QaZ7!)SH1RJ7#YF{*MrHy%ngP*)7##%Y_8g z8lc=>D;g9H$rjsEgd{-@hcNl}0oQc=xCq!+s1FYA{r zYM-8ijNQ?e%%@~_<4<8OzsuLV5>A%-rXCxnH@fbMxpRJQ9E2fv>c;^<+|D^8^vDSG)^5-4Kx*S`T;3hnJvRs9Ck z(KF(?$%F8B7(FY9L-HprU)Z;$s;;}n3)W+~$?y~enuwwE ze1DgvxZEUHxi%Mty_A<^kSw(;D;B$-CP5u{o*_T@uX4ErK_}yeQzMA`1Ds>GA;}q; zQLPuV@U8ATK{$7)v@t(aX}xGv>b&bDiiRqFBWYaw^K!f4YkbfZsxA?f1uN>kr{h77 z|Ns2NslTQ8rRo2FM?j%%IN@$AUp%DY=Z4rosIzZ0GWblAR3H*1Sk2&$#_ZmhDuyv( z!(2RLJ3Q~rWhv*mB!@)hW<>DVhwaW25{9q;;!?9l?^HMc7D|PYqqoYtK&@)|J?~90 zOw3T}(qB}s^Dph8QXZ5rcbY`X6*@k^fpWBmfQ$H#nI+u@Ys=yJ7hoTTUJUX9(Yl*; z{${2fmC~6nHE&maWZKPDBs=;HYyHbYcw%-(V^!9hYY{LHFNr>o0As$|h&Z_*r z3@E-doJy0?4d&28lKY(yD*J;2xca~akOQ7BkOENH>ZFF*{S3JHYIfdg8<;D)G_hrd zcIUYPKX;+{D4u&RnYzOm_fxd!GcZs^T`YDrCOlXH`HxJm+Q>yruN-66)vDvpCA0_% z7zM52um8)P0AmWMto~!a=Cvp>6;EVA&sz#1QFc#H2I+MC)DB8ad=YPNLGY5x)2=7Q z+`HXQl*|5}vsc2Eyf(+(w_lZpMh887Pyx{)7q<)$hHp%p{T)1i|2fC( zC-8UxA?(|J@!g>6WRiWp<|1Ny*3YQ&Zup(<`}zq92)mZg0NZhMg;KvU->DAdT6z0R zjq82uVT5Jt`&)z3^+ZSp){qSnJXm$h(#lT8%X^{zpFnC zy$IfKvv;?$|ABxErX2`BnVI#NLBH3!LC8hKCdfmJcvcAlcoCXDKz{C8^8b-~2m@*D zzwRdaE0v@D#l!5KB7J*#1Af9?WIGYi`A6)&k7%XI?{Ou-%zJcH)A@*u&WU2NgId!G zGs=kp9=?cRRxmQdJ}WFL@bVd-n5GYFVDStlsk8Gzwo*&c$3EnRbY^CDPXv3B#-M8vW1z)$t=IM;1~z5?A$ze zKCR%F{%p``!2eqey20YL%ujgdFe}{OB-bRNznvfnBp)Yd`$XEXty)_5_8U zit~q9rF-RI`XOkl-yqUqd|7l_j}och&K5q}hzmC~IECT%+9@-5)%i5t@}rgktoe|M zq&3>3q{*6pB)G%@w(SEPU?ci|&cCYW6vu>s050}h5TIB_o+dt8_MIFcqL${p7Rlwb zExTu(6awm7O_*a+Mn&h0b%k#Kk#lp09ibu10#RnnJ62iqp#UJAI!I_s??ECiq``mJ zm2ph68e2_7wwJfA6rex*a`$q#^nNWkLEwY_r8?bW+o)05q$(A`>?t_wwXk)y_2HO` zu;>{EAc&|#u#>lXE&KIbrm0Rw$&p0`c{jZI^CFZb)Er!TkY zzao#B#M}&{<9%mG$g3I#T6df}4q%O-(2=P=1m5+{uMreBhGVlMzUr=|G=I&_9+f2< zJsdrMrk7~#Ft5jgji@Z9(-GwD`KXfHB+OY?4|V+hW?hpAsspqNkVOHgi^25H(Ap3v zJa7E9bM>r3L{E$^RQt2#D)1{JGEns(7GRYh@Gn6M1+Wuguu~kR4H_(A`zz%y!0LZ; z(yHd=zquqRut9?d$Kv6#JB;SN^XQb_eC6heoZzAD6&Z_UN;#I4$@=rdiLY)y#5g~1 z$e#12=D@?n9Z*#O=*>SZgJ)v73t{ z)kqv(my9s)DTw79fUz&eIpG~J)~y%%hGc&_AIwE)AZIg_L!nm zmVa_8kh++hI_)Pk0i6aSM^4`!U0<4Lk|>wV>>qCF{55mA${pVMC=^+V$H%asC1KM| zTu%ZaAK)lhs@ie>ag1{rL>IQiZ?uEvw(m|MrO$S-eH){05%3^ z6msq$O<%#9oP5gBfCGhLREvS+iny6=*Y(!<#xal>5itG>$K^tUUmI;y{!%wmHYo3x zr9RKo*Gkox$GdRBFyq~*emOmKx==6pIeP`)-fd4G9uQc|1sf@2A`hcPKb&>fDG5}` z0z@BhRtLnx171VK7cmwp7?F|qj$$>Tt@^s3{p_DKs`+X@7yGkJBvdn33@R#G)i@Di z7@d%93LU(NHLd020d4TlW?EpHzWEIGHojRrQg4Y;B z#75AEFfP*^kb(dXs4_QuqXh*MLyCXG+KDz?IS}i)`_NTISpBK7-*~XPqc=vG2|c2N z1lPS&mx-`zeSMv%9Uca{{$UhnWclwg3^RUr`RM24(fOxY2FGT1k+=0%%R#0t^Jm)> zORl5ev-GXgWv}n=?6R(0nEM;O?UaVnhj*`}@aDXOeoZ4#APIO*`oO+3hFA9n@qpx? zgxXm;3f!>Yp8H8pZfW)uad8q$1H-LDI2TKErJ*k zoFBo91p2y#FUsm?4JMoK%hsWyFWDkxcHGt`pFp8VD=H#J160CmKV zGGZBqqoG_Y{wOcJ{j!%rslnN(iJUA=tz;E})xj*cD75VtONsOm`phs(mUiQs=4Xkv z`1yG9ZVh}t;5MCKw7rCw>>T)jdGxTogQM%PDEi(7c*9~U*4s*aqNoQ$mAYz=2hSFY zAD;y&mB-Lq1=Olb<%m=RHboXl#ZR*2vAN^j4P-MPec724N<_@m?0eU6~f6;4m z|HT*JQlXJd<|rU~K3nqc!q8a^?cEJ%=`jQ)_SE~?#jaOP<5u)H=G$+Y3_$J|q3vnc zxCnT+Qdo&8T%gC2&;QuTq%CNV26ov}tA?~F>|iXz3ln?4gEmMTN177K#?-El%KQom zW@1k8+#_1fc%w5kdETKRgrS9N1DCrr?-M;60qA&GJqQ1K9h`pB#v8?NuRu?AiXigk zI+9Gbr3}q2uvFDF7B|&4aF7vrH}NPX?Mspf>Lt|r5fPxu9^WDv>^QUU{Pd2zpV2{> zR6OSy@Za^^3nJg%In(NcPoh0zt!ghs#V!f4H$6%Z?25*qRJ!< zo6z0p*<7F(sfnePTpJvbI0d#CbD+a!s5WB(Rm0NTB9V67+`pPG7yu#Jhr=^IK29Nci;Q^y)n*S z*38LEX6`?Z%fSQ}(S^Z~Rf7}u2z{dtsrjHC6F3)`^z^D(P8QFLja&%g^M#PVB-7*DHm?%q{6Z9ce{u1_hx%XU?)}G*9avV*xUa)=VqNN(b=0(Zw5ux zt$ZL2Zqs(rL>}~PJ!yC~y47o0C@4t2`!-bv!J<(V6{n|RahRk7BzOn_*qj_vq)RAl z@P1q2`xa7B#Ki)&Qm>C57$-Ak`jKaI%Ib&++V7YcQ>!+e%*xf>Y$P*zGv{ay?wFC@ zDaqBC=J)A`rkIG=QJhtk#0TeI3}WD%ETlQ#ylnds;%~469D1%5M{Kap!9%aGa=vQ; zYl!#i6unNmrU-Lwwer2u7>W?ws}jS`Dndmh#P52q?D)sn{OzM6u`0&hr@T?PCGKIN zaR~`UbeTTTga#*rqnLEhX$-Jx*xVcCExW=e{`oX#zFTqq@uO5uqqHX1*K50Z zDobY6=U-tHQx_ENNsibNYQ8j+X4Gtp1Uf0xP-%EG%8j31%U@>-K&64%7iL=CbdpLq z2NIt=X`Zw!`*M~OK+EGju|b*E_N|*{Dr(|!zuU5Rxvv3H+h=DsX`V-CY8HCK@=8pg z^5(sUFfBM?c}#*@5CW>ow@3cE?3HHaoK;@Mdi-jv%o#`hn89=g>H7$~E|AdUGWL>? z78-1g9;zIG{CCZWwkmX?7)Np3zd3r$pJT&7WMxhDqoh$XFHn;KR;UM2=dmBC7E;q5 zpeFnBl5wQl2!TvrB|Y?^JR(Ty_A9BhEt-vwaZbz~VwXuLq;$_cU3pU;|5IVeXMjs` zc3D8u53%;0E0yC}mej3W&u`NK4-e9#mmZnk?y0(K=tGqH&M0|sG3(5I{<%&#WnXeW zOQp8ggW059`R&hIY3f{fk62w?uV2?-&Epf2+$u==ZG9Uk@BF-u=GzfT((X|qR(m-v z=-CE5yDFtawOl99l!z+97^3WRBM6u+;j`?j;I&UP#&F7 z%i5gWq8M?haMg5tw*wq$)&lQREI@W2(d%r9WMfe5XQv^(4A-j7>N4@%DX~^7Gu8OQ z%!viwf{GCf9tf*>WLp1TkJF{~1tglj9uqDgeahUvJK~eGrCt zzJN{JAt@*bV1RDU`f2?L4{me+EdfNcSuORT&#({?8oMC~!x?Aaj9p>h#r+CC%csgL zb=K6}Dm2aRobTCQ%Nw`!oU-I@n{^eNWn^e#GW8}{95+x8-8sU-!YXPQo;zcD{~R3- z29oE3gsW!%+ye82$-p_pbcgeQU01?H5UD`_ob&nYjkYEUL}??RD%92r0Yo3DT`%M` zQ}4g7KsH#l{(uZfV0KZQn|KyKnxt4eq7-VRsWD2u`){{?S@)=w<;i`{U5BtQf)hEil?@iKv9Kcww!Fq zkL3oi)>V9=2>*V|A-dw3!Em7n47S4~P=YHH%JB%GXW3u?=? zXOb4K7hgm`{7-QHiGr`q*+LkP3Szk&Q`U&IUhcaQS+b=baYw{ zLj!PBlU!7u3fF+CqUU)@_|SF|r%|1b)X17DLV(x?{Fd()DtMfIgB>#3B6KEm^}^~?(CTZi5t1qbEtw$&Q{gG`@8us(bZPWhal zV_xJe-?r=@RGE? zlS~F>Tv)-~VVNM_>tZ*u!RtEjo>+3w!SVMdp7thOW2(yjEhY&8R)0=;l>+Ks6(B3M z=DXN>-{RdsaISX#>-qdg>_SyNj@`%|O`?$1Z%#6u{yD}_t_R1T01pMp87L^|C!xQ8 z-z;y?o49rEUfLjwsuO9+mG0Nv!=VPs=zBQ|S3{vU-W zJ}pa284p4#9B1otSz7c}X<&4@$bYtq~Si5 zbHFw(5`ts6f7B#7Hrmr*S?Y$%T9B~b+scdDO6H++3nU3kWZsO0Khr<@Rkbs5h;;;! zr=J*h|FF@$nN{`z1@|*63d15&_YcSCX>%u#EQSg31d=rfrujCoueJC1d-gNtN%L~n zazXU!DyInBuH7ndegqga8wK7ncW*=q3YCM4Tp5F9x5w^h0)|&yxLWHLwJLe}<{Ru! z{JVBR$-Xe&0ba{VZTq!DI3d<|a&$=M7bqYx;ncQXr-rHPUE_x9cyQpka-h^0HFd}` z42NA=B^BVCOBV8!Nr<rR=)%h56u) z{p}$bLxz(RZWH+dXg0D{bVu&b-+nBP;^6YG*aJh_>wK|71dR>wR~wu8K%jIx8Iv2~ zVKbHBV$*jE=l+t-Ma_vV8TFCL4H%t#5jFSmjd1wjukjVX1<{(bsg-Avrmq3sjaCke z=YDHXaG(pnp*A@8U%S40z3FVW+G1`nl#xiSv6(Zk=wwEWhha~+Y`q~*+IlgG1xA<> zuN%NPn7j<((&SDjkQ;OlQ(pP@xVZZnAPk)9$ooEDG$Ug4nOYuq6&vNYzl1~nWczn| z|3Kd_8xAN3{_X05=T$q0O3|N_eGB1`VRLl8gcHunQ(&jOsr-)r0V0;b2rbirW62Nl ziyuCQvA%ybhEwhccG((}pt@>VK52T?3dCKTC=Mlg;wtt;7;Cb7L*}A1F-Gdhz~*|q5CmqD{E}7aAB*uBz5XYyoN3_kgaQ+9 zXN4@4)ZZUw#9whR)<|#nFS=uM)1=!YK06#UwObP(U;D9l_DL7~(bs!HW?X#C+7@dU z6v%mZb)4yg?^iD)QrWaOdkyR&PiCX>!J@DNRxcUyxWTMRLy-GJME9npsu7FseE@RA ziw~0Useqh%J@%Oi>ASz~!)6B_ERYXGv_pLk3(}<7#=MfksCm*C6p?<0 z1QTNoJU@zOjHQtO_$YY-1mJ=wEPzYaV4jVz$mSy$LVeQZDvO*tIqJ{o{yb5P2N0P4 zs@7)yHUHP4K!!xd+`I4dsR+k1D9%J&G_KrW*v_8YsEq0+KrhLk^_+wKCseBb{pZWy z_mw7l1hM8}fW-izHG5FG|6!?3n-hfDTmITKqoHZwnWPY` zBi_JZ%9qD~60u>l{S)21@c?-Md>RPFf4LoxYF2wV;fk%ow?fSVa57#^e z4TgqBP62(CC`5+%)=yOVG2UQ&slj%KM@GvrKRu}t7*q&SWOVeR|LdE+!G56dYRsuZ zse<52&w??H08gg&sUk?jf=CG#A^%KduS0~YyfJ{p=(QujHDk5*QdG>sn!#EE8R>u( z8W^0dVMCVvOK!&+Qr958dH*?QXdlv)vHG6vSxpc#2Ot*UAjU?H^DC5|CxY>BroP6Y z_Lge5zohS%hy4eFD0S)C)-Am61#N9l_2l|kKvqaZr-A?kQ5}ab1ho^50juH1igPi$ za`U9v+!5r^6amwx4Ut=lD{3ug-8!2Knch+LKQ}&3k1%yb6;WD;8oipJHhiJ>d=vFd zyN{M6EvgKqlc;}apN2p`>?6(qk^nv*NH@5q{uE>zq8ClNHQEheC1nV{85U599C|gJ ztSCKcPeM3p)6+~-k z0X!85jg|8rdt6z~6*MQKO5>i#uwdB97=KzY&5OjF>(Q&r?(ZF;bTSLoPG&C{bj+3& zkG|ogqrM2aa?K@(kdouEm?sYfvWcC431Wd#>5+^ZZ|Fo7uw;cmp^ zTKIwq<`qjQAXO1F@W$hz--1haDRefntyaQ4y@~4b{chO^c$K-(sE#=W7%P@=UehjQ!>z%*=*7l+dq@fIolt<@Uw&4MxYLTH1 zQQ-T*$!{TxDWj1L_qpIoH$a3@&-&Z4!A%L;5dl*DoFwM$mfhKpryG}vt3Bo3OA%3# zGh6xwtYEerofp{zB_IESd5b}z%gTObAp$b2iXNFeX)0=Gf&3aeScH;$*Xn7^rOjP> z;!xDzFNtg>HNaQII#zc-AoSe^7s&p}Bw=g81!|?K0E7BnkajniQiNfgB6&D6ngfHZ zB5xi3EB9CmS>$UB=KDb5kk@fAU=>|8Hl&E zw&*mBD+C7=N!ZlxNDz>A8cxzZy}#cIt#7a-8==Z$el7>$0>~3W!RgRy{aogOJWS45Z!5HM-o0f9yWhAhrStALH|+qPdmCiW za|iHMvIvnxEAQ7ynAcJABBJqdC5^Q7-lFs8u|t|asz`peJ{C|&Ax=LRbt|(sHp1IJm&o=&_KE&;pvh$kurPlGY=e`;BKHP^wYlyLV*!jh!my? zA3%v8fq=gTVjuv@cc_Y=LPDr;!jOyz#Ncyxe!?M4*Yf?o1F&6~;F3>&Tb-MsH0C=H zge%X(oa0HCEoww#uCVEdLNs{_4!rx6#_ROrMZ0aj(CNc9nPOQB=LVNY0~<<2Q12w| zTTDq9zt|CdbF8LsZ#k{unwJ(0>F&g!1mpD&@sU2Eb4dAH%#~B~oxl2)>3vur;c{04 z>^~3{Wvi=)Qy+8q!WZUp7!^!zx>{=w4J_L1NJ+{!ZwkOM{+KKO5gTq-z%EfZ*@L z#@~CcuXkMPmWh22t8;ULk&wAZxy6Uo_F|v8#H4o-l6jx3t+f~bcCW4y3k8gVv;x42 zoCo~}SFeNoVG^4+@Zj=CZ^P<50s01=f=TlBM*!yOv=(GX@$7UM=q7Tywg5yaOD&F%PvD-tgz3qL71}5B3);ZMq>>EomWEDCu-{ zQb|cea)*sWqKT%@D4puoXnA8VyrDqWr?&2AZdsj{Et(ul6$n#R$_X zo~z-S38d%|wXwTdfIk0T^L?aNEN=2ongLx7xe` zG2et9=GOajv?KmD9j5-CTNh8{J;rCb2?H>E@^5sZPyhE1|HA0tWYWO>%LWJz_=w7U z4qAyV5HLH3@rY@9nv*T;7KD!;?$^R^-5lHzWwiMG;&8^-6{nJudb)vv`mKP|TWn(M zx%*)2W{mNPVS|gC+YO8jnN2-|G$~$!LQ?RvBbK=I@ z2DN>~g~95y6A}rX4o>-l2OlE&Uu}omz;(8U(GLEW8n+bd{?8R65N3Rr=^T>ZuOkU z#X8u@_|F_#fRVE_p0|(^@B$Rs14lbVbkNUfP-+#=o%E{G? zA9kzE*+?}I>*FiG@_V7#&M+F`3dV;p$+p7C%&nni$?F1@Xyci1!%2S#(Xzo6OvTuy zfhO$r#3`6CVi$6dG;m*MLEA=A$0r2Gfhu1O+ApO(b+FvcR06fV1+{+ul_rt4n@f~# zYRS#IbK>iu$Vo0D`$oR9yUYpeQE=;t&g~}O zK3n*Y$a|nFq_ypfyODLw&Avx%v6`AJgWxH!pn&WQB>c<#z>$lBp-(ZGF@9_BMZ!eo zQQgKoTlr06kmPRdXE2J-g8UbC*P}jl)1>Oj`UojC)!X350+rb@2E*6k(i}Et(zMI2 z?eT~Mq;w?szyCK|FYnkdB%r7EI?B_66}YOu(;&<$MjxyqMD!apicQkuKwQz{kDZ75 zURZbwM(xiwFL*J^gXRO3h=@3foR=5@pzZfZU??nHFr@nh9sL8=xhc<02DV(QIaHkT zyw)bFVkHzP^|3rZL1M>X?H*QsS97^J>m^9#N~Xu6A_Zu^h>&C@Hyn#KlFLQy!Hw2n zMPuX$B3imWjoscYmY*W@DEbp-TCF7v9$`>gTp4q}PI}(-x_D79yB<`Sqho6q9DW)G zvvTDOu#92q26C1IeSKICR4zy05f%HgG-2+NcXX?v!Vc>Y8sP930r?ZijKTt`Mxm`D z?j0od3cAVN1em97>XVuDFVJU-X#kVb&>+9aviX3G1)0AU4agJ!Th*N8YYdgdQwN3A z{Y&(7@Jk(nrLvt1AgJL>5Gnv%*^k`DD2eYXz>JLza?a1>2b;G4pw1@Ef9ZmPztr!t zX_J-0GoMaLs4%zo1RtnmX3{@8H-U0}l z00y%IJ}uU^wis$06?(+_7nKwkELik|Fvj(6fFNx18_6i5+BXEhz@fW%AD^Bb*{?o4x>vB!9WFq!LrVF)#YM0bDR4!_NJyYcxgk zKdqDWmm4t=Bo6|@eBU`vM!`@am@+VsNJa~1K?Hko>f!jx*~D8tb9kYbo0i$!?m0F& zDJ3o~JYF9$1)zsob#ylLO^}-fV}a?3s%!UyE}izj(6$R=8y3_BNWds+wBkJ)P&UnjQ*Z93bVO%{+_y3h-92x9-&w)WQQ!qCf#LIwYpFkvJ?)E@L~Gb|4HMON zC5pVwzA#R)AIp?4$jz#@+Oq7 zLfzmBuW4}h*Ht6&{Yf_|rM|z4kc0-BNrX@jnBs<533-~ca77M(r|rD@bTsb-NZ3;> zLBbon0pR9LlLi=bn3QIAU-`g4@Llz~aeXZ&0&+#cbYl%KKhzBddqG%I^8c+OixF|z z2as+BAy@yEgU*;c4z^klPYG1GN&-C*NdB9DMPWlD)aMC_k@9aobx#6r44fa3uZ4~i zLj08cDozgN(_5TY1`wEnOmYNbpR-KUVoCx@adSL@8(B@wUYq4S3n5QYbkz5^Z-BG87kr1xkNM)M0vsXgxXE-`{WGIv2BmuA4=Ir$gxwqW8X19u zs?zDv!Ouc;DjvIirScR~-$f&YQTZm1e}CG$w3tQ}5e7z0*s;xVtj8>z09sekt@$#KXE8rmHkg;?K?LY!ExY2#g3{75g{Hg&jdtT526!I}B=;yWYt;aZOo%K1)STgfOGCkg7oe zbyUGW^nGpNE$%nEB6idNE_f4w>%j`DVi#ZnvDzqc*|_7DZU}VB zqD0Zbc*=vq1(UG^tU_?%VDM@u@=GCEa1RYOGVjmRHLAf%HJ=Gxw;d;veu_-I6g7ovXp3aFEbUv`?i?bY20z8jYr}ir{+*VBjS_h*M(>P$o;WP&y1!cAugoVJ1k$ za_^0BvsUbFftXaXgTS7{7AAE~|EyOU<&MO-jI9l`m@?0hKO(&wgkyvL)~g>NQ?U0!Sb~{_#kaiNz?WVMUMa}M zav@-a_lmO4JV(2t`_Jj}EBBZPSW+}JxlqKQuKAlksiv!IDI80hx~y9{+zG0#k1Dp4 zX+!>rbF~$Cf?v1SFtlZ=|KtmMtziolEghR-7gP~yI{-py{f!J&H8ZbL3SS3>Qcg)J^0#4fzu?Ylr#GqspV;bYEy`YYb2*& zE!wISu8uWjmHbPJL#ZE{z6c)n-bbXvA-(nHskLBm(OYoBIsYLf0zUQ{en#fBP5QYA zm>OIf$Miyvn3VK+aG1|vHXvMN%YTk}ND}{)wO}~(QCXP-1yiy(gP4&#rswq4Kr8q` zxG?*^zgensiTZne^!c{2P{WP@dK7$BGvog6TJu##DnnL@7J(RJX2=csymBlnZ^eUe z!@M4+@muPTAN>>K5)$6Ty=8p+=y;SQ7EPZAXYJI?PtdDcX?lUmo!-mP*hcn)0a|9O zK)xtzjsO)2nX099_ez8eP z?W}qcQMo(lUb(8IBx<`@U8UDgrl!Iyu)L8eTiDo5&_VJ$DqkcC4=S{byRhu-7QA0D z_!x7rD(kG9$!qx8gz2u)T4?iE*QO+qh$0#FMA{gHeH!Ndv0-LAr`y@qvZwP z{he4W>~ch(^y?G}?CNTJ)R4cFEort~zALllj?)ac~oWQjxGh))y)q{3(;ud+&IFAhEpqkkOz^F1!^o$CHZURlMa*!9zg z*(D8DlNV6p_?E_5$$gh<$=O2I%E9>ydMtyc7i}P}_t8UtMY#x&0YTdIc;m^MN3y z+}zYL$|lMiG227oTb23I(O=moP02S~LB}_L#VhEST<5p?TO{w*o~^)$|6QNV!cR{Y zq$VUy4Xq&r$oUjuGuzdK{;uVMW^OT5Sw9n2e_h)-MWoxGCMJ`QT$7KZJ6r3Eh+Iq< z^`L2Ha=NheySHidJ{H~dr)nwRH*w|anwrVAQyfDz4Gv4OmCz;3nq!BOl8Lhu;z{Ar zgqq>1zmXcarqo~q=ff;r&q8cAZgtvd7c9{*^oGVocaH28#~4UTdOQT&Ub*GeQE}n+ zXxLa{95q|B3^shLkScvuU{uIWK>&*@sL3T+WtyR*)*fjymTHl$ZG!X{(~U;Dj1m&{ z&y5i67DlAxRGE~fFCXtB_F$U#rTdc&SXf!nkdQ+KLT_w?ASHCOxR`w5Iz*^pGV~Jp;hAHFe|_`vW2WHi;q==i4eM^-Vtr*3 z$WKo$gnNlkUr5&nK2uwJe>MhdHNW)Rs6VY!Z@8~Tl6Q!(i@#&GP>D(WCcO<*;k`A> z_?A;eIxKqZci`_Rl(BOrnamhI9p6Y|W``z9&T30xKHq<7M}{YNRY9 z0+fqCP!y1E_|=bixZM+nqwRq@<+`4_l|TPMQ?u#}tay3Sge3u80zxD8dFcD6jR-3^ zWO#*XsR~ZYx+qo_Ltd$4!pWa%J)fGl=i_+Nktw}-(zPqiN3+G@2%N3Ez{wx{n(DVf z8hPJ?2+K4fy%!so;72Y+)(xty*@&6TI;gfFKzZ{;4K{U8N!xeWWUSkWm9ZE6O0aAt zA%4ImVfQ8nPDOR~)D_q8Fl%mevs84D#-763JiJAQ+(gjUCh;67!Qu0jTd3rdatpO3 zOC&uVx`w6di=cbm?CU0$E^-lr2e-U&xp#sE4SZ0EiiY4}Q5oO77It+Xmz(DNN?Gyy z9SyPuM|m-wZ#VUW-=TD_ZaxC#aF#pqG*aZB+T;=JXXjdx;|5{BeNU_mr1!x!2iUm%owTPG7Y#Y+-nLYTIf-8u|AH9gY98Xbn zr-$FoqlWdKO-l(HWhGPQ4Nhd$R>A~Qeu?=Yvc<}WZbTDp*w(mBjO+B;a_J)S$KiXI z@7Xy&2ouL!FtG}rb&&l_f0fP={Ax>)2e3vsJ4<)%e4GlMsQ29x^5&^^I%2wVS#Vp` zE}oprigZi$W0s}w=w~rcNO8@Htg<%|0P7|zr@sr!19=DsBjqYO!3l>P^i^fX)l~<~ zvXi#>747s-5xt2Cy0d>@PR?P4g=knD^vJ?|X>B0TY9kxGkMS{+y>;=t_E7$pBOs>Vaki9zl+_TD*-)*YPzvsh&}$>>rW3l$F&wzzlYlR;qvQGJq$OL1V+jYWSj}8U@9M{U z5j6qmQAdWUFsT@$5q&Y#w<0PPIIC^e&M*?@b8TNs7bs6u?lf@Tca9=jOPgcuBBB*b zvO<9ejnEKY*U%7VWkt(Z>6kmyRaW(F=Wav&?3uRt&HnG4ge__p)pAA%Tw> z@r&gE20hFqOi?xyPZcWJV(o<4z9Hx?5NkTW;~ka2`!@7}^=-t&Ov8guckpQQMqJ38=Oj=QXvqiRt|*8c5-~b36yW@Zdq+SMZ2p8q>1% z$dC@s0OXh;b>bsLqpkG(hL>YQ_0(?R$_K2k6AuyeXaVT$q>Nuu*3Ie#gH?W#C~A_d z)av46D`K7N;sw1k!P%l&Yr>COc6#*>`HK7y2jys4K_ej3ixZ^M5>x{D=Fu0c`E^+NynCpAf0*TE$s6ng(ZN_)yq%MuIG52-@&^>hoOHX zz4jBTCU~*(M7mlmnA0H8R9pVCG7WZV!%e4u%@_x#|)ySO{G=jl;(L8xF z#_4|151lp(yi< zA(t--vRC-pvqYL%$Vr129yl)A=2(J=A@PPxTmv#$KkOHY%7l?hu!n4d^Z-sK2QxY!NxUT041Q0qnn05y55`TI&e#2y~m3Y`j zZuWXLj>hMjfdBt7^_F2(a9!6ZN(uNO!l0bb~ZVcY}0y zcb~QKe%|kRUH(yY?^Sb-ImVc4U6s7N9bSGZ(ewcJ2eFNSn3y4k+q{AqE|{N6qFui! zu5S_!m^Kq6ty(X8>cW)sl}ptNyZeoO&=nao;jfy@HypnTFXvdvgQ|?~(^Lq$nbUyn zziIIuAvh~X;Ur+|sO#K6zF2vDIJj)nN$xAu&q*BMU}Q@h=3 z-aRlX`CGTj0dG64P zkBO?;59Q&pRZ(&>ZG>r#_Mr8}COVqglit5mBMr?eN9%t>3e_L>>od5hOI{1T#S~M^ zyOb8N;oVCcZ@NDjlDdN6K&fGHN{tTF?z0%YSu11{7_O;HlVEN7#^mn^NhTqv=pO^} zu|~lE!HXdyaL#&2-d{Uo3C)@%YRY&1j{=>|FGe27F`%Ntxxe>XepkCVi<~#_{2m|Bpvd{B??&U) zV3F7hCh(Bi(*wn_{d;1lwl42Zug@fy2&+?aWc~RxCi&hxTx@7e*Pg!mecxKiBZh18 z1cRT0aA_o{!lL=t69O(Y=RJeXoC7am9^6;o^%qpG0t9s2TU*YQ5^*iKrRL0*eQdv|e8KMQ z=!S;kkA@=J`MmEqz2j0)F)a5^JK@A${xbO`fW~fq)_afpqVyXelsa%8x0I>3Zd}<> zp<8mA;KSO8k2RUJJ|BQG)?&X@zEFwF1h>~A^(zRy@z0vDxH8Yx2O$I(A76-_hklwh z{q~+m{eUqdC)mbW4^`LO8M@)Yx;0*BBf$qg-c#$u6TPIE5S5_|x^G~=sQg{rAhKa< zK@n`731&jS?O#G_W~_`q2XBc2IB6dm*>MTi;1MHz7fMDVsdJ5LmL?jQK+2FTrUGh~?5sb9wYI0?13Fh{6~x*cc?hSp`%xv{>`v&}Zy(7k z0(tIS3LYdzO}YUDQH&JJ76sS{4&J}Oqse^}9t2i^eWjwTrt9<2>Ycq_U)i0z5$&kn zRjv7KxHzucC?pX4&kFz|^4aCf@33+8e7fLrof%^3WH)9Xs^$gq0g*e zL@a<0X|uOV2WkVcvE?aXIrzw#9@9d}cb8oThos)+sJ>xylq35O^x>dr~vQ+La1-{#~Med{Ib$$p5mr-2vHHG}tnp@9$wBDol?pEH7V^0gcPF z_Jb~uhH)C1+?&?8jHMrv<3-rLq>#9v--A-zyD9?{MJvqm?-`&-b_jT*tG(coXkt4I zSzH>sSa@jnzWCe{>yWxRE&!a6_Sg~P8|Vp^CC+=3@oA7<(EU28x-;- zFG2C*>Srz@l0%pW*LW8G(km$a5vqHm!Fj_H`uJ4-&QuY#X{OO0wc64}t8#s)D2=~Z z-@c>cqi^wL5m)uHzusfGeqY5b(nkVfa4{;lsyohT3~tUkT(TQB7|mkgnSSP+n_Tut zn@NSA;!@7|A&!Fx(`zqgm#(h*(gSb3R~~h6sn5XkGXlQVv-1-^PB!p!I@Yy~MCJs# zX+L|T?3Ck_Tg;vHO(gyI=y-4v`l-uVjYY{#v&%lP6Pb(AV;h+wP~)Ps?eD*LSA%!E zbzi=4N+E7ol}@zc!?NbgI61ri`RCyMQ&=-;ojRZU;dnLHc?%tvKc;UM`*7?1(pW^aAliF)X0Ge*n|IB~k`R zfjdsECl<7&ChtD^FP*p-f)b68mvVOZfv;wEjA^{>4+2Ncvxxa&PH=f^#Y~(04W_My zhz*XIxHyc?K`xg4am)T9`oo%A!^_8uHg7Uk`n`^9K~o3{Oj3wlTJR!4sjgvep?{t? z@R@dN?^ndfZjD?;gNyGWb=lvH3z?S0#p45sBENti{M%?MMSFeFV@`=T@LyOXdj{(M>9Yk=QU7EdWvu0LDP9N7s+`^Z3;1Kzdo+hzKgn6A zP%)&C4#Zfg4!?NC$J3sv5Cw_p%Vfax`^kGq$867gpN`{yXj7Cvtc3*}7UlhoE%kSh zTHq2y^?Qf>0efAHM}f@U7a^7FyI_0Zqafrz^NqT0B{pt#^Y_(v=_Iv3D#;Y6q1Rm=+$)-|Sq3P>1l z#yu3n8UY6zl0xWpEQ2+&1+MO5Y>mH-wjza7=3-^ov``;?YX=^KC((>^GPnmA3XEOocGnXZ4c~-0uhzc|qug z$St$cYK^?HR?BL@6qy@2IAH1?er|=v{g22N^cx@mFD*B^Umz{OujXrCi5>^XSOw0? z2iE^~WtJo-wgYI6MU^F*a-;usdFxfYFC2am9DeAAeRILoZiZrryBu=hn{T0B4{X%< zp=3OF@ur{4MsUd@n~^aQ0?AT7#7c-5`8mkJCyw#A@Szps4VGot-!%tGn3T>e(+04x z9Sd=hG(EDU>7FAk7fWMBG3;+2dmU&~yg{v-PfJIvVipu00C|NB>ae$L3Zk>Xsd`CK z__RPhf3_@dCIpxK_-R#h{BV)Mg+Pt54xYmvTl)xH*X()qa~&ff;bSMrCjNj0>zCEU zGL;R0!;vjmLm`dI1mNm#SXIRvMz9>8tZkMpp~+GTRs=T_ixJ;ig(0Pt#1L9qo7;4h zdxI+`*2|>qS8i@R5a0sIbv6slVQbA>*+nm=^3u;&iUQsQn|&(dfbT0#?qOzwun>_j zG1%5l)8(JXV#gwqb1|%l{wYCh`Li^aG@(I%SlQWOnir|A?EH~AL$Hn#wfG674}Uf; z9r_C!upip+6B(P-O3TT?ru2Q_uJ=_*83J3OEy4WjV1}PqHX3;$CD+JSw>s2KKeGe5 z2kjLf4{NZ5aRNN_i0dEWeyhNFGv4vR890%*YBM30wgc371v@F<5BWcDB621}@Ghkj zKPDmaO8UX=Gq=Vzj~Yn*GK+-8vQ^o<7!J0Zo#o#l0DJv}7-Y5-PVJy}*QP&lCKKU@ z#-;1ih!u{&3&AAUJX~8fH0-Oi&N_LXbJU&&{I-9%6=z7#s4Idcso4`f{1Ofy^juq$ z1t(rrJ1XW2TLA|~&zLEZI5RH3p}2>jO*1O|tk%)zJ}Sb(XqaOScv>B-1P#T{llE~5 zts8cxc#~d-8pZ?_uzDB!i?;+2>b;t;zER;q34_LGYS!OO`EPQI6f&oHfcUY2z1k>A zuiiKAsV|_W1>Da@t1KjWlb3-^0pS}}ozuzw)@S@eh*$ZWIra;-(dkCG9gXndh{|ym zke~)YdFRVzDuXLWLbE*hkLYk|>D4vv@C+~JJ9JCFtjTiqMxtY(``XwYTsNU&PGk$p z`|jQzAtxuw?}=g~1@v^X4YUq?cOE9NTT8Fftv=v4;s_a35;gLG9pv@+Qu6cnp)bzcE(-Nn+M8>tdw^#L#mu%46Mxt99NlkvQM)7$VppSp zQtszRrgzrYFkmg#1v70G;Zrn<5+wrkg#7%j`t4(gK6i3EPBmSE8|x8kYW#@E-fSXr z(=klnC38(KaS==+RP(({!Ib+4j@DXD0vQNu80m4&mh04c8lK%{K2SdwJ}ENMAO4t8 z{R4SQHU1>ysl1S4rSMO-XLY>xq$xi9OJfqkns% zsg}>342;QXugd@Fm9t;-^x)x29&S z5jKOu#WaC}8!#R11Ch2c+1c4fSm}6fl)1Zy1h_~nT!))7^>*l}-1R0gEg+lkHN<|` zKYijmqv>8v{3jK|e#+KN^#O15U{#R3iDY(jGv+QY0 z1;**XP9^uz^nADswKhI7{PEGyqsGxrq-nLk;KsP=FdlQs3Hmsou6m;oKTN3@CkFdA zJa^)Wlqr=u)${F7aeS{qE8Q!P+Fu7lurN!mSqe!GK(Et7Dld$?P^G_(uZR7V9QA`z zG1$xjyw5P7g>1-2@+l1s)DAILrQEE1!IuQQ#~;*b9g?VdSs#Trb_ZyW{edrqgZI12 zyY>2_TVjj%Jf!2-&renA^Z`a)eC3wOv-^o;%)C$B4P3#`pj4x2eMnHc3 z>Xm7dudg;6WPjWKC0f0?Pj5KFOq%s4vN9gVJ6dgae=cjqfXteg34W+J-J1bWWUq4F zDx`ATM8{||Rr6E+L!6$LJsaS!FEKPbgO*+t zUL6Z$On6F^I?D%BdME|AJ z^Ka#rjkG!8f@@HI)nUjlu@wxew)=I27;nE3}~MfUCB zB=QEAVeYq>BJ4cAk!G073L+=&TQM752Grj-?u({Dq2Sj~V|P%Ft-17$Oiq0gM6VN@ zMGj7PQB^0(;1rCKu)DSjrq!aCv#_7y!P6ZxmLKLGc%1s*Oby)?%v%qkkYbZN{JhQ~ zbf*K%1~+%Uz=Zhk(`&a^h(Y$N0~u^fg9JMYY^JTQ-Zt%nveQ=!0MvU+UK0Wj0HW@F zV$3F;J@z-n#<~_`vB;_jBAFQDZPi@vcc(4Y0?jW$jDd%e?M~&QZ_jq-XWyRsKcrJ7 z{#2sacYPD-hu7K69{c%u%-5XSevP6Lm8?Dc>R+Jla}tQW|ZWR$e`-pwwT+{NlH z+|~`};PpVc*<~lb$G&(NJ?9<=D!4o7twVyPFgg1ti3Ge=d2W&_hh&-$P0KO#Q3{O^ zkrV=N2t~;WxxuXw2}Hua<_n9#jqdn>dx}jJ#4uzkUuhCod;XT=s={*P>_y{4`=vnV zSb-O*x;qdM3srepS!1}&^76VuBt+t%Hx546^A91Fy>1nPz#DC-^zO2n7*)y?N-E$` z$;%@c`RSt9U0l)x=e(fce1YK%8styfyzRsz$Wu7G)Xz;aWtbR6<5)scrDMpqm2+o6 z1y|(0&?!EUZrg%Fu@-pgMIvosop!YQj_-;^^3;V*Xbz~C=wG6H;j-^KJ4sRMu& zqMW(H49w>La zJ_BD56s_`o{n3(iP~;@YxFWM-=)BiUM{Uh;@qeeymI6#Dv+61>Yyj2Vo%QII`Las3 z#iWOTP*H2Ryl%=*y#CE+W8BWfadX-XIZ^^9`%N}7-&idmEc8KTwKqT3{fsvzqHdxB zh}fD?d2l}4;If)VMxaqUAGpD^k}j9SN-;*wE*^F*Exq98+?TAGt&sW#`vT8G7g67j z(7n%^N!j>U8YSaD&(BYaNx(Wl#HhFXVa*;c0e&u5n~(ka*pkJsr}(g~Id?FU@pVcj zvfETTmrJl? z+6?;eZf77&5C|7*HKAiwKb+Dij(mS)BetUh|?12Vg-P|*Bn*WOp76~Wo z?!_R$C+O<-zPC^M7TVbf=K>Sx3-!g!0p`uf)^<7ze01?&lp3SUK~(kFM3^cd3)25C zgS#Lju#@FpbsIo!zV)^(EfX!}r1pfhlY>@*~DDiI!VZoeUsD3VsPDd~&$0rg4 zEXmJS6DakY3C+3RwlAQTsF?WtH=NS`(6}P=KwBqxGl1V#LdzykT0fe^;%5O}}DB!&OqK2bojr z^t<}+Qsg=fo{=ev%bk9;LB`JVU6Zz-Q%4!(kgzKy2n5m+Yk_Y8_rw}C_LG&*0gHxv zcz6oo3M8#Uq;iFf}!_hacVsE{4+XFHmZ}pzxrjp_SQ0zsy zyj0?rH^{n_jn{1h^llo!{EaMA8vEv=^TbUX;+uD(Nz}Z!x!Dk`F!KbBOX6X&(T#04$32VGCS2(kMk*Rr7=WOM`az z_`j;k?1V{GZ!_9iIUe zKTGmkhvAW1Ju?rjwZ9A4bbZCYF}>aLd{X7gNo#B?SjM0N3lew(C@FL&Ku#hoxagM} z>V1XcUj_)u=|-a=b+c3n8KCBqFgI_UfM9!TYJGR=*)};X>yPImE+#fS;V2VlWna&) z1XDMN!#v&q-6B-y81s~umZ=2srA%PCl4?Vk($3>if6%-a6{YAmVMB&%&!HtDerpTm z)6%l};I;B6sB(Kqq-_8gd1RbrRs|)=Bb&aE5b31F%n%18(r5r@l*@isGw)_|O=XSY zO!M5pr%>gaI~l`LJg9%(MgvpW9bkJ3yvasD?l}y|6pZ)zIHmIyR>dRZ$(0uq2AFae z$6G;{-_U#CnLr)~Qcp@p5VfG2OS$QDF!$c&#dG|f|nuDc_bP(tRUiXSl( zG2do4HZjSnti*(3{xoR`bu~9M*kQ@pzHawop;*ah6Y9CoGj~(c`0>3YB^=_^KRGNEeY;HZ)T{bxZ zp$Alr*Db6)QAC#28+eek4e%0%rriJYUmwXeq&Er&YK@#7DH;dXTnt=NG;L z_gLz)7QiHXy)!K*MMv}-=)qwU;rKL}FCZ-~4eEsRx^z5bINVS%aC^!dUS0ytqFR+5 z{xlQ^hZI_r3ir!=+S!*c&-1_=W$PEMSV&A=!1|EEwMC)l96$*@)+c=}_F57qPzV79 zmIW7Agq*b>B@(y2pBz4H)UZ(V9{0P3p4Z^T8HPYt;CVX2?{|QjN|j4T_ndlCnEEac ziU2cYl!b&wKECIGT@OVVYsB=K$IP%)LmN8;OSRzq4AzR$WFU#ZxaGuOCY1-v-``(y z=Es%)@xlB{qio+;FF|dEv99N*i>>U@0G@U$`&O%lFJR<&IaK>Z-zRi-_HCOF^Nmq6wfQzds>a!RV2GCFUprv2q+-aJvKf&|R0W`uxjmrXy;hQ>`Z&A?>YAAG=gbNb~q zIN z;Q^TKVs&K@IwvK5FEn^y6e@A^l2WWzc*FSl2qIs>G-jx^Ithln%)srhrv%S{7qf4aG3tk`lkMgW97P^ASPYVdi{SK_aa91ftTjq#de| zJmq3OTR?+j5+$20xAWd=^v-P7PIbxo!P=^nY+ssk`70$!ABh#aYuJ$qOsZS(c)CpbI~}KN_o2MZ%xAK)@WaEyUjhQ$IpUr@av4!U-DiuKB4k@T=WVlj{b)%L_uHgEbEpD&&h&$G-HM+>VFJge zYHFNnFcFC=^nb8X-==Fsk`X}<0XDngVs&v@edu%HU5)oEhZ%7EoZJnhbk0t0n`}F^ zs$78~Gn5xKbCx7VM?lxU4hf`4<{fS$cu15&3ze6yM+E=_LEd=>ULNGc{*C9x#>Tc? z7(w&^4B6N)0iu2yZ`Jm=qoOld3AnXaV`)h@j=$lQ@SI!L2(nxb>aeA#yNNT%T-Rk4 z=dG-;HYG}M8fLScIo&QD?wXpC|8(`H1FqsQpwV?$`*j%duktzndS#Tw*4-z_w>CGw zFA9!GQWDB*T;!FCp?A{tt7o9VSUQ1?U*UD;_gzwuI9jEefXfvlGpJLAS%lbb{+$p3 z*rP9mHuTe$POnm3kNZ9}n${uM#fHHqthO@Jr@w^6KfOnF?s_XbPX6d*Qf-7cqfk)j7|Q<6q!^d& z<)4qHrtQY8lGui6->%-LxJ+vVv7yL_m}er*KM*7Pe+5b&7L%J&kTx7^T8YIegfk5% zseXe_6sxibYPzz$-yut->qqY)QHm@}(iNBoEf*XSG9@hFUIAk^s4ED!WXLlCX#i9q zk?i)p?`-PylSBNosb)XHWdxF%--QSH(oihtf2**-7Glq<`+=wgN^DTQO?^jiYL#%x z8bJdto)^S+GVnlxgDBMiOb7E0fp-=G)0H)n= z*`e-ioy+kzd@`V}lpY7 zlb4tYgT%B$tj31FjqnBdzI|=@qO2af0rZ=+*)uIrWuNd}!h)wHDWlEzC`(5NO^-vC zuhR309pse%l_5@F`+Lj-;$T%oYYRtFQdL7iE&MQS3lqqDSH8mp$`P=^fipe^9`$L5 zQ_$l+)pZ~#RLA^fjHW>an)+O;h$L{C0FvT0dQgrP3E-2D-4`$z6tGaGI}VM;>h9NP z4pe7UKZ77+xJ^`pK>U7?WnJF_?UaLD&r44LG}=$2twM01Q6J;p!nL4g%4Q5`<_;SO zjsTA^6shtqe{|s^%1htn%oQEx{*bTxYHBrd|BJt3&203r>@yJGt)Ps#jOkROFUb2l zYekCUe=HEGkESOW*(pDM~;Evaj*j z*v*Os>k4~!^cwxk=r4Ag>ADvLi?fB_kmj#XH>FwCH~U{#^cYLk8J&T|Hr;qTKJE^W zLa5Mx23`WqWfLVcxbkQ$zbYK)88`SrM*=^4^9na=s=WsI-|3rk5ykjT*CFjLWMl@8 zF3>KH?idgg#R5vK6l_J^mkLg_o~IgkN#U=hjpO-UnQ49W3+Ggg?{8Amx)8U)C#p9; zaLmA^lmI3I>{jST!36u5nW*sR1&O?A#td)4{i3(Hrltbn5LV}E)Z}aX2@$d}J3h;& z$vyC&<>MQ|$-ShfrKW!6=mZmn1$5SkMgLy(1L9Sk2}x1b z?*9M003}Yq5{s_!MImzo*kMx}`0S)O+ zUPsR8CsPlG#{0HRle`KSv@g!{q$ZaFmt*-SExvBPnO@B3 z8yR+7P}D{_jnIgL9oAB9l?S(x(&w)tPi-2s1 zIcMQILzcyg6Q3A6U)2CSg>tD2Kc1e zKsCDV#`p^N{cGmeT|fArpjJ5)snCG*Gs_60LrffA*Nv>tdUqEW7lsbXuCdS8?kGT| z0|HuvVCf5wNc9Snmy;#lve+ujOhpMHp!o-0>|XCj3-!Mg?umL0G`1MXx$O zIVpv29Hv%Ts#%mJ3mwCQBjr;@P@C_D)*qPA3yiTK_H;YulsimyO%l@ATT>Q1Ia$#@ zj5@eLtJl<_r5$`Job72H5IM zj{jfd0(m_y*wLw=2KYdR^one}0kH+cZWj+w<85t*X&vT5IL$zWgoBSg_VGNQ2*LP0 zjTJp(88Blh=H$eQS}3UtWdn9hfm(^&4QwgU?fv?i{ClH<%Z4U{qwLH$3irg>@&46W zy~R3q1%rgm`C3}_BBLSmSN?f3mK&id=17Qe;>Hu|U5}J#)ltY{mXH`ity5@i@`*zw_4NbeX&M&x8hsps%#*&cDm$ z0Z0QqBH}MZ3c|}rjVf;4BD>?2PsVDHz0+pNnVpgG{==IHmuGzMq?7I5=oC-bu!Kr#hf)0q=;dJ8#qic6@W*xwh>P4z@LsS_qEw1-B zQ^ub$;&B==x!$@wzrTN|oLMmZgmREy@=+;>UN%q0_UpCFboav{(Sq zZ8^9dkdyi2;^Fx$9!7th*l?-p{ri_9IxQ%IZIw2pYs_b&KyCGWYKp3g=)Y!~46g5w z9-RtoG#_kgP@B@4D*tW(n?fj4a}bEvk~Se7h8-&%A!RPd98m+c$@IrEF#{&jGpC>V zmQwcY)yYP!CR6|a`bSjvu0I0DAylb?HPOE&yl_+7q_gCvk`kO{TXpRH{Nl85@Rb10 zjoZ5k7GyRj1oQ{EQbckmJ`lJ#_-t=$^v4O7Y3T*6vD;ZhFg~BD^FH@GNz%06O<(Nn zo7I(d<1KEw8Sf|_f0{K=sm8J)ed}M{Zn-(%J^uTtq{k5Po$i?;IeNg*RPxCLfqLqb zwDc_|BX>R!^uc_!c}-s6w7#}RMnx6R`%OX+JTGm#^5+ZvUv#D=$UviY;STlawC;#co0-AmDkSG*@OsT=(v@;m`iXUg};5n6dO2 zqmm;NXbK?|thukab#&NOn*5y4gH#f8o1x@3wse8FqU+ELb1Wn;vrPrAD)>!XP^Zyb z{EpV_lj}ATpyEO7NVOkrM*l|ipAy=@Q4Qtq4D6O!&8lkDL_?D+Ep~S!cr@t(yh&4I z1*|Ug^#^4CbrO+vfKvK@@mY0$)T|O{Y!Q)>t*Ij9_TY*2#zuY#_S*<*Qbd=80TZxG z0fliejrj@zrqpRaDJLK~e&I9HhN@cXrStbhxVPFJa|SsQsRu^5d@M01vvm;QG+j=Y zZxvxLD3;mb*T4P1cMV{})jE@RnDgSikG?|FAsa}SpaP4#{h8NA*M}z!rM>Uu?j&>3 z@xnhTbQhZJ56Z{&rmC7zPGgrVaG^)=t1EEW;aM9Rodwyo&_ZZa1pgm zjm4MG;s9KEyv_x2`;KgK=Pq4e?cI3^fb_@zu-okAcW_{>Q6-zJ*lJOgx353m^e$aH z-SHhHoylHw1O+7FJabVCYc#CEv0G!8l_<~41U+;=3kurruGP9(`?b~86I91&s6~Z^ zq0?M9%=Z==wN4zTfUuiKa^-Bsfq#IIg=EGv`h81+eS3eps)U%y$`dy8+u4{aC0l>t zgvGM$TYc6<7v^3WkDDwIH?k|nqR%eCef!gvN|}oJwf3Xk!^5xO;O^{Flgzb2<7#bQ zb@0TK6a5=C1*GNyF6k(h1%l^-|1!x^jPUwA+haF{BcZG@FBim(OSx;1=y#HP`^38>!RG++RqjRb$-> z_69lX*MTG_G_QMk0paRM75SjSkNV7Cs*Uy~ZMyzz?3HL*Fb+tZu;4&MLK<5U;>9Y| zd&CD>nSln{afOwYojG}6*vzG!Y#tn{t=(Pezrv*=rT=Y~+$nMOTw0I~?9ixjy$Mn^}WZi8eaUx1yOBq;< z)A{c(5s`k_!M{rNukVBQZb`2^hi@0W+pE&ctkb!n2`UDgT(wX=G3GP{0EG7CFPcRg zfE zB9bHw3h=Uv$_uoUQHv_uI&IME^JNXQcy!lM-OZGN)-*o+zTdJ(+$VMhO0hT&I#AKV z9YQleI+{Hi0eytz=&09Ks8ON#kYJFY@fLiK*NmyAlR;vEz>(2YW)2N7�)6~4s+ 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%0A-ub8hJ=@QU>-x8PqKR3r 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

    lW@Znwwk~BmPbdH%uB7_YbIlAWN&4yBN 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∨qgdZOytke3mcK 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.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 z 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 Uvi6cL`X6#q%Ga~68vOnL0DIz(O#lD@ literal 0 HcmV?d00001 diff --git a/vendor/github.com/golang/dep/docs/assets/DigbyScene2Shadows.svg b/vendor/github.com/golang/dep/docs/assets/DigbyScene2Shadows.svg new file mode 100644 index 00000000..4122d3d1 --- /dev/null +++ b/vendor/github.com/golang/dep/docs/assets/DigbyScene2Shadows.svg @@ -0,0 +1 @@ +BoyerScene2Shadows \ No newline at end of file diff --git a/vendor/github.com/golang/dep/docs/assets/DigbyShadows.png b/vendor/github.com/golang/dep/docs/assets/DigbyShadows.png new file mode 100644 index 0000000000000000000000000000000000000000..649214512735de02f57bd0a5b31d71e6d9732d55 GIT binary patch literal 456068 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

    a2T`w< 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

    {VYWhfr(>?EFGW&D?J+uFkA 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

    Cl1 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

    <>&?zlQ$**wZRpL8w@n>hu^#+D`FBXN=+F7 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%0A>PKZpmPey- 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 Q!GBQSx$lp--wgl$e;pU|MF0Q* literal 0 HcmV?d00001 diff --git a/vendor/github.com/golang/dep/docs/assets/DigbyShadows.svg b/vendor/github.com/golang/dep/docs/assets/DigbyShadows.svg new file mode 100644 index 00000000..305806cd --- /dev/null +++ b/vendor/github.com/golang/dep/docs/assets/DigbyShadows.svg @@ -0,0 +1 @@ +BoyerShadows \ No newline at end of file diff --git a/vendor/github.com/golang/dep/docs/assets/DigbyShadowsScene2.png b/vendor/github.com/golang/dep/docs/assets/DigbyShadowsScene2.png new file mode 100644 index 0000000000000000000000000000000000000000..0d72555c531d2fe464c6ebf07a744a87d33ab1f1 GIT binary patch literal 619236 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

    ?2Or1ehVBa#X;NiMa@6ZH;R^CKFLWL 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%0Aw3T-$F!gswKhbSc9=i=(eog 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 {~`$S9{fnGCZ<6iCY7%ppCyQe+-<=8Jq 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�NMN$43APaUb_2QP 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 k{Tvs}#QN>@qt$@y-i` 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 om$SaBoyerShadowsScene2 \ No newline at end of file diff --git a/vendor/github.com/golang/dep/docs/assets/StatusGraph.png b/vendor/github.com/golang/dep/docs/assets/StatusGraph.png new file mode 100644 index 0000000000000000000000000000000000000000..5380aecae1ee420bfb1bf7e4a9058789eb35e40f GIT binary patch literal 19271 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 QGZsl%UR~~`?BzTE3kVC41poj5 literal 0 HcmV?d00001 diff --git a/vendor/github.com/golang/dep/docs/assets/annotated-func-arrows.png b/vendor/github.com/golang/dep/docs/assets/annotated-func-arrows.png new file mode 100644 index 0000000000000000000000000000000000000000..cc9190f2a0431c36d7d53bce3ceb2198ca3e67fa GIT binary patch literal 42366 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 R{SFzh=xdwYtI=|P_CFilNeKV| literal 0 HcmV?d00001 diff --git a/vendor/github.com/golang/dep/docs/assets/base-arrows.png b/vendor/github.com/golang/dep/docs/assets/base-arrows.png new file mode 100644 index 0000000000000000000000000000000000000000..d60e598c86421c9ccd0630cb1edd5fcfe0b15dc4 GIT binary patch literal 33999 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 + ); + } +} + +module.exports = Footer; diff --git a/vendor/github.com/golang/dep/website/i18n/en.json b/vendor/github.com/golang/dep/website/i18n/en.json new file mode 100644 index 00000000..caf77a3d --- /dev/null +++ b/vendor/github.com/golang/dep/website/i18n/en.json @@ -0,0 +1,30 @@ +{ + "_comment": "This file is auto-generated by write-translations.js", + "localized-strings": { + "next": "Next", + "previous": "Previous", + "tagline": "Dependency management for Go", + "daily-dep": "Daily Dep", + "deduction": "Import Path Deduction", + "ensure-mechanics": "Models and Mechanisms", + "failure-modes": "Failure Modes", + "FAQ": "FAQ", + "glossary": "Glossary", + "Gopkg.lock": "Gopkg.lock", + "Gopkg.toml": "Gopkg.toml", + "installation": "Installation", + "introduction": "Getting Started", + "migrating": "Migrating to Dep", + "new-project": "Creating a New Project", + "the-solver": "The Solver", + "Documentation": "Documentation", + "Blog": "Blog", + "Guides": "Guides", + "References": "References" + }, + "pages-strings": { + "Help Translate|recruit community translators for your project": "Help Translate", + "Edit this Doc|recruitment message asking to edit the doc source": "Edit", + "Translate this Doc|recruitment message asking to translate the docs": "Translate" + } +} diff --git a/vendor/github.com/golang/dep/website/package.json b/vendor/github.com/golang/dep/website/package.json new file mode 100644 index 00000000..ec2e7d74 --- /dev/null +++ b/vendor/github.com/golang/dep/website/package.json @@ -0,0 +1,14 @@ +{ + "scripts": { + "examples": "docusaurus-examples", + "start": "docusaurus-start", + "build": "docusaurus-build", + "publish-gh-pages": "docusaurus-publish", + "write-translations": "docusaurus-write-translations", + "version": "docusaurus-version", + "rename-version": "docusaurus-rename-version" + }, + "devDependencies": { + "docusaurus": "^1.0.5" + } +} diff --git a/vendor/github.com/golang/dep/website/pages/en/help.js b/vendor/github.com/golang/dep/website/pages/en/help.js new file mode 100755 index 00000000..0a63c19e --- /dev/null +++ b/vendor/github.com/golang/dep/website/pages/en/help.js @@ -0,0 +1,43 @@ +const React = require('react'); + +const CompLibrary = require('../../core/CompLibrary.js'); +const Container = CompLibrary.Container; +const GridBlock = CompLibrary.GridBlock; + +const siteConfig = require(process.cwd() + '/siteConfig.js'); + +class Help extends React.Component { + render() { + const supportLinks = [ + { + content: + 'Learn more using the [documentation on this site.](/test-site/docs/en/doc1.html)', + title: 'Browse Docs', + }, + { + content: 'Ask questions about the documentation and project', + title: 'Join the community', + }, + { + content: "Find out what's new with this project", + title: 'Stay up to date', + }, + ]; + + return ( +
    + +
    +
    +

    Need help?

    +
    +

    This project is maintained by a dedicated group of people.

    + +
    +
    +
    + ); + } +} + +module.exports = Help; diff --git a/vendor/github.com/golang/dep/website/pages/en/index.js b/vendor/github.com/golang/dep/website/pages/en/index.js new file mode 100755 index 00000000..11437ae9 --- /dev/null +++ b/vendor/github.com/golang/dep/website/pages/en/index.js @@ -0,0 +1,92 @@ +const React = require('react'); + +const CompLibrary = require('../../core/CompLibrary.js'); +const MarkdownBlock = CompLibrary.MarkdownBlock; /* Used to read markdown */ +const Container = CompLibrary.Container; +const GridBlock = CompLibrary.GridBlock; + +const siteConfig = require(process.cwd() + '/siteConfig.js'); + +class Button extends React.Component { + render() { + return ( + + ); + } +} + +function assetUrl(img) { + return siteConfig.baseUrl + 'docs/assets/' + img; +} + +function docUrl(doc, language) { + return siteConfig.baseUrl + 'docs/' + (language ? language + '/' : '') + doc; +} + +Button.defaultProps = { + target: '_self', +}; + +const SplashContainer = props => ( +
    +
    +
    {props.children}
    +
    +
    +); + +const Logo = props => ( +
    + +
    +); + +const ProjectTitle = props => ( +

    + {siteConfig.title} + {siteConfig.tagline} +

    +); + +const PromoSection = props => ( +
    +
    +
    {props.children}
    +
    +
    +); + +class HomeSplash extends React.Component { + render() { + let language = this.props.language || ''; + return ( + + +
    + + + + + + +
    +
    + ); + } +} + +class Index extends React.Component { + render() { + let language = this.props.language || ''; + + return ( + + ); + } +} + +module.exports = Index; diff --git a/vendor/github.com/golang/dep/website/pages/en/users.js b/vendor/github.com/golang/dep/website/pages/en/users.js new file mode 100644 index 00000000..b94c4bc6 --- /dev/null +++ b/vendor/github.com/golang/dep/website/pages/en/users.js @@ -0,0 +1,40 @@ +const React = require('react'); + +const CompLibrary = require('../../core/CompLibrary.js'); +const Container = CompLibrary.Container; + +const siteConfig = require(process.cwd() + '/siteConfig.js'); + +class Users extends React.Component { + render() { + const showcase = siteConfig.users.map((user, i) => { + return ( + + + + ); + }); + + return ( +
    + +
    +
    +

    Who's Using This?

    +

    This project is used by many folks

    +
    +
    {showcase}
    +

    Are you using this project?

    + + Add your company + +
    +
    +
    + ); + } +} + +module.exports = Users; diff --git a/vendor/github.com/golang/dep/website/sidebars.json b/vendor/github.com/golang/dep/website/sidebars.json new file mode 100644 index 00000000..962d2bc6 --- /dev/null +++ b/vendor/github.com/golang/dep/website/sidebars.json @@ -0,0 +1,6 @@ +{ + "docs": { + "Guides": ["introduction", "installation", "new-project", "migrating", "daily-dep"], + "References": ["ensure-mechanics", "failure-modes", "the-solver", "deduction", "Gopkg.toml", "Gopkg.lock", "FAQ", "glossary"] + } +} diff --git a/vendor/github.com/golang/dep/website/siteConfig.js b/vendor/github.com/golang/dep/website/siteConfig.js new file mode 100644 index 00000000..41acaeca --- /dev/null +++ b/vendor/github.com/golang/dep/website/siteConfig.js @@ -0,0 +1,46 @@ +/* List of projects/orgs using your project for the users page */ +const users = [ +]; + +const siteConfig = { + title: 'dep' /* title for your website */, + tagline: 'Dependency management for Go', + url: 'https://golang.github.io' /* your website url */, + baseUrl: '/dep/' /* base url for your project */, + editUrl: 'https://github.com/golang/dep/edit/master/docs/', + projectName: 'dep', + headerLinks: [ + {doc: 'introduction', label: 'Documentation'}, + {blog: true, label: 'Blog'}, + ], + users, + /* path to images for header/footer */ + headerIcon: 'docs/assets/DigbyFlat.svg', + footerIcon: 'docs/assets/DigbyShadowsScene2.svg', + favicon: 'docs/assets/DigbyScene2Flat.png', + /* colors for website */ + colors: { + secondaryColor: '#E0EBF5', + primaryColor: '#375EAB', + }, + //algolia: { + //apiKey: "f2e26cf744b3d81c7e57499075753104", + //indexName: "dep-docs" + //}, + // This copyright info is used in /core/Footer.js and blog rss/atom feeds. + copyright: + 'Copyright © ' + + new Date().getFullYear() + + ' The Go Authors', + organizationName: 'golang', // or set an env variable ORGANIZATION_NAME + projectName: 'dep', // or set an env variable PROJECT_NAME + highlight: { + // Highlight.js theme to use for syntax highlighting in code blocks + theme: 'default', + }, + scripts: ['https://buttons.github.io/buttons.js'], + // You may provide arbitrary config keys to be used as needed by your template. + repoUrl: 'https://github.com/golang/dep', +}; + +module.exports = siteConfig; diff --git a/vendor/github.com/golang/dep/website/static/css/custom.css b/vendor/github.com/golang/dep/website/static/css/custom.css new file mode 100644 index 00000000..097e466a --- /dev/null +++ b/vendor/github.com/golang/dep/website/static/css/custom.css @@ -0,0 +1,52 @@ +/* your custom css */ + +.homeContainer { + flex: 1 0 auto; + padding-bottom: 1em; +} + +.docMainWrapper { + flex: 1 0 auto; + padding-bottom: 1em; +} + +.homeContainer .homeWrapper .projectLogo { + justify-content: center; + position: relative; + padding: 2em; +} + +.homeContainer .homeWrapper .projectLogo img { + max-height: 360px; +} + +body { + display: flex; + flex-direction: column; +} + +div.navPusher { + display: flex; + flex-direction: column; +} + +.footer-logo { + padding-top: 1em; + display: flex; + justify-content: center; +} + +@media only screen and (min-device-width: 360px) and (max-device-width: 736px) { +} + +@media only screen and (min-width: 1024px) { +} + +@media only screen and (max-width: 1023px) { +} + +@media only screen and (min-width: 1400px) { +} + +@media only screen and (min-width: 1500px) { +} diff --git a/vendor/github.com/golang/dep/website/yarn.lock b/vendor/github.com/golang/dep/website/yarn.lock new file mode 100644 index 00000000..cb5417d7 --- /dev/null +++ b/vendor/github.com/golang/dep/website/yarn.lock @@ -0,0 +1,1739 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +accepts@~1.3.4: + version "1.3.4" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.4.tgz#86246758c7dd6d21a6474ff084a4740ec05eb21f" + dependencies: + mime-types "~2.1.16" + negotiator "0.6.1" + +ajv@^5.1.0: + version "5.5.2" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" + dependencies: + co "^4.6.0" + fast-deep-equal "^1.0.0" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.3.0" + +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + +ansi-styles@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" + +ansi-styles@^3.1.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.0.tgz#c159b8d5be0f9e5a6f346dab94f16ce022161b88" + dependencies: + color-convert "^1.9.0" + +argparse@^1.0.7: + version "1.0.9" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.9.tgz#73d83bc263f86e97f8cc4f6bae1b0e90a7d22c86" + dependencies: + sprintf-js "~1.0.2" + +argparse@~0.1.15: + version "0.1.16" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-0.1.16.tgz#cfd01e0fbba3d6caed049fbd758d40f65196f57c" + dependencies: + underscore "~1.7.0" + underscore.string "~2.4.0" + +array-flatten@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" + +asap@~2.0.3: + version "2.0.6" + resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" + +asn1@~0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86" + +assert-plus@1.0.0, assert-plus@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + +autolinker@~0.15.0: + version "0.15.3" + resolved "https://registry.yarnpkg.com/autolinker/-/autolinker-0.15.3.tgz#342417d8f2f3461b14cf09088d5edf8791dc9832" + +aws-sign2@~0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" + +aws4@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e" + +babel-code-frame@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" + dependencies: + chalk "^1.1.3" + esutils "^2.0.2" + js-tokens "^3.0.2" + +babel-core@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.0.tgz#af32f78b31a6fcef119c87b0fd8d9753f03a0bb8" + dependencies: + babel-code-frame "^6.26.0" + babel-generator "^6.26.0" + babel-helpers "^6.24.1" + babel-messages "^6.23.0" + babel-register "^6.26.0" + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + convert-source-map "^1.5.0" + debug "^2.6.8" + json5 "^0.5.1" + lodash "^4.17.4" + minimatch "^3.0.4" + path-is-absolute "^1.0.1" + private "^0.1.7" + slash "^1.0.0" + source-map "^0.5.6" + +babel-generator@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.0.tgz#ac1ae20070b79f6e3ca1d3269613053774f20dc5" + dependencies: + babel-messages "^6.23.0" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + detect-indent "^4.0.0" + jsesc "^1.3.0" + lodash "^4.17.4" + source-map "^0.5.6" + trim-right "^1.0.1" + +babel-helper-builder-binary-assignment-operator-visitor@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz#cce4517ada356f4220bcae8a02c2b346f9a56664" + dependencies: + babel-helper-explode-assignable-expression "^6.24.1" + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-builder-react-jsx@^6.24.1: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.26.0.tgz#39ff8313b75c8b65dceff1f31d383e0ff2a408a0" + dependencies: + babel-runtime "^6.26.0" + babel-types "^6.26.0" + esutils "^2.0.2" + +babel-helper-call-delegate@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz#ece6aacddc76e41c3461f88bfc575bd0daa2df8d" + dependencies: + babel-helper-hoist-variables "^6.24.1" + babel-runtime "^6.22.0" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-define-map@^6.24.1: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz#a5f56dab41a25f97ecb498c7ebaca9819f95be5f" + dependencies: + babel-helper-function-name "^6.24.1" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + lodash "^4.17.4" + +babel-helper-explode-assignable-expression@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz#f25b82cf7dc10433c55f70592d5746400ac22caa" + dependencies: + babel-runtime "^6.22.0" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-function-name@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz#d3475b8c03ed98242a25b48351ab18399d3580a9" + dependencies: + babel-helper-get-function-arity "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-get-function-arity@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz#8f7782aa93407c41d3aa50908f89b031b1b6853d" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-hoist-variables@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz#1ecb27689c9d25513eadbc9914a73f5408be7a76" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-optimise-call-expression@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz#f7a13427ba9f73f8f4fa993c54a97882d1244257" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-regex@^6.24.1: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz#325c59f902f82f24b74faceed0363954f6495e72" + dependencies: + babel-runtime "^6.26.0" + babel-types "^6.26.0" + lodash "^4.17.4" + +babel-helper-remap-async-to-generator@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz#5ec581827ad723fecdd381f1c928390676e4551b" + dependencies: + babel-helper-function-name "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-replace-supers@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz#bf6dbfe43938d17369a213ca8a8bf74b6a90ab1a" + dependencies: + babel-helper-optimise-call-expression "^6.24.1" + babel-messages "^6.23.0" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helpers@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2" + dependencies: + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-messages@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-check-es2015-constants@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz#35157b101426fd2ffd3da3f75c7d1e91835bbf8a" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-syntax-async-functions@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95" + +babel-plugin-syntax-exponentiation-operator@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz#9ee7e8337290da95288201a6a57f4170317830de" + +babel-plugin-syntax-flow@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz#4c3ab20a2af26aa20cd25995c398c4eb70310c8d" + +babel-plugin-syntax-jsx@^6.3.13, babel-plugin-syntax-jsx@^6.8.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz#0af32a9a6e13ca7a3fd5069e62d7b0f58d0d8946" + +babel-plugin-syntax-trailing-function-commas@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3" + +babel-plugin-transform-async-to-generator@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz#6536e378aff6cb1d5517ac0e40eb3e9fc8d08761" + dependencies: + babel-helper-remap-async-to-generator "^6.24.1" + babel-plugin-syntax-async-functions "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-arrow-functions@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz#452692cb711d5f79dc7f85e440ce41b9f244d221" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-block-scoped-functions@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz#bbc51b49f964d70cb8d8e0b94e820246ce3a6141" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-block-scoping@^6.23.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz#d70f5299c1308d05c12f463813b0a09e73b1895f" + dependencies: + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + lodash "^4.17.4" + +babel-plugin-transform-es2015-classes@^6.23.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz#5a4c58a50c9c9461e564b4b2a3bfabc97a2584db" + dependencies: + babel-helper-define-map "^6.24.1" + babel-helper-function-name "^6.24.1" + babel-helper-optimise-call-expression "^6.24.1" + babel-helper-replace-supers "^6.24.1" + babel-messages "^6.23.0" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-computed-properties@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz#6fe2a8d16895d5634f4cd999b6d3480a308159b3" + dependencies: + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-destructuring@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz#997bb1f1ab967f682d2b0876fe358d60e765c56d" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-duplicate-keys@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz#73eb3d310ca969e3ef9ec91c53741a6f1576423e" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-for-of@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz#f47c95b2b613df1d3ecc2fdb7573623c75248691" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-function-name@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz#834c89853bc36b1af0f3a4c5dbaa94fd8eacaa8b" + dependencies: + babel-helper-function-name "^6.24.1" + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-literals@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz#4f54a02d6cd66cf915280019a31d31925377ca2e" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-modules-amd@^6.22.0, babel-plugin-transform-es2015-modules-amd@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz#3b3e54017239842d6d19c3011c4bd2f00a00d154" + dependencies: + babel-plugin-transform-es2015-modules-commonjs "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-modules-commonjs@^6.23.0, babel-plugin-transform-es2015-modules-commonjs@^6.24.1: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.0.tgz#0d8394029b7dc6abe1a97ef181e00758dd2e5d8a" + dependencies: + babel-plugin-transform-strict-mode "^6.24.1" + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-types "^6.26.0" + +babel-plugin-transform-es2015-modules-systemjs@^6.23.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz#ff89a142b9119a906195f5f106ecf305d9407d23" + dependencies: + babel-helper-hoist-variables "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-modules-umd@^6.23.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz#ac997e6285cd18ed6176adb607d602344ad38468" + dependencies: + babel-plugin-transform-es2015-modules-amd "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-object-super@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz#24cef69ae21cb83a7f8603dad021f572eb278f8d" + dependencies: + babel-helper-replace-supers "^6.24.1" + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-parameters@^6.23.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz#57ac351ab49caf14a97cd13b09f66fdf0a625f2b" + dependencies: + babel-helper-call-delegate "^6.24.1" + babel-helper-get-function-arity "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-shorthand-properties@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz#24f875d6721c87661bbd99a4622e51f14de38aa0" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-spread@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz#d6d68a99f89aedc4536c81a542e8dd9f1746f8d1" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-sticky-regex@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz#00c1cdb1aca71112cdf0cf6126c2ed6b457ccdbc" + dependencies: + babel-helper-regex "^6.24.1" + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-template-literals@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz#a84b3450f7e9f8f1f6839d6d687da84bb1236d8d" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-typeof-symbol@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz#dec09f1cddff94b52ac73d505c84df59dcceb372" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-unicode-regex@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz#d38b12f42ea7323f729387f18a7c5ae1faeb35e9" + dependencies: + babel-helper-regex "^6.24.1" + babel-runtime "^6.22.0" + regexpu-core "^2.0.0" + +babel-plugin-transform-exponentiation-operator@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz#2ab0c9c7f3098fa48907772bb813fe41e8de3a0e" + dependencies: + babel-helper-builder-binary-assignment-operator-visitor "^6.24.1" + babel-plugin-syntax-exponentiation-operator "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-flow-strip-types@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz#84cb672935d43714fdc32bce84568d87441cf7cf" + dependencies: + babel-plugin-syntax-flow "^6.18.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-react-display-name@^6.23.0: + version "6.25.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.25.0.tgz#67e2bf1f1e9c93ab08db96792e05392bf2cc28d1" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-react-jsx-self@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-jsx-self/-/babel-plugin-transform-react-jsx-self-6.22.0.tgz#df6d80a9da2612a121e6ddd7558bcbecf06e636e" + dependencies: + babel-plugin-syntax-jsx "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-react-jsx-source@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-jsx-source/-/babel-plugin-transform-react-jsx-source-6.22.0.tgz#66ac12153f5cd2d17b3c19268f4bf0197f44ecd6" + dependencies: + babel-plugin-syntax-jsx "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-react-jsx@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz#840a028e7df460dfc3a2d29f0c0d91f6376e66a3" + dependencies: + babel-helper-builder-react-jsx "^6.24.1" + babel-plugin-syntax-jsx "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-regenerator@^6.22.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz#e0703696fbde27f0a3efcacf8b4dca2f7b3a8f2f" + dependencies: + regenerator-transform "^0.10.0" + +babel-plugin-transform-strict-mode@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz#d5faf7aa578a65bbe591cf5edae04a0c67020758" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-preset-env@^1.6.0: + version "1.6.1" + resolved "https://registry.yarnpkg.com/babel-preset-env/-/babel-preset-env-1.6.1.tgz#a18b564cc9b9afdf4aae57ae3c1b0d99188e6f48" + dependencies: + babel-plugin-check-es2015-constants "^6.22.0" + babel-plugin-syntax-trailing-function-commas "^6.22.0" + babel-plugin-transform-async-to-generator "^6.22.0" + babel-plugin-transform-es2015-arrow-functions "^6.22.0" + babel-plugin-transform-es2015-block-scoped-functions "^6.22.0" + babel-plugin-transform-es2015-block-scoping "^6.23.0" + babel-plugin-transform-es2015-classes "^6.23.0" + babel-plugin-transform-es2015-computed-properties "^6.22.0" + babel-plugin-transform-es2015-destructuring "^6.23.0" + babel-plugin-transform-es2015-duplicate-keys "^6.22.0" + babel-plugin-transform-es2015-for-of "^6.23.0" + babel-plugin-transform-es2015-function-name "^6.22.0" + babel-plugin-transform-es2015-literals "^6.22.0" + babel-plugin-transform-es2015-modules-amd "^6.22.0" + babel-plugin-transform-es2015-modules-commonjs "^6.23.0" + babel-plugin-transform-es2015-modules-systemjs "^6.23.0" + babel-plugin-transform-es2015-modules-umd "^6.23.0" + babel-plugin-transform-es2015-object-super "^6.22.0" + babel-plugin-transform-es2015-parameters "^6.23.0" + babel-plugin-transform-es2015-shorthand-properties "^6.22.0" + babel-plugin-transform-es2015-spread "^6.22.0" + babel-plugin-transform-es2015-sticky-regex "^6.22.0" + babel-plugin-transform-es2015-template-literals "^6.22.0" + babel-plugin-transform-es2015-typeof-symbol "^6.23.0" + babel-plugin-transform-es2015-unicode-regex "^6.22.0" + babel-plugin-transform-exponentiation-operator "^6.22.0" + babel-plugin-transform-regenerator "^6.22.0" + browserslist "^2.1.2" + invariant "^2.2.2" + semver "^5.3.0" + +babel-preset-flow@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-preset-flow/-/babel-preset-flow-6.23.0.tgz#e71218887085ae9a24b5be4169affb599816c49d" + dependencies: + babel-plugin-transform-flow-strip-types "^6.22.0" + +babel-preset-react@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-preset-react/-/babel-preset-react-6.24.1.tgz#ba69dfaea45fc3ec639b6a4ecea6e17702c91380" + dependencies: + babel-plugin-syntax-jsx "^6.3.13" + babel-plugin-transform-react-display-name "^6.23.0" + babel-plugin-transform-react-jsx "^6.24.1" + babel-plugin-transform-react-jsx-self "^6.22.0" + babel-plugin-transform-react-jsx-source "^6.22.0" + babel-preset-flow "^6.23.0" + +babel-register@^6.24.1, babel-register@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071" + dependencies: + babel-core "^6.26.0" + babel-runtime "^6.26.0" + core-js "^2.5.0" + home-or-tmp "^2.0.0" + lodash "^4.17.4" + mkdirp "^0.5.1" + source-map-support "^0.4.15" + +babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" + dependencies: + core-js "^2.4.0" + regenerator-runtime "^0.11.0" + +babel-template@^6.24.1, babel-template@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02" + dependencies: + babel-runtime "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + lodash "^4.17.4" + +babel-traverse@^6.24.1, babel-traverse@^6.25.0, babel-traverse@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee" + dependencies: + babel-code-frame "^6.26.0" + babel-messages "^6.23.0" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + debug "^2.6.8" + globals "^9.18.0" + invariant "^2.2.2" + lodash "^4.17.4" + +babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" + dependencies: + babel-runtime "^6.26.0" + esutils "^2.0.2" + lodash "^4.17.4" + to-fast-properties "^1.0.3" + +babylon@^6.17.4, babylon@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" + +balanced-match@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + +bcrypt-pbkdf@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz#63bc5dcb61331b92bc05fd528953c33462a06f8d" + dependencies: + tweetnacl "^0.14.3" + +body-parser@1.18.2: + version "1.18.2" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.18.2.tgz#87678a19d84b47d859b83199bd59bce222b10454" + dependencies: + bytes "3.0.0" + content-type "~1.0.4" + debug "2.6.9" + depd "~1.1.1" + http-errors "~1.6.2" + iconv-lite "0.4.19" + on-finished "~2.3.0" + qs "6.5.1" + raw-body "2.3.2" + type-is "~1.6.15" + +boom@4.x.x: + version "4.3.1" + resolved "https://registry.yarnpkg.com/boom/-/boom-4.3.1.tgz#4f8a3005cb4a7e3889f749030fd25b96e01d2e31" + dependencies: + hoek "4.x.x" + +boom@5.x.x: + version "5.2.0" + resolved "https://registry.yarnpkg.com/boom/-/boom-5.2.0.tgz#5dd9da6ee3a5f302077436290cb717d3f4a54e02" + dependencies: + hoek "4.x.x" + +brace-expansion@^1.1.7: + version "1.1.8" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292" + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +browserslist@^2.1.2: + version "2.11.3" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-2.11.3.tgz#fe36167aed1bbcde4827ebfe71347a2cc70b99b2" + dependencies: + caniuse-lite "^1.0.30000792" + electron-to-chromium "^1.3.30" + +bytes@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" + +caniuse-lite@^1.0.30000792: + version "1.0.30000792" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000792.tgz#d0cea981f8118f3961471afbb43c9a1e5bbf0332" + +caseless@~0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" + +chalk@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + dependencies: + ansi-styles "^2.2.1" + escape-string-regexp "^1.0.2" + has-ansi "^2.0.0" + strip-ansi "^3.0.0" + supports-color "^2.0.0" + +chalk@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.0.tgz#b5ea48efc9c1793dccc9b4767c93914d3f2d52ba" + dependencies: + ansi-styles "^3.1.0" + escape-string-regexp "^1.0.5" + supports-color "^4.0.0" + +classnames@^2.2.5: + version "2.2.5" + resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.5.tgz#fb3801d453467649ef3603c7d61a02bd129bde6d" + +co@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + +color-convert@^1.9.0, color-convert@^1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.1.tgz#c1261107aeb2f294ebffec9ed9ecad529a6097ed" + dependencies: + color-name "^1.1.1" + +color-name@^1.0.0, color-name@^1.1.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + +color-string@^1.5.2: + version "1.5.2" + resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.5.2.tgz#26e45814bc3c9a7cbd6751648a41434514a773a9" + dependencies: + color-name "^1.0.0" + simple-swizzle "^0.2.2" + +color@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color/-/color-2.0.1.tgz#e4ed78a3c4603d0891eba5430b04b86314f4c839" + dependencies: + color-convert "^1.9.1" + color-string "^1.5.2" + +combined-stream@^1.0.5, combined-stream@~1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009" + dependencies: + delayed-stream "~1.0.0" + +commander@^2.11.0: + version "2.13.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.13.0.tgz#6964bca67685df7c1f1430c584f07d7597885b9c" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + +content-disposition@0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4" + +content-type@~1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" + +convert-source-map@^1.5.0: + version "1.5.1" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.1.tgz#b8278097b9bc229365de5c62cf5fcaed8b5599e5" + +cookie-signature@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" + +cookie@0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb" + +core-js@^1.0.0: + version "1.2.7" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636" + +core-js@^2.4.0, core-js@^2.5.0: + version "2.5.3" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.3.tgz#8acc38345824f16d8365b7c9b4259168e8ed603e" + +core-util-is@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + +create-react-class@^15.6.0: + version "15.6.2" + resolved "https://registry.yarnpkg.com/create-react-class/-/create-react-class-15.6.2.tgz#cf1ed15f12aad7f14ef5f2dfe05e6c42f91ef02a" + dependencies: + fbjs "^0.8.9" + loose-envify "^1.3.1" + object-assign "^4.1.1" + +crowdin-cli@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/crowdin-cli/-/crowdin-cli-0.3.0.tgz#eac9989a6fe7feaaf33090397afc187c67b46191" + dependencies: + request "^2.53.0" + yamljs "^0.2.1" + yargs "^2.3.0" + +cryptiles@3.x.x: + version "3.1.2" + resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-3.1.2.tgz#a89fbb220f5ce25ec56e8c4aa8a4fd7b5b0d29fe" + dependencies: + boom "5.x.x" + +dashdash@^1.12.0: + version "1.14.1" + resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + dependencies: + assert-plus "^1.0.0" + +debug@0.7.4: + version "0.7.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-0.7.4.tgz#06e1ea8082c2cb14e39806e22e2f6f757f92af39" + +debug@2.6.9, debug@^2.6.8: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + dependencies: + ms "2.0.0" + +deep-is@0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.2.tgz#9ced65ea0bc0b09f42a6d79c1b1903f9d913cc18" + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + +depd@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.1.tgz#5783b4e1c459f06fa5ca27f991f3d06e7a310359" + +depd@~1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" + +destroy@~1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" + +detect-indent@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208" + dependencies: + repeating "^2.0.0" + +docusaurus@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/docusaurus/-/docusaurus-1.0.5.tgz#a2d75690e8dde50987a44cc836d6375b6130c8b7" + dependencies: + babel-preset-env "^1.6.0" + babel-preset-react "^6.24.1" + babel-register "^6.24.1" + babel-traverse "^6.25.0" + babylon "^6.17.4" + chalk "^2.1.0" + classnames "^2.2.5" + color "^2.0.1" + commander "^2.11.0" + crowdin-cli "^0.3.0" + escape-string-regexp "^1.0.5" + express "^4.15.3" + feed "^1.1.0" + fs-extra "^5.0.0" + glob "^7.1.2" + highlight.js "^9.12.0" + react "^15.5.4" + react-dom "^15.5.4" + react-dom-factories "^1.0.1" + remarkable "^1.7.1" + request "^2.81.0" + shelljs "^0.7.8" + sitemap "^1.13.0" + tcp-port-used "^0.1.2" + +ecc-jsbn@~0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505" + dependencies: + jsbn "~0.1.0" + +ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + +electron-to-chromium@^1.3.30: + version "1.3.31" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.31.tgz#00d832cba9fe2358652b0c48a8816c8e3a037e9f" + +encodeurl@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" + +encoding@^0.1.11: + version "0.1.12" + resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb" + dependencies: + iconv-lite "~0.4.13" + +escape-html@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + +escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + +esutils@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" + +etag@~1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" + +express@^4.15.3: + version "4.16.2" + resolved "https://registry.yarnpkg.com/express/-/express-4.16.2.tgz#e35c6dfe2d64b7dca0a5cd4f21781be3299e076c" + dependencies: + accepts "~1.3.4" + array-flatten "1.1.1" + body-parser "1.18.2" + content-disposition "0.5.2" + content-type "~1.0.4" + cookie "0.3.1" + cookie-signature "1.0.6" + debug "2.6.9" + depd "~1.1.1" + encodeurl "~1.0.1" + escape-html "~1.0.3" + etag "~1.8.1" + finalhandler "1.1.0" + fresh "0.5.2" + merge-descriptors "1.0.1" + methods "~1.1.2" + on-finished "~2.3.0" + parseurl "~1.3.2" + path-to-regexp "0.1.7" + proxy-addr "~2.0.2" + qs "6.5.1" + range-parser "~1.2.0" + safe-buffer "5.1.1" + send "0.16.1" + serve-static "1.13.1" + setprototypeof "1.1.0" + statuses "~1.3.1" + type-is "~1.6.15" + utils-merge "1.0.1" + vary "~1.1.2" + +extend@~3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444" + +extsprintf@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" + +extsprintf@^1.2.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" + +fast-deep-equal@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz#96256a3bc975595eb36d82e9929d060d893439ff" + +fast-json-stable-stringify@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" + +fbjs@^0.8.16, fbjs@^0.8.9: + version "0.8.16" + resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.16.tgz#5e67432f550dc41b572bf55847b8aca64e5337db" + dependencies: + core-js "^1.0.0" + isomorphic-fetch "^2.1.1" + loose-envify "^1.0.0" + object-assign "^4.1.0" + promise "^7.1.1" + setimmediate "^1.0.5" + ua-parser-js "^0.7.9" + +feed@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/feed/-/feed-1.1.1.tgz#914897517e94fa327cc6f73bb585a47c4a9ed321" + dependencies: + xml "^1.0.1" + +finalhandler@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.0.tgz#ce0b6855b45853e791b2fcc680046d88253dd7f5" + dependencies: + debug "2.6.9" + encodeurl "~1.0.1" + escape-html "~1.0.3" + on-finished "~2.3.0" + parseurl "~1.3.2" + statuses "~1.3.1" + unpipe "~1.0.0" + +forever-agent@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + +form-data@~2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.1.tgz#6fb94fbd71885306d73d15cc497fe4cc4ecd44bf" + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.5" + mime-types "^2.1.12" + +forwarded@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" + +fresh@0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" + +fs-extra@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-5.0.0.tgz#414d0110cdd06705734d055652c5411260c31abd" + dependencies: + graceful-fs "^4.1.2" + jsonfile "^4.0.0" + universalify "^0.1.0" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + +getpass@^0.1.1: + version "0.1.7" + resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" + dependencies: + assert-plus "^1.0.0" + +glob@^7.0.0, glob@^7.0.5, glob@^7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +globals@^9.18.0: + version "9.18.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" + +graceful-fs@^4.1.2, graceful-fs@^4.1.6: + version "4.1.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" + +har-schema@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" + +har-validator@~5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.0.3.tgz#ba402c266194f15956ef15e0fcf242993f6a7dfd" + dependencies: + ajv "^5.1.0" + har-schema "^2.0.0" + +has-ansi@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" + dependencies: + ansi-regex "^2.0.0" + +has-flag@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" + +hawk@~6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/hawk/-/hawk-6.0.2.tgz#af4d914eb065f9b5ce4d9d11c1cb2126eecc3038" + dependencies: + boom "4.x.x" + cryptiles "3.x.x" + hoek "4.x.x" + sntp "2.x.x" + +highlight.js@^9.12.0: + version "9.12.0" + resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.12.0.tgz#e6d9dbe57cbefe60751f02af336195870c90c01e" + +hoek@4.x.x: + version "4.2.0" + resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.2.0.tgz#72d9d0754f7fe25ca2d01ad8f8f9a9449a89526d" + +home-or-tmp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8" + dependencies: + os-homedir "^1.0.0" + os-tmpdir "^1.0.1" + +http-errors@1.6.2, http-errors@~1.6.2: + version "1.6.2" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.2.tgz#0a002cc85707192a7e7946ceedc11155f60ec736" + dependencies: + depd "1.1.1" + inherits "2.0.3" + setprototypeof "1.0.3" + statuses ">= 1.3.1 < 2" + +http-signature@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" + dependencies: + assert-plus "^1.0.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + +iconv-lite@0.4.19, iconv-lite@~0.4.13: + version "0.4.19" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b" + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + +interpret@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.1.0.tgz#7ed1b1410c6a0e0f78cf95d3b8440c63f78b8614" + +invariant@^2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.2.tgz#9e1f56ac0acdb6bf303306f338be3b204ae60360" + dependencies: + loose-envify "^1.0.0" + +ipaddr.js@1.5.2: + version "1.5.2" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.5.2.tgz#d4b505bde9946987ccf0fc58d9010ff9607e3fa0" + +is-arrayish@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.1.tgz#c2dfc386abaa0c3e33c48db3fe87059e69065efd" + +is-finite@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa" + dependencies: + number-is-nan "^1.0.0" + +is-stream@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" + +is-typedarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + +is2@0.0.9: + version "0.0.9" + resolved "https://registry.yarnpkg.com/is2/-/is2-0.0.9.tgz#119556d1d1651a41ba105af803267c80b299f629" + dependencies: + deep-is "0.1.2" + +isomorphic-fetch@^2.1.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9" + dependencies: + node-fetch "^1.0.1" + whatwg-fetch ">=0.10.0" + +isstream@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + +js-tokens@^3.0.0, js-tokens@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" + +jsbn@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + +jsesc@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" + +jsesc@~0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" + +json-schema-traverse@^0.3.0: + version "0.3.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" + +json-schema@0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" + +json-stringify-safe@~5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + +json5@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" + +jsonfile@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" + optionalDependencies: + graceful-fs "^4.1.6" + +jsprim@^1.2.2: + version "1.4.1" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" + dependencies: + assert-plus "1.0.0" + extsprintf "1.3.0" + json-schema "0.2.3" + verror "1.10.0" + +lodash@^4.17.4: + version "4.17.4" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" + +loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.3.1.tgz#d1a8ad33fa9ce0e713d65fdd0ac8b748d478c848" + dependencies: + js-tokens "^3.0.0" + +media-typer@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" + +merge-descriptors@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" + +methods@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" + +mime-db@~1.30.0: + version "1.30.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.30.0.tgz#74c643da2dd9d6a45399963465b26d5ca7d71f01" + +mime-types@^2.1.12, mime-types@~2.1.15, mime-types@~2.1.16, mime-types@~2.1.17: + version "2.1.17" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.17.tgz#09d7a393f03e995a79f8af857b70a9e0ab16557a" + dependencies: + mime-db "~1.30.0" + +mime@1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6" + +minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + dependencies: + brace-expansion "^1.1.7" + +minimist@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + +mkdirp@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" + dependencies: + minimist "0.0.8" + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + +negotiator@0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9" + +node-fetch@^1.0.1: + version "1.7.3" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef" + dependencies: + encoding "^0.1.11" + is-stream "^1.0.1" + +number-is-nan@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + +oauth-sign@~0.8.2: + version "0.8.2" + resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" + +object-assign@^4.1.0, object-assign@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + +on-finished@~2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" + dependencies: + ee-first "1.1.1" + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + dependencies: + wrappy "1" + +os-homedir@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" + +os-tmpdir@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + +parseurl@~1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.2.tgz#fc289d4ed8993119460c156253262cdc8de65bf3" + +path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + +path-parse@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1" + +path-to-regexp@0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" + +performance-now@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + +private@^0.1.6, private@^0.1.7: + version "0.1.8" + resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" + +promise@^7.1.1: + version "7.3.1" + resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf" + dependencies: + asap "~2.0.3" + +prop-types@^15.5.10: + version "15.6.0" + resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.0.tgz#ceaf083022fc46b4a35f69e13ef75aed0d639856" + dependencies: + fbjs "^0.8.16" + loose-envify "^1.3.1" + object-assign "^4.1.1" + +proxy-addr@~2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.2.tgz#6571504f47bb988ec8180253f85dd7e14952bdec" + dependencies: + forwarded "~0.1.2" + ipaddr.js "1.5.2" + +punycode@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + +q@0.9.7: + version "0.9.7" + resolved "https://registry.yarnpkg.com/q/-/q-0.9.7.tgz#4de2e6cb3b29088c9e4cbc03bf9d42fb96ce2f75" + +qs@6.5.1, qs@~6.5.1: + version "6.5.1" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8" + +range-parser@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" + +raw-body@2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.3.2.tgz#bcd60c77d3eb93cde0050295c3f379389bc88f89" + dependencies: + bytes "3.0.0" + http-errors "1.6.2" + iconv-lite "0.4.19" + unpipe "1.0.0" + +react-dom-factories@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/react-dom-factories/-/react-dom-factories-1.0.2.tgz#eb7705c4db36fb501b3aa38ff759616aa0ff96e0" + +react-dom@^15.5.4: + version "15.6.2" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-15.6.2.tgz#41cfadf693b757faf2708443a1d1fd5a02bef730" + dependencies: + fbjs "^0.8.9" + loose-envify "^1.1.0" + object-assign "^4.1.0" + prop-types "^15.5.10" + +react@^15.5.4: + version "15.6.2" + resolved "https://registry.yarnpkg.com/react/-/react-15.6.2.tgz#dba0434ab439cfe82f108f0f511663908179aa72" + dependencies: + create-react-class "^15.6.0" + fbjs "^0.8.9" + loose-envify "^1.1.0" + object-assign "^4.1.0" + prop-types "^15.5.10" + +rechoir@^0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" + dependencies: + resolve "^1.1.6" + +regenerate@^1.2.1: + version "1.3.3" + resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.3.3.tgz#0c336d3980553d755c39b586ae3b20aa49c82b7f" + +regenerator-runtime@^0.11.0: + version "0.11.1" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" + +regenerator-transform@^0.10.0: + version "0.10.1" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.10.1.tgz#1e4996837231da8b7f3cf4114d71b5691a0680dd" + dependencies: + babel-runtime "^6.18.0" + babel-types "^6.19.0" + private "^0.1.6" + +regexpu-core@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240" + dependencies: + regenerate "^1.2.1" + regjsgen "^0.2.0" + regjsparser "^0.1.4" + +regjsgen@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7" + +regjsparser@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.1.5.tgz#7ee8f84dc6fa792d3fd0ae228d24bd949ead205c" + dependencies: + jsesc "~0.5.0" + +remarkable@^1.7.1: + version "1.7.1" + resolved "https://registry.yarnpkg.com/remarkable/-/remarkable-1.7.1.tgz#aaca4972100b66a642a63a1021ca4bac1be3bff6" + dependencies: + argparse "~0.1.15" + autolinker "~0.15.0" + +repeating@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" + dependencies: + is-finite "^1.0.0" + +request@^2.53.0, request@^2.81.0: + version "2.83.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.83.0.tgz#ca0b65da02ed62935887808e6f510381034e3356" + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.6.0" + caseless "~0.12.0" + combined-stream "~1.0.5" + extend "~3.0.1" + forever-agent "~0.6.1" + form-data "~2.3.1" + har-validator "~5.0.3" + hawk "~6.0.2" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.17" + oauth-sign "~0.8.2" + performance-now "^2.1.0" + qs "~6.5.1" + safe-buffer "^5.1.1" + stringstream "~0.0.5" + tough-cookie "~2.3.3" + tunnel-agent "^0.6.0" + uuid "^3.1.0" + +resolve@^1.1.6: + version "1.5.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.5.0.tgz#1f09acce796c9a762579f31b2c1cc4c3cddf9f36" + dependencies: + path-parse "^1.0.5" + +safe-buffer@5.1.1, safe-buffer@^5.0.1, safe-buffer@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" + +semver@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" + +send@0.16.1: + version "0.16.1" + resolved "https://registry.yarnpkg.com/send/-/send-0.16.1.tgz#a70e1ca21d1382c11d0d9f6231deb281080d7ab3" + dependencies: + debug "2.6.9" + depd "~1.1.1" + destroy "~1.0.4" + encodeurl "~1.0.1" + escape-html "~1.0.3" + etag "~1.8.1" + fresh "0.5.2" + http-errors "~1.6.2" + mime "1.4.1" + ms "2.0.0" + on-finished "~2.3.0" + range-parser "~1.2.0" + statuses "~1.3.1" + +serve-static@1.13.1: + version "1.13.1" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.13.1.tgz#4c57d53404a761d8f2e7c1e8a18a47dbf278a719" + dependencies: + encodeurl "~1.0.1" + escape-html "~1.0.3" + parseurl "~1.3.2" + send "0.16.1" + +setimmediate@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" + +setprototypeof@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.0.3.tgz#66567e37043eeb4f04d91bd658c0cbefb55b8e04" + +setprototypeof@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" + +shelljs@^0.7.8: + version "0.7.8" + resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.8.tgz#decbcf874b0d1e5fb72e14b164a9683048e9acb3" + dependencies: + glob "^7.0.0" + interpret "^1.0.0" + rechoir "^0.6.2" + +simple-swizzle@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a" + dependencies: + is-arrayish "^0.3.1" + +sitemap@^1.13.0: + version "1.13.0" + resolved "https://registry.yarnpkg.com/sitemap/-/sitemap-1.13.0.tgz#569cbe2180202926a62a266cd3de09c9ceb43f83" + dependencies: + underscore "^1.7.0" + url-join "^1.1.0" + +slash@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" + +sntp@2.x.x: + version "2.1.0" + resolved "https://registry.yarnpkg.com/sntp/-/sntp-2.1.0.tgz#2c6cec14fedc2222739caf9b5c3d85d1cc5a2cc8" + dependencies: + hoek "4.x.x" + +source-map-support@^0.4.15: + version "0.4.18" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" + dependencies: + source-map "^0.5.6" + +source-map@^0.5.6: + version "0.5.7" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + +sshpk@^1.7.0: + version "1.13.1" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.13.1.tgz#512df6da6287144316dc4c18fe1cf1d940739be3" + dependencies: + asn1 "~0.2.3" + assert-plus "^1.0.0" + dashdash "^1.12.0" + getpass "^0.1.1" + optionalDependencies: + bcrypt-pbkdf "^1.0.0" + ecc-jsbn "~0.1.1" + jsbn "~0.1.0" + tweetnacl "~0.14.0" + +"statuses@>= 1.3.1 < 2": + version "1.4.0" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087" + +statuses@~1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.3.1.tgz#faf51b9eb74aaef3b3acf4ad5f61abf24cb7b93e" + +stringstream@~0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878" + +strip-ansi@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + dependencies: + ansi-regex "^2.0.0" + +supports-color@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" + +supports-color@^4.0.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.5.0.tgz#be7a0de484dec5c5cddf8b3d59125044912f635b" + dependencies: + has-flag "^2.0.0" + +tcp-port-used@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/tcp-port-used/-/tcp-port-used-0.1.2.tgz#9450e8768c83b416fd4d1a6a9449eeccbf496c29" + dependencies: + debug "0.7.4" + is2 "0.0.9" + q "0.9.7" + +to-fast-properties@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" + +tough-cookie@~2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.3.tgz#0b618a5565b6dea90bf3425d04d55edc475a7561" + dependencies: + punycode "^1.4.1" + +trim-right@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" + +tunnel-agent@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + dependencies: + safe-buffer "^5.0.1" + +tweetnacl@^0.14.3, tweetnacl@~0.14.0: + version "0.14.5" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + +type-is@~1.6.15: + version "1.6.15" + resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.15.tgz#cab10fb4909e441c82842eafe1ad646c81804410" + dependencies: + media-typer "0.3.0" + mime-types "~2.1.15" + +ua-parser-js@^0.7.9: + version "0.7.17" + resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.17.tgz#e9ec5f9498b9ec910e7ae3ac626a805c4d09ecac" + +underscore.string@~2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/underscore.string/-/underscore.string-2.4.0.tgz#8cdd8fbac4e2d2ea1e7e2e8097c42f442280f85b" + +underscore@^1.7.0: + version "1.8.3" + resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.8.3.tgz#4f3fb53b106e6097fcf9cb4109f2a5e9bdfa5022" + +underscore@~1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.7.0.tgz#6bbaf0877500d36be34ecaa584e0db9fef035209" + +universalify@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.1.tgz#fa71badd4437af4c148841e3b3b165f9e9e590b7" + +unpipe@1.0.0, unpipe@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + +url-join@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/url-join/-/url-join-1.1.0.tgz#741c6c2f4596c4830d6718460920d0c92202dc78" + +utils-merge@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" + +uuid@^3.1.0: + version "3.2.1" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.2.1.tgz#12c528bb9d58d0b9265d9a2f6f0fe8be17ff1f14" + +vary@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" + +verror@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" + dependencies: + assert-plus "^1.0.0" + core-util-is "1.0.2" + extsprintf "^1.2.0" + +whatwg-fetch@>=0.10.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.3.tgz#9c84ec2dcf68187ff00bc64e1274b442176e1c84" + +wordwrap@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + +xml@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/xml/-/xml-1.0.1.tgz#78ba72020029c5bc87b8a81a3cfcd74b4a2fc1e5" + +yamljs@^0.2.1: + version "0.2.10" + resolved "https://registry.yarnpkg.com/yamljs/-/yamljs-0.2.10.tgz#481cc7c25ca73af59f591f0c96e3ce56c757a40f" + dependencies: + argparse "^1.0.7" + glob "^7.0.5" + +yargs@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-2.3.0.tgz#e900c87250ec5cd080db6009fe3dd63156f1d7fb" + dependencies: + wordwrap "0.0.2" diff --git a/vendor/github.com/golang/protobuf/.gitignore b/vendor/github.com/golang/protobuf/.gitignore new file mode 100644 index 00000000..8f5b596b --- /dev/null +++ b/vendor/github.com/golang/protobuf/.gitignore @@ -0,0 +1,16 @@ +.DS_Store +*.[568ao] +*.ao +*.so +*.pyc +._* +.nfs.* +[568a].out +*~ +*.orig +core +_obj +_test +_testmain.go +protoc-gen-go/testdata/multi/*.pb.go +_conformance/_conformance diff --git a/vendor/github.com/golang/protobuf/.travis.yml b/vendor/github.com/golang/protobuf/.travis.yml new file mode 100644 index 00000000..93c67805 --- /dev/null +++ b/vendor/github.com/golang/protobuf/.travis.yml @@ -0,0 +1,18 @@ +sudo: false +language: go +go: +- 1.6.x +- 1.7.x +- 1.8.x +- 1.9.x + +install: + - go get -v -d -t github.com/golang/protobuf/... + - curl -L https://github.com/google/protobuf/releases/download/v3.3.0/protoc-3.3.0-linux-x86_64.zip -o /tmp/protoc.zip + - unzip /tmp/protoc.zip -d $HOME/protoc + +env: + - PATH=$HOME/protoc/bin:$PATH + +script: + - make all test diff --git a/vendor/github.com/golang/protobuf/AUTHORS b/vendor/github.com/golang/protobuf/AUTHORS new file mode 100644 index 00000000..15167cd7 --- /dev/null +++ b/vendor/github.com/golang/protobuf/AUTHORS @@ -0,0 +1,3 @@ +# This source code refers to The Go Authors for copyright purposes. +# The master list of authors is in the main Go distribution, +# visible at http://tip.golang.org/AUTHORS. diff --git a/vendor/github.com/golang/protobuf/CONTRIBUTORS b/vendor/github.com/golang/protobuf/CONTRIBUTORS new file mode 100644 index 00000000..1c4577e9 --- /dev/null +++ b/vendor/github.com/golang/protobuf/CONTRIBUTORS @@ -0,0 +1,3 @@ +# This source code was written by the Go contributors. +# The master list of contributors is in the main Go distribution, +# visible at http://tip.golang.org/CONTRIBUTORS. diff --git a/vendor/github.com/golang/protobuf/LICENSE b/vendor/github.com/golang/protobuf/LICENSE new file mode 100644 index 00000000..1b1b1921 --- /dev/null +++ b/vendor/github.com/golang/protobuf/LICENSE @@ -0,0 +1,31 @@ +Go support for Protocol Buffers - Google's data interchange format + +Copyright 2010 The Go Authors. All rights reserved. +https://github.com/golang/protobuf + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * 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. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +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 +OWNER 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/golang/protobuf/Make.protobuf b/vendor/github.com/golang/protobuf/Make.protobuf new file mode 100644 index 00000000..15071de1 --- /dev/null +++ b/vendor/github.com/golang/protobuf/Make.protobuf @@ -0,0 +1,40 @@ +# Go support for Protocol Buffers - Google's data interchange format +# +# Copyright 2010 The Go Authors. All rights reserved. +# https://github.com/golang/protobuf +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# 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 +# OWNER 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. + +# Includable Makefile to add a rule for generating .pb.go files from .proto files +# (Google protocol buffer descriptions). +# Typical use if myproto.proto is a file in package mypackage in this directory: +# +# include $(GOROOT)/src/pkg/github.com/golang/protobuf/Make.protobuf + +%.pb.go: %.proto + protoc --go_out=. $< + diff --git a/vendor/github.com/golang/protobuf/Makefile b/vendor/github.com/golang/protobuf/Makefile new file mode 100644 index 00000000..a1421d8b --- /dev/null +++ b/vendor/github.com/golang/protobuf/Makefile @@ -0,0 +1,55 @@ +# Go support for Protocol Buffers - Google's data interchange format +# +# Copyright 2010 The Go Authors. All rights reserved. +# https://github.com/golang/protobuf +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# 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 +# OWNER 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. + + +all: install + +install: + go install ./proto ./jsonpb ./ptypes + go install ./protoc-gen-go + +test: + go test ./proto ./jsonpb ./ptypes + make -C protoc-gen-go/testdata test + +clean: + go clean ./... + +nuke: + go clean -i ./... + +regenerate: + make -C protoc-gen-go/descriptor regenerate + make -C protoc-gen-go/plugin regenerate + make -C protoc-gen-go/testdata regenerate + make -C proto/testdata regenerate + make -C jsonpb/jsonpb_test_proto regenerate + make -C _conformance regenerate diff --git a/vendor/github.com/golang/protobuf/README.md b/vendor/github.com/golang/protobuf/README.md new file mode 100644 index 00000000..9c4c815c --- /dev/null +++ b/vendor/github.com/golang/protobuf/README.md @@ -0,0 +1,244 @@ +# Go support for Protocol Buffers + +[![Build Status](https://travis-ci.org/golang/protobuf.svg?branch=master)](https://travis-ci.org/golang/protobuf) +[![GoDoc](https://godoc.org/github.com/golang/protobuf?status.svg)](https://godoc.org/github.com/golang/protobuf) + +Google's data interchange format. +Copyright 2010 The Go Authors. +https://github.com/golang/protobuf + +This package and the code it generates requires at least Go 1.4. + +This software implements Go bindings for protocol buffers. For +information about protocol buffers themselves, see + https://developers.google.com/protocol-buffers/ + +## Installation ## + +To use this software, you must: +- Install the standard C++ implementation of protocol buffers from + https://developers.google.com/protocol-buffers/ +- Of course, install the Go compiler and tools from + https://golang.org/ + See + https://golang.org/doc/install + for details or, if you are using gccgo, follow the instructions at + https://golang.org/doc/install/gccgo +- Grab the code from the repository and install the proto package. + The simplest way is to run `go get -u github.com/golang/protobuf/protoc-gen-go`. + The compiler plugin, protoc-gen-go, will be installed in $GOBIN, + defaulting to $GOPATH/bin. It must be in your $PATH for the protocol + compiler, protoc, to find it. + +This software has two parts: a 'protocol compiler plugin' that +generates Go source files that, once compiled, can access and manage +protocol buffers; and a library that implements run-time support for +encoding (marshaling), decoding (unmarshaling), and accessing protocol +buffers. + +There is support for gRPC in Go using protocol buffers. +See the note at the bottom of this file for details. + +There are no insertion points in the plugin. + + +## Using protocol buffers with Go ## + +Once the software is installed, there are two steps to using it. +First you must compile the protocol buffer definitions and then import +them, with the support library, into your program. + +To compile the protocol buffer definition, run protoc with the --go_out +parameter set to the directory you want to output the Go code to. + + protoc --go_out=. *.proto + +The generated files will be suffixed .pb.go. See the Test code below +for an example using such a file. + + +The package comment for the proto library contains text describing +the interface provided in Go for protocol buffers. Here is an edited +version. + +========== + +The proto package converts data structures to and from the +wire format of protocol buffers. It works in concert with the +Go source code generated for .proto files by the protocol compiler. + +A summary of the properties of the protocol buffer interface +for a protocol buffer variable v: + + - Names are turned from camel_case to CamelCase for export. + - There are no methods on v to set fields; just treat + them as structure fields. + - There are getters that return a field's value if set, + and return the field's default value if unset. + The getters work even if the receiver is a nil message. + - The zero value for a struct is its correct initialization state. + All desired fields must be set before marshaling. + - A Reset() method will restore a protobuf struct to its zero state. + - Non-repeated fields are pointers to the values; nil means unset. + That is, optional or required field int32 f becomes F *int32. + - Repeated fields are slices. + - Helper functions are available to aid the setting of fields. + Helpers for getting values are superseded by the + GetFoo methods and their use is deprecated. + msg.Foo = proto.String("hello") // set field + - Constants are defined to hold the default values of all fields that + have them. They have the form Default_StructName_FieldName. + Because the getter methods handle defaulted values, + direct use of these constants should be rare. + - Enums are given type names and maps from names to values. + Enum values are prefixed with the enum's type name. Enum types have + a String method, and a Enum method to assist in message construction. + - Nested groups and enums have type names prefixed with the name of + the surrounding message type. + - Extensions are given descriptor names that start with E_, + followed by an underscore-delimited list of the nested messages + that contain it (if any) followed by the CamelCased name of the + extension field itself. HasExtension, ClearExtension, GetExtension + and SetExtension are functions for manipulating extensions. + - Oneof field sets are given a single field in their message, + with distinguished wrapper types for each possible field value. + - Marshal and Unmarshal are functions to encode and decode the wire format. + +When the .proto file specifies `syntax="proto3"`, there are some differences: + + - Non-repeated fields of non-message type are values instead of pointers. + - Enum types do not get an Enum method. + +Consider file test.proto, containing + +```proto + syntax = "proto2"; + package example; + + enum FOO { X = 17; }; + + message Test { + required string label = 1; + optional int32 type = 2 [default=77]; + repeated int64 reps = 3; + optional group OptionalGroup = 4 { + required string RequiredField = 5; + } + } +``` + +To create and play with a Test object from the example package, + +```go + package main + + import ( + "log" + + "github.com/golang/protobuf/proto" + "path/to/example" + ) + + func main() { + test := &example.Test { + Label: proto.String("hello"), + Type: proto.Int32(17), + Reps: []int64{1, 2, 3}, + Optionalgroup: &example.Test_OptionalGroup { + RequiredField: proto.String("good bye"), + }, + } + data, err := proto.Marshal(test) + if err != nil { + log.Fatal("marshaling error: ", err) + } + newTest := &example.Test{} + err = proto.Unmarshal(data, newTest) + if err != nil { + log.Fatal("unmarshaling error: ", err) + } + // Now test and newTest contain the same data. + if test.GetLabel() != newTest.GetLabel() { + log.Fatalf("data mismatch %q != %q", test.GetLabel(), newTest.GetLabel()) + } + // etc. + } +``` + +## Parameters ## + +To pass extra parameters to the plugin, use a comma-separated +parameter list separated from the output directory by a colon: + + + protoc --go_out=plugins=grpc,import_path=mypackage:. *.proto + + +- `import_prefix=xxx` - a prefix that is added onto the beginning of + all imports. Useful for things like generating protos in a + subdirectory, or regenerating vendored protobufs in-place. +- `import_path=foo/bar` - used as the package if no input files + declare `go_package`. If it contains slashes, everything up to the + rightmost slash is ignored. +- `plugins=plugin1+plugin2` - specifies the list of sub-plugins to + load. The only plugin in this repo is `grpc`. +- `Mfoo/bar.proto=quux/shme` - declares that foo/bar.proto is + associated with Go package quux/shme. This is subject to the + import_prefix parameter. + +## gRPC Support ## + +If a proto file specifies RPC services, protoc-gen-go can be instructed to +generate code compatible with gRPC (http://www.grpc.io/). To do this, pass +the `plugins` parameter to protoc-gen-go; the usual way is to insert it into +the --go_out argument to protoc: + + protoc --go_out=plugins=grpc:. *.proto + +## Compatibility ## + +The library and the generated code are expected to be stable over time. +However, we reserve the right to make breaking changes without notice for the +following reasons: + +- Security. A security issue in the specification or implementation may come to + light whose resolution requires breaking compatibility. We reserve the right + to address such security issues. +- Unspecified behavior. There are some aspects of the Protocol Buffers + specification that are undefined. Programs that depend on such unspecified + behavior may break in future releases. +- Specification errors or changes. If it becomes necessary to address an + inconsistency, incompleteness, or change in the Protocol Buffers + specification, resolving the issue could affect the meaning or legality of + existing programs. We reserve the right to address such issues, including + updating the implementations. +- Bugs. If the library has a bug that violates the specification, a program + that depends on the buggy behavior may break if the bug is fixed. We reserve + the right to fix such bugs. +- Adding methods or fields to generated structs. These may conflict with field + names that already exist in a schema, causing applications to break. When the + code generator encounters a field in the schema that would collide with a + generated field or method name, the code generator will append an underscore + to the generated field or method name. +- Adding, removing, or changing methods or fields in generated structs that + start with `XXX`. These parts of the generated code are exported out of + necessity, but should not be considered part of the public API. +- Adding, removing, or changing unexported symbols in generated code. + +Any breaking changes outside of these will be announced 6 months in advance to +protobuf@googlegroups.com. + +You should, whenever possible, use generated code created by the `protoc-gen-go` +tool built at the same commit as the `proto` package. The `proto` package +declares package-level constants in the form `ProtoPackageIsVersionX`. +Application code and generated code may depend on one of these constants to +ensure that compilation will fail if the available version of the proto library +is too old. Whenever we make a change to the generated code that requires newer +library support, in the same commit we will increment the version number of the +generated code and declare a new package-level constant whose name incorporates +the latest version number. Removing a compatibility constant is considered a +breaking change and would be subject to the announcement policy stated above. + +The `protoc-gen-go/generator` package exposes a plugin interface, +which is used by the gRPC code generation. This interface is not +supported and is subject to incompatible changes without notice. diff --git a/vendor/github.com/golang/protobuf/_conformance/Makefile b/vendor/github.com/golang/protobuf/_conformance/Makefile new file mode 100644 index 00000000..89800e2d --- /dev/null +++ b/vendor/github.com/golang/protobuf/_conformance/Makefile @@ -0,0 +1,33 @@ +# Go support for Protocol Buffers - Google's data interchange format +# +# Copyright 2016 The Go Authors. All rights reserved. +# https://github.com/golang/protobuf +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# 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 +# OWNER 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. + +regenerate: + protoc --go_out=Mgoogle/protobuf/any.proto=github.com/golang/protobuf/ptypes/any,Mgoogle/protobuf/duration.proto=github.com/golang/protobuf/ptypes/duration,Mgoogle/protobuf/struct.proto=github.com/golang/protobuf/ptypes/struct,Mgoogle/protobuf/timestamp.proto=github.com/golang/protobuf/ptypes/timestamp,Mgoogle/protobuf/wrappers.proto=github.com/golang/protobuf/ptypes/wrappers,Mgoogle/protobuf/field_mask.proto=google.golang.org/genproto/protobuf:. conformance_proto/conformance.proto diff --git a/vendor/github.com/golang/protobuf/_conformance/conformance.go b/vendor/github.com/golang/protobuf/_conformance/conformance.go new file mode 100644 index 00000000..c54212c8 --- /dev/null +++ b/vendor/github.com/golang/protobuf/_conformance/conformance.go @@ -0,0 +1,161 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2016 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// 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 +// OWNER 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. + +// conformance implements the conformance test subprocess protocol as +// documented in conformance.proto. +package main + +import ( + "encoding/binary" + "fmt" + "io" + "os" + + pb "github.com/golang/protobuf/_conformance/conformance_proto" + "github.com/golang/protobuf/jsonpb" + "github.com/golang/protobuf/proto" +) + +func main() { + var sizeBuf [4]byte + inbuf := make([]byte, 0, 4096) + outbuf := proto.NewBuffer(nil) + for { + if _, err := io.ReadFull(os.Stdin, sizeBuf[:]); err == io.EOF { + break + } else if err != nil { + fmt.Fprintln(os.Stderr, "go conformance: read request:", err) + os.Exit(1) + } + size := binary.LittleEndian.Uint32(sizeBuf[:]) + if int(size) > cap(inbuf) { + inbuf = make([]byte, size) + } + inbuf = inbuf[:size] + if _, err := io.ReadFull(os.Stdin, inbuf); err != nil { + fmt.Fprintln(os.Stderr, "go conformance: read request:", err) + os.Exit(1) + } + + req := new(pb.ConformanceRequest) + if err := proto.Unmarshal(inbuf, req); err != nil { + fmt.Fprintln(os.Stderr, "go conformance: parse request:", err) + os.Exit(1) + } + res := handle(req) + + if err := outbuf.Marshal(res); err != nil { + fmt.Fprintln(os.Stderr, "go conformance: marshal response:", err) + os.Exit(1) + } + binary.LittleEndian.PutUint32(sizeBuf[:], uint32(len(outbuf.Bytes()))) + if _, err := os.Stdout.Write(sizeBuf[:]); err != nil { + fmt.Fprintln(os.Stderr, "go conformance: write response:", err) + os.Exit(1) + } + if _, err := os.Stdout.Write(outbuf.Bytes()); err != nil { + fmt.Fprintln(os.Stderr, "go conformance: write response:", err) + os.Exit(1) + } + outbuf.Reset() + } +} + +var jsonMarshaler = jsonpb.Marshaler{ + OrigName: true, +} + +func handle(req *pb.ConformanceRequest) *pb.ConformanceResponse { + var err error + var msg pb.TestAllTypes + switch p := req.Payload.(type) { + case *pb.ConformanceRequest_ProtobufPayload: + err = proto.Unmarshal(p.ProtobufPayload, &msg) + case *pb.ConformanceRequest_JsonPayload: + err = jsonpb.UnmarshalString(p.JsonPayload, &msg) + if err != nil && err.Error() == "unmarshaling Any not supported yet" { + return &pb.ConformanceResponse{ + Result: &pb.ConformanceResponse_Skipped{ + Skipped: err.Error(), + }, + } + } + default: + return &pb.ConformanceResponse{ + Result: &pb.ConformanceResponse_RuntimeError{ + RuntimeError: "unknown request payload type", + }, + } + } + if err != nil { + return &pb.ConformanceResponse{ + Result: &pb.ConformanceResponse_ParseError{ + ParseError: err.Error(), + }, + } + } + switch req.RequestedOutputFormat { + case pb.WireFormat_PROTOBUF: + p, err := proto.Marshal(&msg) + if err != nil { + return &pb.ConformanceResponse{ + Result: &pb.ConformanceResponse_SerializeError{ + SerializeError: err.Error(), + }, + } + } + return &pb.ConformanceResponse{ + Result: &pb.ConformanceResponse_ProtobufPayload{ + ProtobufPayload: p, + }, + } + case pb.WireFormat_JSON: + p, err := jsonMarshaler.MarshalToString(&msg) + if err != nil { + return &pb.ConformanceResponse{ + Result: &pb.ConformanceResponse_SerializeError{ + SerializeError: err.Error(), + }, + } + } + return &pb.ConformanceResponse{ + Result: &pb.ConformanceResponse_JsonPayload{ + JsonPayload: p, + }, + } + default: + return &pb.ConformanceResponse{ + Result: &pb.ConformanceResponse_RuntimeError{ + RuntimeError: "unknown output format", + }, + } + } +} diff --git a/vendor/github.com/golang/protobuf/_conformance/conformance_proto/conformance.pb.go b/vendor/github.com/golang/protobuf/_conformance/conformance_proto/conformance.pb.go new file mode 100644 index 00000000..ec354ead --- /dev/null +++ b/vendor/github.com/golang/protobuf/_conformance/conformance_proto/conformance.pb.go @@ -0,0 +1,1885 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: conformance_proto/conformance.proto + +/* +Package conformance is a generated protocol buffer package. + +It is generated from these files: + conformance_proto/conformance.proto + +It has these top-level messages: + ConformanceRequest + ConformanceResponse + TestAllTypes + ForeignMessage +*/ +package conformance + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" +import google_protobuf "github.com/golang/protobuf/ptypes/any" +import google_protobuf1 "github.com/golang/protobuf/ptypes/duration" +import google_protobuf2 "google.golang.org/genproto/protobuf" +import google_protobuf3 "github.com/golang/protobuf/ptypes/struct" +import google_protobuf4 "github.com/golang/protobuf/ptypes/timestamp" +import google_protobuf5 "github.com/golang/protobuf/ptypes/wrappers" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package + +type WireFormat int32 + +const ( + WireFormat_UNSPECIFIED WireFormat = 0 + WireFormat_PROTOBUF WireFormat = 1 + WireFormat_JSON WireFormat = 2 +) + +var WireFormat_name = map[int32]string{ + 0: "UNSPECIFIED", + 1: "PROTOBUF", + 2: "JSON", +} +var WireFormat_value = map[string]int32{ + "UNSPECIFIED": 0, + "PROTOBUF": 1, + "JSON": 2, +} + +func (x WireFormat) String() string { + return proto.EnumName(WireFormat_name, int32(x)) +} +func (WireFormat) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } + +type ForeignEnum int32 + +const ( + ForeignEnum_FOREIGN_FOO ForeignEnum = 0 + ForeignEnum_FOREIGN_BAR ForeignEnum = 1 + ForeignEnum_FOREIGN_BAZ ForeignEnum = 2 +) + +var ForeignEnum_name = map[int32]string{ + 0: "FOREIGN_FOO", + 1: "FOREIGN_BAR", + 2: "FOREIGN_BAZ", +} +var ForeignEnum_value = map[string]int32{ + "FOREIGN_FOO": 0, + "FOREIGN_BAR": 1, + "FOREIGN_BAZ": 2, +} + +func (x ForeignEnum) String() string { + return proto.EnumName(ForeignEnum_name, int32(x)) +} +func (ForeignEnum) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } + +type TestAllTypes_NestedEnum int32 + +const ( + TestAllTypes_FOO TestAllTypes_NestedEnum = 0 + TestAllTypes_BAR TestAllTypes_NestedEnum = 1 + TestAllTypes_BAZ TestAllTypes_NestedEnum = 2 + TestAllTypes_NEG TestAllTypes_NestedEnum = -1 +) + +var TestAllTypes_NestedEnum_name = map[int32]string{ + 0: "FOO", + 1: "BAR", + 2: "BAZ", + -1: "NEG", +} +var TestAllTypes_NestedEnum_value = map[string]int32{ + "FOO": 0, + "BAR": 1, + "BAZ": 2, + "NEG": -1, +} + +func (x TestAllTypes_NestedEnum) String() string { + return proto.EnumName(TestAllTypes_NestedEnum_name, int32(x)) +} +func (TestAllTypes_NestedEnum) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{2, 0} } + +// Represents a single test case's input. The testee should: +// +// 1. parse this proto (which should always succeed) +// 2. parse the protobuf or JSON payload in "payload" (which may fail) +// 3. if the parse succeeded, serialize the message in the requested format. +type ConformanceRequest struct { + // The payload (whether protobuf of JSON) is always for a TestAllTypes proto + // (see below). + // + // Types that are valid to be assigned to Payload: + // *ConformanceRequest_ProtobufPayload + // *ConformanceRequest_JsonPayload + Payload isConformanceRequest_Payload `protobuf_oneof:"payload"` + // Which format should the testee serialize its message to? + RequestedOutputFormat WireFormat `protobuf:"varint,3,opt,name=requested_output_format,json=requestedOutputFormat,enum=conformance.WireFormat" json:"requested_output_format,omitempty"` +} + +func (m *ConformanceRequest) Reset() { *m = ConformanceRequest{} } +func (m *ConformanceRequest) String() string { return proto.CompactTextString(m) } +func (*ConformanceRequest) ProtoMessage() {} +func (*ConformanceRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } + +type isConformanceRequest_Payload interface { + isConformanceRequest_Payload() +} + +type ConformanceRequest_ProtobufPayload struct { + ProtobufPayload []byte `protobuf:"bytes,1,opt,name=protobuf_payload,json=protobufPayload,proto3,oneof"` +} +type ConformanceRequest_JsonPayload struct { + JsonPayload string `protobuf:"bytes,2,opt,name=json_payload,json=jsonPayload,oneof"` +} + +func (*ConformanceRequest_ProtobufPayload) isConformanceRequest_Payload() {} +func (*ConformanceRequest_JsonPayload) isConformanceRequest_Payload() {} + +func (m *ConformanceRequest) GetPayload() isConformanceRequest_Payload { + if m != nil { + return m.Payload + } + return nil +} + +func (m *ConformanceRequest) GetProtobufPayload() []byte { + if x, ok := m.GetPayload().(*ConformanceRequest_ProtobufPayload); ok { + return x.ProtobufPayload + } + return nil +} + +func (m *ConformanceRequest) GetJsonPayload() string { + if x, ok := m.GetPayload().(*ConformanceRequest_JsonPayload); ok { + return x.JsonPayload + } + return "" +} + +func (m *ConformanceRequest) GetRequestedOutputFormat() WireFormat { + if m != nil { + return m.RequestedOutputFormat + } + return WireFormat_UNSPECIFIED +} + +// XXX_OneofFuncs is for the internal use of the proto package. +func (*ConformanceRequest) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { + return _ConformanceRequest_OneofMarshaler, _ConformanceRequest_OneofUnmarshaler, _ConformanceRequest_OneofSizer, []interface{}{ + (*ConformanceRequest_ProtobufPayload)(nil), + (*ConformanceRequest_JsonPayload)(nil), + } +} + +func _ConformanceRequest_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { + m := msg.(*ConformanceRequest) + // payload + switch x := m.Payload.(type) { + case *ConformanceRequest_ProtobufPayload: + b.EncodeVarint(1<<3 | proto.WireBytes) + b.EncodeRawBytes(x.ProtobufPayload) + case *ConformanceRequest_JsonPayload: + b.EncodeVarint(2<<3 | proto.WireBytes) + b.EncodeStringBytes(x.JsonPayload) + case nil: + default: + return fmt.Errorf("ConformanceRequest.Payload has unexpected type %T", x) + } + return nil +} + +func _ConformanceRequest_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { + m := msg.(*ConformanceRequest) + switch tag { + case 1: // payload.protobuf_payload + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeRawBytes(true) + m.Payload = &ConformanceRequest_ProtobufPayload{x} + return true, err + case 2: // payload.json_payload + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeStringBytes() + m.Payload = &ConformanceRequest_JsonPayload{x} + return true, err + default: + return false, nil + } +} + +func _ConformanceRequest_OneofSizer(msg proto.Message) (n int) { + m := msg.(*ConformanceRequest) + // payload + switch x := m.Payload.(type) { + case *ConformanceRequest_ProtobufPayload: + n += proto.SizeVarint(1<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(len(x.ProtobufPayload))) + n += len(x.ProtobufPayload) + case *ConformanceRequest_JsonPayload: + n += proto.SizeVarint(2<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(len(x.JsonPayload))) + n += len(x.JsonPayload) + case nil: + default: + panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) + } + return n +} + +// Represents a single test case's output. +type ConformanceResponse struct { + // Types that are valid to be assigned to Result: + // *ConformanceResponse_ParseError + // *ConformanceResponse_SerializeError + // *ConformanceResponse_RuntimeError + // *ConformanceResponse_ProtobufPayload + // *ConformanceResponse_JsonPayload + // *ConformanceResponse_Skipped + Result isConformanceResponse_Result `protobuf_oneof:"result"` +} + +func (m *ConformanceResponse) Reset() { *m = ConformanceResponse{} } +func (m *ConformanceResponse) String() string { return proto.CompactTextString(m) } +func (*ConformanceResponse) ProtoMessage() {} +func (*ConformanceResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } + +type isConformanceResponse_Result interface { + isConformanceResponse_Result() +} + +type ConformanceResponse_ParseError struct { + ParseError string `protobuf:"bytes,1,opt,name=parse_error,json=parseError,oneof"` +} +type ConformanceResponse_SerializeError struct { + SerializeError string `protobuf:"bytes,6,opt,name=serialize_error,json=serializeError,oneof"` +} +type ConformanceResponse_RuntimeError struct { + RuntimeError string `protobuf:"bytes,2,opt,name=runtime_error,json=runtimeError,oneof"` +} +type ConformanceResponse_ProtobufPayload struct { + ProtobufPayload []byte `protobuf:"bytes,3,opt,name=protobuf_payload,json=protobufPayload,proto3,oneof"` +} +type ConformanceResponse_JsonPayload struct { + JsonPayload string `protobuf:"bytes,4,opt,name=json_payload,json=jsonPayload,oneof"` +} +type ConformanceResponse_Skipped struct { + Skipped string `protobuf:"bytes,5,opt,name=skipped,oneof"` +} + +func (*ConformanceResponse_ParseError) isConformanceResponse_Result() {} +func (*ConformanceResponse_SerializeError) isConformanceResponse_Result() {} +func (*ConformanceResponse_RuntimeError) isConformanceResponse_Result() {} +func (*ConformanceResponse_ProtobufPayload) isConformanceResponse_Result() {} +func (*ConformanceResponse_JsonPayload) isConformanceResponse_Result() {} +func (*ConformanceResponse_Skipped) isConformanceResponse_Result() {} + +func (m *ConformanceResponse) GetResult() isConformanceResponse_Result { + if m != nil { + return m.Result + } + return nil +} + +func (m *ConformanceResponse) GetParseError() string { + if x, ok := m.GetResult().(*ConformanceResponse_ParseError); ok { + return x.ParseError + } + return "" +} + +func (m *ConformanceResponse) GetSerializeError() string { + if x, ok := m.GetResult().(*ConformanceResponse_SerializeError); ok { + return x.SerializeError + } + return "" +} + +func (m *ConformanceResponse) GetRuntimeError() string { + if x, ok := m.GetResult().(*ConformanceResponse_RuntimeError); ok { + return x.RuntimeError + } + return "" +} + +func (m *ConformanceResponse) GetProtobufPayload() []byte { + if x, ok := m.GetResult().(*ConformanceResponse_ProtobufPayload); ok { + return x.ProtobufPayload + } + return nil +} + +func (m *ConformanceResponse) GetJsonPayload() string { + if x, ok := m.GetResult().(*ConformanceResponse_JsonPayload); ok { + return x.JsonPayload + } + return "" +} + +func (m *ConformanceResponse) GetSkipped() string { + if x, ok := m.GetResult().(*ConformanceResponse_Skipped); ok { + return x.Skipped + } + return "" +} + +// XXX_OneofFuncs is for the internal use of the proto package. +func (*ConformanceResponse) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { + return _ConformanceResponse_OneofMarshaler, _ConformanceResponse_OneofUnmarshaler, _ConformanceResponse_OneofSizer, []interface{}{ + (*ConformanceResponse_ParseError)(nil), + (*ConformanceResponse_SerializeError)(nil), + (*ConformanceResponse_RuntimeError)(nil), + (*ConformanceResponse_ProtobufPayload)(nil), + (*ConformanceResponse_JsonPayload)(nil), + (*ConformanceResponse_Skipped)(nil), + } +} + +func _ConformanceResponse_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { + m := msg.(*ConformanceResponse) + // result + switch x := m.Result.(type) { + case *ConformanceResponse_ParseError: + b.EncodeVarint(1<<3 | proto.WireBytes) + b.EncodeStringBytes(x.ParseError) + case *ConformanceResponse_SerializeError: + b.EncodeVarint(6<<3 | proto.WireBytes) + b.EncodeStringBytes(x.SerializeError) + case *ConformanceResponse_RuntimeError: + b.EncodeVarint(2<<3 | proto.WireBytes) + b.EncodeStringBytes(x.RuntimeError) + case *ConformanceResponse_ProtobufPayload: + b.EncodeVarint(3<<3 | proto.WireBytes) + b.EncodeRawBytes(x.ProtobufPayload) + case *ConformanceResponse_JsonPayload: + b.EncodeVarint(4<<3 | proto.WireBytes) + b.EncodeStringBytes(x.JsonPayload) + case *ConformanceResponse_Skipped: + b.EncodeVarint(5<<3 | proto.WireBytes) + b.EncodeStringBytes(x.Skipped) + case nil: + default: + return fmt.Errorf("ConformanceResponse.Result has unexpected type %T", x) + } + return nil +} + +func _ConformanceResponse_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { + m := msg.(*ConformanceResponse) + switch tag { + case 1: // result.parse_error + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeStringBytes() + m.Result = &ConformanceResponse_ParseError{x} + return true, err + case 6: // result.serialize_error + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeStringBytes() + m.Result = &ConformanceResponse_SerializeError{x} + return true, err + case 2: // result.runtime_error + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeStringBytes() + m.Result = &ConformanceResponse_RuntimeError{x} + return true, err + case 3: // result.protobuf_payload + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeRawBytes(true) + m.Result = &ConformanceResponse_ProtobufPayload{x} + return true, err + case 4: // result.json_payload + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeStringBytes() + m.Result = &ConformanceResponse_JsonPayload{x} + return true, err + case 5: // result.skipped + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeStringBytes() + m.Result = &ConformanceResponse_Skipped{x} + return true, err + default: + return false, nil + } +} + +func _ConformanceResponse_OneofSizer(msg proto.Message) (n int) { + m := msg.(*ConformanceResponse) + // result + switch x := m.Result.(type) { + case *ConformanceResponse_ParseError: + n += proto.SizeVarint(1<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(len(x.ParseError))) + n += len(x.ParseError) + case *ConformanceResponse_SerializeError: + n += proto.SizeVarint(6<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(len(x.SerializeError))) + n += len(x.SerializeError) + case *ConformanceResponse_RuntimeError: + n += proto.SizeVarint(2<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(len(x.RuntimeError))) + n += len(x.RuntimeError) + case *ConformanceResponse_ProtobufPayload: + n += proto.SizeVarint(3<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(len(x.ProtobufPayload))) + n += len(x.ProtobufPayload) + case *ConformanceResponse_JsonPayload: + n += proto.SizeVarint(4<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(len(x.JsonPayload))) + n += len(x.JsonPayload) + case *ConformanceResponse_Skipped: + n += proto.SizeVarint(5<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(len(x.Skipped))) + n += len(x.Skipped) + case nil: + default: + panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) + } + return n +} + +// This proto includes every type of field in both singular and repeated +// forms. +type TestAllTypes struct { + // Singular + OptionalInt32 int32 `protobuf:"varint,1,opt,name=optional_int32,json=optionalInt32" json:"optional_int32,omitempty"` + OptionalInt64 int64 `protobuf:"varint,2,opt,name=optional_int64,json=optionalInt64" json:"optional_int64,omitempty"` + OptionalUint32 uint32 `protobuf:"varint,3,opt,name=optional_uint32,json=optionalUint32" json:"optional_uint32,omitempty"` + OptionalUint64 uint64 `protobuf:"varint,4,opt,name=optional_uint64,json=optionalUint64" json:"optional_uint64,omitempty"` + OptionalSint32 int32 `protobuf:"zigzag32,5,opt,name=optional_sint32,json=optionalSint32" json:"optional_sint32,omitempty"` + OptionalSint64 int64 `protobuf:"zigzag64,6,opt,name=optional_sint64,json=optionalSint64" json:"optional_sint64,omitempty"` + OptionalFixed32 uint32 `protobuf:"fixed32,7,opt,name=optional_fixed32,json=optionalFixed32" json:"optional_fixed32,omitempty"` + OptionalFixed64 uint64 `protobuf:"fixed64,8,opt,name=optional_fixed64,json=optionalFixed64" json:"optional_fixed64,omitempty"` + OptionalSfixed32 int32 `protobuf:"fixed32,9,opt,name=optional_sfixed32,json=optionalSfixed32" json:"optional_sfixed32,omitempty"` + OptionalSfixed64 int64 `protobuf:"fixed64,10,opt,name=optional_sfixed64,json=optionalSfixed64" json:"optional_sfixed64,omitempty"` + OptionalFloat float32 `protobuf:"fixed32,11,opt,name=optional_float,json=optionalFloat" json:"optional_float,omitempty"` + OptionalDouble float64 `protobuf:"fixed64,12,opt,name=optional_double,json=optionalDouble" json:"optional_double,omitempty"` + OptionalBool bool `protobuf:"varint,13,opt,name=optional_bool,json=optionalBool" json:"optional_bool,omitempty"` + OptionalString string `protobuf:"bytes,14,opt,name=optional_string,json=optionalString" json:"optional_string,omitempty"` + OptionalBytes []byte `protobuf:"bytes,15,opt,name=optional_bytes,json=optionalBytes,proto3" json:"optional_bytes,omitempty"` + OptionalNestedMessage *TestAllTypes_NestedMessage `protobuf:"bytes,18,opt,name=optional_nested_message,json=optionalNestedMessage" json:"optional_nested_message,omitempty"` + OptionalForeignMessage *ForeignMessage `protobuf:"bytes,19,opt,name=optional_foreign_message,json=optionalForeignMessage" json:"optional_foreign_message,omitempty"` + OptionalNestedEnum TestAllTypes_NestedEnum `protobuf:"varint,21,opt,name=optional_nested_enum,json=optionalNestedEnum,enum=conformance.TestAllTypes_NestedEnum" json:"optional_nested_enum,omitempty"` + OptionalForeignEnum ForeignEnum `protobuf:"varint,22,opt,name=optional_foreign_enum,json=optionalForeignEnum,enum=conformance.ForeignEnum" json:"optional_foreign_enum,omitempty"` + OptionalStringPiece string `protobuf:"bytes,24,opt,name=optional_string_piece,json=optionalStringPiece" json:"optional_string_piece,omitempty"` + OptionalCord string `protobuf:"bytes,25,opt,name=optional_cord,json=optionalCord" json:"optional_cord,omitempty"` + RecursiveMessage *TestAllTypes `protobuf:"bytes,27,opt,name=recursive_message,json=recursiveMessage" json:"recursive_message,omitempty"` + // Repeated + RepeatedInt32 []int32 `protobuf:"varint,31,rep,packed,name=repeated_int32,json=repeatedInt32" json:"repeated_int32,omitempty"` + RepeatedInt64 []int64 `protobuf:"varint,32,rep,packed,name=repeated_int64,json=repeatedInt64" json:"repeated_int64,omitempty"` + RepeatedUint32 []uint32 `protobuf:"varint,33,rep,packed,name=repeated_uint32,json=repeatedUint32" json:"repeated_uint32,omitempty"` + RepeatedUint64 []uint64 `protobuf:"varint,34,rep,packed,name=repeated_uint64,json=repeatedUint64" json:"repeated_uint64,omitempty"` + RepeatedSint32 []int32 `protobuf:"zigzag32,35,rep,packed,name=repeated_sint32,json=repeatedSint32" json:"repeated_sint32,omitempty"` + RepeatedSint64 []int64 `protobuf:"zigzag64,36,rep,packed,name=repeated_sint64,json=repeatedSint64" json:"repeated_sint64,omitempty"` + RepeatedFixed32 []uint32 `protobuf:"fixed32,37,rep,packed,name=repeated_fixed32,json=repeatedFixed32" json:"repeated_fixed32,omitempty"` + RepeatedFixed64 []uint64 `protobuf:"fixed64,38,rep,packed,name=repeated_fixed64,json=repeatedFixed64" json:"repeated_fixed64,omitempty"` + RepeatedSfixed32 []int32 `protobuf:"fixed32,39,rep,packed,name=repeated_sfixed32,json=repeatedSfixed32" json:"repeated_sfixed32,omitempty"` + RepeatedSfixed64 []int64 `protobuf:"fixed64,40,rep,packed,name=repeated_sfixed64,json=repeatedSfixed64" json:"repeated_sfixed64,omitempty"` + RepeatedFloat []float32 `protobuf:"fixed32,41,rep,packed,name=repeated_float,json=repeatedFloat" json:"repeated_float,omitempty"` + RepeatedDouble []float64 `protobuf:"fixed64,42,rep,packed,name=repeated_double,json=repeatedDouble" json:"repeated_double,omitempty"` + RepeatedBool []bool `protobuf:"varint,43,rep,packed,name=repeated_bool,json=repeatedBool" json:"repeated_bool,omitempty"` + RepeatedString []string `protobuf:"bytes,44,rep,name=repeated_string,json=repeatedString" json:"repeated_string,omitempty"` + RepeatedBytes [][]byte `protobuf:"bytes,45,rep,name=repeated_bytes,json=repeatedBytes,proto3" json:"repeated_bytes,omitempty"` + RepeatedNestedMessage []*TestAllTypes_NestedMessage `protobuf:"bytes,48,rep,name=repeated_nested_message,json=repeatedNestedMessage" json:"repeated_nested_message,omitempty"` + RepeatedForeignMessage []*ForeignMessage `protobuf:"bytes,49,rep,name=repeated_foreign_message,json=repeatedForeignMessage" json:"repeated_foreign_message,omitempty"` + RepeatedNestedEnum []TestAllTypes_NestedEnum `protobuf:"varint,51,rep,packed,name=repeated_nested_enum,json=repeatedNestedEnum,enum=conformance.TestAllTypes_NestedEnum" json:"repeated_nested_enum,omitempty"` + RepeatedForeignEnum []ForeignEnum `protobuf:"varint,52,rep,packed,name=repeated_foreign_enum,json=repeatedForeignEnum,enum=conformance.ForeignEnum" json:"repeated_foreign_enum,omitempty"` + RepeatedStringPiece []string `protobuf:"bytes,54,rep,name=repeated_string_piece,json=repeatedStringPiece" json:"repeated_string_piece,omitempty"` + RepeatedCord []string `protobuf:"bytes,55,rep,name=repeated_cord,json=repeatedCord" json:"repeated_cord,omitempty"` + // Map + MapInt32Int32 map[int32]int32 `protobuf:"bytes,56,rep,name=map_int32_int32,json=mapInt32Int32" json:"map_int32_int32,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"varint,2,opt,name=value"` + MapInt64Int64 map[int64]int64 `protobuf:"bytes,57,rep,name=map_int64_int64,json=mapInt64Int64" json:"map_int64_int64,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"varint,2,opt,name=value"` + MapUint32Uint32 map[uint32]uint32 `protobuf:"bytes,58,rep,name=map_uint32_uint32,json=mapUint32Uint32" json:"map_uint32_uint32,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"varint,2,opt,name=value"` + MapUint64Uint64 map[uint64]uint64 `protobuf:"bytes,59,rep,name=map_uint64_uint64,json=mapUint64Uint64" json:"map_uint64_uint64,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"varint,2,opt,name=value"` + MapSint32Sint32 map[int32]int32 `protobuf:"bytes,60,rep,name=map_sint32_sint32,json=mapSint32Sint32" json:"map_sint32_sint32,omitempty" protobuf_key:"zigzag32,1,opt,name=key" protobuf_val:"zigzag32,2,opt,name=value"` + MapSint64Sint64 map[int64]int64 `protobuf:"bytes,61,rep,name=map_sint64_sint64,json=mapSint64Sint64" json:"map_sint64_sint64,omitempty" protobuf_key:"zigzag64,1,opt,name=key" protobuf_val:"zigzag64,2,opt,name=value"` + MapFixed32Fixed32 map[uint32]uint32 `protobuf:"bytes,62,rep,name=map_fixed32_fixed32,json=mapFixed32Fixed32" json:"map_fixed32_fixed32,omitempty" protobuf_key:"fixed32,1,opt,name=key" protobuf_val:"fixed32,2,opt,name=value"` + MapFixed64Fixed64 map[uint64]uint64 `protobuf:"bytes,63,rep,name=map_fixed64_fixed64,json=mapFixed64Fixed64" json:"map_fixed64_fixed64,omitempty" protobuf_key:"fixed64,1,opt,name=key" protobuf_val:"fixed64,2,opt,name=value"` + MapSfixed32Sfixed32 map[int32]int32 `protobuf:"bytes,64,rep,name=map_sfixed32_sfixed32,json=mapSfixed32Sfixed32" json:"map_sfixed32_sfixed32,omitempty" protobuf_key:"fixed32,1,opt,name=key" protobuf_val:"fixed32,2,opt,name=value"` + MapSfixed64Sfixed64 map[int64]int64 `protobuf:"bytes,65,rep,name=map_sfixed64_sfixed64,json=mapSfixed64Sfixed64" json:"map_sfixed64_sfixed64,omitempty" protobuf_key:"fixed64,1,opt,name=key" protobuf_val:"fixed64,2,opt,name=value"` + MapInt32Float map[int32]float32 `protobuf:"bytes,66,rep,name=map_int32_float,json=mapInt32Float" json:"map_int32_float,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"fixed32,2,opt,name=value"` + MapInt32Double map[int32]float64 `protobuf:"bytes,67,rep,name=map_int32_double,json=mapInt32Double" json:"map_int32_double,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"fixed64,2,opt,name=value"` + MapBoolBool map[bool]bool `protobuf:"bytes,68,rep,name=map_bool_bool,json=mapBoolBool" json:"map_bool_bool,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"varint,2,opt,name=value"` + MapStringString map[string]string `protobuf:"bytes,69,rep,name=map_string_string,json=mapStringString" json:"map_string_string,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + MapStringBytes map[string][]byte `protobuf:"bytes,70,rep,name=map_string_bytes,json=mapStringBytes" json:"map_string_bytes,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value,proto3"` + MapStringNestedMessage map[string]*TestAllTypes_NestedMessage `protobuf:"bytes,71,rep,name=map_string_nested_message,json=mapStringNestedMessage" json:"map_string_nested_message,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + MapStringForeignMessage map[string]*ForeignMessage `protobuf:"bytes,72,rep,name=map_string_foreign_message,json=mapStringForeignMessage" json:"map_string_foreign_message,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + MapStringNestedEnum map[string]TestAllTypes_NestedEnum `protobuf:"bytes,73,rep,name=map_string_nested_enum,json=mapStringNestedEnum" json:"map_string_nested_enum,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"varint,2,opt,name=value,enum=conformance.TestAllTypes_NestedEnum"` + MapStringForeignEnum map[string]ForeignEnum `protobuf:"bytes,74,rep,name=map_string_foreign_enum,json=mapStringForeignEnum" json:"map_string_foreign_enum,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"varint,2,opt,name=value,enum=conformance.ForeignEnum"` + // Types that are valid to be assigned to OneofField: + // *TestAllTypes_OneofUint32 + // *TestAllTypes_OneofNestedMessage + // *TestAllTypes_OneofString + // *TestAllTypes_OneofBytes + // *TestAllTypes_OneofBool + // *TestAllTypes_OneofUint64 + // *TestAllTypes_OneofFloat + // *TestAllTypes_OneofDouble + // *TestAllTypes_OneofEnum + OneofField isTestAllTypes_OneofField `protobuf_oneof:"oneof_field"` + // Well-known types + OptionalBoolWrapper *google_protobuf5.BoolValue `protobuf:"bytes,201,opt,name=optional_bool_wrapper,json=optionalBoolWrapper" json:"optional_bool_wrapper,omitempty"` + OptionalInt32Wrapper *google_protobuf5.Int32Value `protobuf:"bytes,202,opt,name=optional_int32_wrapper,json=optionalInt32Wrapper" json:"optional_int32_wrapper,omitempty"` + OptionalInt64Wrapper *google_protobuf5.Int64Value `protobuf:"bytes,203,opt,name=optional_int64_wrapper,json=optionalInt64Wrapper" json:"optional_int64_wrapper,omitempty"` + OptionalUint32Wrapper *google_protobuf5.UInt32Value `protobuf:"bytes,204,opt,name=optional_uint32_wrapper,json=optionalUint32Wrapper" json:"optional_uint32_wrapper,omitempty"` + OptionalUint64Wrapper *google_protobuf5.UInt64Value `protobuf:"bytes,205,opt,name=optional_uint64_wrapper,json=optionalUint64Wrapper" json:"optional_uint64_wrapper,omitempty"` + OptionalFloatWrapper *google_protobuf5.FloatValue `protobuf:"bytes,206,opt,name=optional_float_wrapper,json=optionalFloatWrapper" json:"optional_float_wrapper,omitempty"` + OptionalDoubleWrapper *google_protobuf5.DoubleValue `protobuf:"bytes,207,opt,name=optional_double_wrapper,json=optionalDoubleWrapper" json:"optional_double_wrapper,omitempty"` + OptionalStringWrapper *google_protobuf5.StringValue `protobuf:"bytes,208,opt,name=optional_string_wrapper,json=optionalStringWrapper" json:"optional_string_wrapper,omitempty"` + OptionalBytesWrapper *google_protobuf5.BytesValue `protobuf:"bytes,209,opt,name=optional_bytes_wrapper,json=optionalBytesWrapper" json:"optional_bytes_wrapper,omitempty"` + RepeatedBoolWrapper []*google_protobuf5.BoolValue `protobuf:"bytes,211,rep,name=repeated_bool_wrapper,json=repeatedBoolWrapper" json:"repeated_bool_wrapper,omitempty"` + RepeatedInt32Wrapper []*google_protobuf5.Int32Value `protobuf:"bytes,212,rep,name=repeated_int32_wrapper,json=repeatedInt32Wrapper" json:"repeated_int32_wrapper,omitempty"` + RepeatedInt64Wrapper []*google_protobuf5.Int64Value `protobuf:"bytes,213,rep,name=repeated_int64_wrapper,json=repeatedInt64Wrapper" json:"repeated_int64_wrapper,omitempty"` + RepeatedUint32Wrapper []*google_protobuf5.UInt32Value `protobuf:"bytes,214,rep,name=repeated_uint32_wrapper,json=repeatedUint32Wrapper" json:"repeated_uint32_wrapper,omitempty"` + RepeatedUint64Wrapper []*google_protobuf5.UInt64Value `protobuf:"bytes,215,rep,name=repeated_uint64_wrapper,json=repeatedUint64Wrapper" json:"repeated_uint64_wrapper,omitempty"` + RepeatedFloatWrapper []*google_protobuf5.FloatValue `protobuf:"bytes,216,rep,name=repeated_float_wrapper,json=repeatedFloatWrapper" json:"repeated_float_wrapper,omitempty"` + RepeatedDoubleWrapper []*google_protobuf5.DoubleValue `protobuf:"bytes,217,rep,name=repeated_double_wrapper,json=repeatedDoubleWrapper" json:"repeated_double_wrapper,omitempty"` + RepeatedStringWrapper []*google_protobuf5.StringValue `protobuf:"bytes,218,rep,name=repeated_string_wrapper,json=repeatedStringWrapper" json:"repeated_string_wrapper,omitempty"` + RepeatedBytesWrapper []*google_protobuf5.BytesValue `protobuf:"bytes,219,rep,name=repeated_bytes_wrapper,json=repeatedBytesWrapper" json:"repeated_bytes_wrapper,omitempty"` + OptionalDuration *google_protobuf1.Duration `protobuf:"bytes,301,opt,name=optional_duration,json=optionalDuration" json:"optional_duration,omitempty"` + OptionalTimestamp *google_protobuf4.Timestamp `protobuf:"bytes,302,opt,name=optional_timestamp,json=optionalTimestamp" json:"optional_timestamp,omitempty"` + OptionalFieldMask *google_protobuf2.FieldMask `protobuf:"bytes,303,opt,name=optional_field_mask,json=optionalFieldMask" json:"optional_field_mask,omitempty"` + OptionalStruct *google_protobuf3.Struct `protobuf:"bytes,304,opt,name=optional_struct,json=optionalStruct" json:"optional_struct,omitempty"` + OptionalAny *google_protobuf.Any `protobuf:"bytes,305,opt,name=optional_any,json=optionalAny" json:"optional_any,omitempty"` + OptionalValue *google_protobuf3.Value `protobuf:"bytes,306,opt,name=optional_value,json=optionalValue" json:"optional_value,omitempty"` + RepeatedDuration []*google_protobuf1.Duration `protobuf:"bytes,311,rep,name=repeated_duration,json=repeatedDuration" json:"repeated_duration,omitempty"` + RepeatedTimestamp []*google_protobuf4.Timestamp `protobuf:"bytes,312,rep,name=repeated_timestamp,json=repeatedTimestamp" json:"repeated_timestamp,omitempty"` + RepeatedFieldmask []*google_protobuf2.FieldMask `protobuf:"bytes,313,rep,name=repeated_fieldmask,json=repeatedFieldmask" json:"repeated_fieldmask,omitempty"` + RepeatedStruct []*google_protobuf3.Struct `protobuf:"bytes,324,rep,name=repeated_struct,json=repeatedStruct" json:"repeated_struct,omitempty"` + RepeatedAny []*google_protobuf.Any `protobuf:"bytes,315,rep,name=repeated_any,json=repeatedAny" json:"repeated_any,omitempty"` + RepeatedValue []*google_protobuf3.Value `protobuf:"bytes,316,rep,name=repeated_value,json=repeatedValue" json:"repeated_value,omitempty"` + // Test field-name-to-JSON-name convention. + // (protobuf says names can be any valid C/C++ identifier.) + Fieldname1 int32 `protobuf:"varint,401,opt,name=fieldname1" json:"fieldname1,omitempty"` + FieldName2 int32 `protobuf:"varint,402,opt,name=field_name2,json=fieldName2" json:"field_name2,omitempty"` + XFieldName3 int32 `protobuf:"varint,403,opt,name=_field_name3,json=FieldName3" json:"_field_name3,omitempty"` + Field_Name4_ int32 `protobuf:"varint,404,opt,name=field__name4_,json=fieldName4" json:"field__name4_,omitempty"` + Field0Name5 int32 `protobuf:"varint,405,opt,name=field0name5" json:"field0name5,omitempty"` + Field_0Name6 int32 `protobuf:"varint,406,opt,name=field_0_name6,json=field0Name6" json:"field_0_name6,omitempty"` + FieldName7 int32 `protobuf:"varint,407,opt,name=fieldName7" json:"fieldName7,omitempty"` + FieldName8 int32 `protobuf:"varint,408,opt,name=FieldName8" json:"FieldName8,omitempty"` + Field_Name9 int32 `protobuf:"varint,409,opt,name=field_Name9,json=fieldName9" json:"field_Name9,omitempty"` + Field_Name10 int32 `protobuf:"varint,410,opt,name=Field_Name10,json=FieldName10" json:"Field_Name10,omitempty"` + FIELD_NAME11 int32 `protobuf:"varint,411,opt,name=FIELD_NAME11,json=FIELDNAME11" json:"FIELD_NAME11,omitempty"` + FIELDName12 int32 `protobuf:"varint,412,opt,name=FIELD_name12,json=FIELDName12" json:"FIELD_name12,omitempty"` + XFieldName13 int32 `protobuf:"varint,413,opt,name=__field_name13,json=FieldName13" json:"__field_name13,omitempty"` + X_FieldName14 int32 `protobuf:"varint,414,opt,name=__Field_name14,json=FieldName14" json:"__Field_name14,omitempty"` + Field_Name15 int32 `protobuf:"varint,415,opt,name=field__name15,json=fieldName15" json:"field__name15,omitempty"` + Field__Name16 int32 `protobuf:"varint,416,opt,name=field__Name16,json=fieldName16" json:"field__Name16,omitempty"` + FieldName17__ int32 `protobuf:"varint,417,opt,name=field_name17__,json=fieldName17" json:"field_name17__,omitempty"` + FieldName18__ int32 `protobuf:"varint,418,opt,name=Field_name18__,json=FieldName18" json:"Field_name18__,omitempty"` +} + +func (m *TestAllTypes) Reset() { *m = TestAllTypes{} } +func (m *TestAllTypes) String() string { return proto.CompactTextString(m) } +func (*TestAllTypes) ProtoMessage() {} +func (*TestAllTypes) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } + +type isTestAllTypes_OneofField interface { + isTestAllTypes_OneofField() +} + +type TestAllTypes_OneofUint32 struct { + OneofUint32 uint32 `protobuf:"varint,111,opt,name=oneof_uint32,json=oneofUint32,oneof"` +} +type TestAllTypes_OneofNestedMessage struct { + OneofNestedMessage *TestAllTypes_NestedMessage `protobuf:"bytes,112,opt,name=oneof_nested_message,json=oneofNestedMessage,oneof"` +} +type TestAllTypes_OneofString struct { + OneofString string `protobuf:"bytes,113,opt,name=oneof_string,json=oneofString,oneof"` +} +type TestAllTypes_OneofBytes struct { + OneofBytes []byte `protobuf:"bytes,114,opt,name=oneof_bytes,json=oneofBytes,proto3,oneof"` +} +type TestAllTypes_OneofBool struct { + OneofBool bool `protobuf:"varint,115,opt,name=oneof_bool,json=oneofBool,oneof"` +} +type TestAllTypes_OneofUint64 struct { + OneofUint64 uint64 `protobuf:"varint,116,opt,name=oneof_uint64,json=oneofUint64,oneof"` +} +type TestAllTypes_OneofFloat struct { + OneofFloat float32 `protobuf:"fixed32,117,opt,name=oneof_float,json=oneofFloat,oneof"` +} +type TestAllTypes_OneofDouble struct { + OneofDouble float64 `protobuf:"fixed64,118,opt,name=oneof_double,json=oneofDouble,oneof"` +} +type TestAllTypes_OneofEnum struct { + OneofEnum TestAllTypes_NestedEnum `protobuf:"varint,119,opt,name=oneof_enum,json=oneofEnum,enum=conformance.TestAllTypes_NestedEnum,oneof"` +} + +func (*TestAllTypes_OneofUint32) isTestAllTypes_OneofField() {} +func (*TestAllTypes_OneofNestedMessage) isTestAllTypes_OneofField() {} +func (*TestAllTypes_OneofString) isTestAllTypes_OneofField() {} +func (*TestAllTypes_OneofBytes) isTestAllTypes_OneofField() {} +func (*TestAllTypes_OneofBool) isTestAllTypes_OneofField() {} +func (*TestAllTypes_OneofUint64) isTestAllTypes_OneofField() {} +func (*TestAllTypes_OneofFloat) isTestAllTypes_OneofField() {} +func (*TestAllTypes_OneofDouble) isTestAllTypes_OneofField() {} +func (*TestAllTypes_OneofEnum) isTestAllTypes_OneofField() {} + +func (m *TestAllTypes) GetOneofField() isTestAllTypes_OneofField { + if m != nil { + return m.OneofField + } + return nil +} + +func (m *TestAllTypes) GetOptionalInt32() int32 { + if m != nil { + return m.OptionalInt32 + } + return 0 +} + +func (m *TestAllTypes) GetOptionalInt64() int64 { + if m != nil { + return m.OptionalInt64 + } + return 0 +} + +func (m *TestAllTypes) GetOptionalUint32() uint32 { + if m != nil { + return m.OptionalUint32 + } + return 0 +} + +func (m *TestAllTypes) GetOptionalUint64() uint64 { + if m != nil { + return m.OptionalUint64 + } + return 0 +} + +func (m *TestAllTypes) GetOptionalSint32() int32 { + if m != nil { + return m.OptionalSint32 + } + return 0 +} + +func (m *TestAllTypes) GetOptionalSint64() int64 { + if m != nil { + return m.OptionalSint64 + } + return 0 +} + +func (m *TestAllTypes) GetOptionalFixed32() uint32 { + if m != nil { + return m.OptionalFixed32 + } + return 0 +} + +func (m *TestAllTypes) GetOptionalFixed64() uint64 { + if m != nil { + return m.OptionalFixed64 + } + return 0 +} + +func (m *TestAllTypes) GetOptionalSfixed32() int32 { + if m != nil { + return m.OptionalSfixed32 + } + return 0 +} + +func (m *TestAllTypes) GetOptionalSfixed64() int64 { + if m != nil { + return m.OptionalSfixed64 + } + return 0 +} + +func (m *TestAllTypes) GetOptionalFloat() float32 { + if m != nil { + return m.OptionalFloat + } + return 0 +} + +func (m *TestAllTypes) GetOptionalDouble() float64 { + if m != nil { + return m.OptionalDouble + } + return 0 +} + +func (m *TestAllTypes) GetOptionalBool() bool { + if m != nil { + return m.OptionalBool + } + return false +} + +func (m *TestAllTypes) GetOptionalString() string { + if m != nil { + return m.OptionalString + } + return "" +} + +func (m *TestAllTypes) GetOptionalBytes() []byte { + if m != nil { + return m.OptionalBytes + } + return nil +} + +func (m *TestAllTypes) GetOptionalNestedMessage() *TestAllTypes_NestedMessage { + if m != nil { + return m.OptionalNestedMessage + } + return nil +} + +func (m *TestAllTypes) GetOptionalForeignMessage() *ForeignMessage { + if m != nil { + return m.OptionalForeignMessage + } + return nil +} + +func (m *TestAllTypes) GetOptionalNestedEnum() TestAllTypes_NestedEnum { + if m != nil { + return m.OptionalNestedEnum + } + return TestAllTypes_FOO +} + +func (m *TestAllTypes) GetOptionalForeignEnum() ForeignEnum { + if m != nil { + return m.OptionalForeignEnum + } + return ForeignEnum_FOREIGN_FOO +} + +func (m *TestAllTypes) GetOptionalStringPiece() string { + if m != nil { + return m.OptionalStringPiece + } + return "" +} + +func (m *TestAllTypes) GetOptionalCord() string { + if m != nil { + return m.OptionalCord + } + return "" +} + +func (m *TestAllTypes) GetRecursiveMessage() *TestAllTypes { + if m != nil { + return m.RecursiveMessage + } + return nil +} + +func (m *TestAllTypes) GetRepeatedInt32() []int32 { + if m != nil { + return m.RepeatedInt32 + } + return nil +} + +func (m *TestAllTypes) GetRepeatedInt64() []int64 { + if m != nil { + return m.RepeatedInt64 + } + return nil +} + +func (m *TestAllTypes) GetRepeatedUint32() []uint32 { + if m != nil { + return m.RepeatedUint32 + } + return nil +} + +func (m *TestAllTypes) GetRepeatedUint64() []uint64 { + if m != nil { + return m.RepeatedUint64 + } + return nil +} + +func (m *TestAllTypes) GetRepeatedSint32() []int32 { + if m != nil { + return m.RepeatedSint32 + } + return nil +} + +func (m *TestAllTypes) GetRepeatedSint64() []int64 { + if m != nil { + return m.RepeatedSint64 + } + return nil +} + +func (m *TestAllTypes) GetRepeatedFixed32() []uint32 { + if m != nil { + return m.RepeatedFixed32 + } + return nil +} + +func (m *TestAllTypes) GetRepeatedFixed64() []uint64 { + if m != nil { + return m.RepeatedFixed64 + } + return nil +} + +func (m *TestAllTypes) GetRepeatedSfixed32() []int32 { + if m != nil { + return m.RepeatedSfixed32 + } + return nil +} + +func (m *TestAllTypes) GetRepeatedSfixed64() []int64 { + if m != nil { + return m.RepeatedSfixed64 + } + return nil +} + +func (m *TestAllTypes) GetRepeatedFloat() []float32 { + if m != nil { + return m.RepeatedFloat + } + return nil +} + +func (m *TestAllTypes) GetRepeatedDouble() []float64 { + if m != nil { + return m.RepeatedDouble + } + return nil +} + +func (m *TestAllTypes) GetRepeatedBool() []bool { + if m != nil { + return m.RepeatedBool + } + return nil +} + +func (m *TestAllTypes) GetRepeatedString() []string { + if m != nil { + return m.RepeatedString + } + return nil +} + +func (m *TestAllTypes) GetRepeatedBytes() [][]byte { + if m != nil { + return m.RepeatedBytes + } + return nil +} + +func (m *TestAllTypes) GetRepeatedNestedMessage() []*TestAllTypes_NestedMessage { + if m != nil { + return m.RepeatedNestedMessage + } + return nil +} + +func (m *TestAllTypes) GetRepeatedForeignMessage() []*ForeignMessage { + if m != nil { + return m.RepeatedForeignMessage + } + return nil +} + +func (m *TestAllTypes) GetRepeatedNestedEnum() []TestAllTypes_NestedEnum { + if m != nil { + return m.RepeatedNestedEnum + } + return nil +} + +func (m *TestAllTypes) GetRepeatedForeignEnum() []ForeignEnum { + if m != nil { + return m.RepeatedForeignEnum + } + return nil +} + +func (m *TestAllTypes) GetRepeatedStringPiece() []string { + if m != nil { + return m.RepeatedStringPiece + } + return nil +} + +func (m *TestAllTypes) GetRepeatedCord() []string { + if m != nil { + return m.RepeatedCord + } + return nil +} + +func (m *TestAllTypes) GetMapInt32Int32() map[int32]int32 { + if m != nil { + return m.MapInt32Int32 + } + return nil +} + +func (m *TestAllTypes) GetMapInt64Int64() map[int64]int64 { + if m != nil { + return m.MapInt64Int64 + } + return nil +} + +func (m *TestAllTypes) GetMapUint32Uint32() map[uint32]uint32 { + if m != nil { + return m.MapUint32Uint32 + } + return nil +} + +func (m *TestAllTypes) GetMapUint64Uint64() map[uint64]uint64 { + if m != nil { + return m.MapUint64Uint64 + } + return nil +} + +func (m *TestAllTypes) GetMapSint32Sint32() map[int32]int32 { + if m != nil { + return m.MapSint32Sint32 + } + return nil +} + +func (m *TestAllTypes) GetMapSint64Sint64() map[int64]int64 { + if m != nil { + return m.MapSint64Sint64 + } + return nil +} + +func (m *TestAllTypes) GetMapFixed32Fixed32() map[uint32]uint32 { + if m != nil { + return m.MapFixed32Fixed32 + } + return nil +} + +func (m *TestAllTypes) GetMapFixed64Fixed64() map[uint64]uint64 { + if m != nil { + return m.MapFixed64Fixed64 + } + return nil +} + +func (m *TestAllTypes) GetMapSfixed32Sfixed32() map[int32]int32 { + if m != nil { + return m.MapSfixed32Sfixed32 + } + return nil +} + +func (m *TestAllTypes) GetMapSfixed64Sfixed64() map[int64]int64 { + if m != nil { + return m.MapSfixed64Sfixed64 + } + return nil +} + +func (m *TestAllTypes) GetMapInt32Float() map[int32]float32 { + if m != nil { + return m.MapInt32Float + } + return nil +} + +func (m *TestAllTypes) GetMapInt32Double() map[int32]float64 { + if m != nil { + return m.MapInt32Double + } + return nil +} + +func (m *TestAllTypes) GetMapBoolBool() map[bool]bool { + if m != nil { + return m.MapBoolBool + } + return nil +} + +func (m *TestAllTypes) GetMapStringString() map[string]string { + if m != nil { + return m.MapStringString + } + return nil +} + +func (m *TestAllTypes) GetMapStringBytes() map[string][]byte { + if m != nil { + return m.MapStringBytes + } + return nil +} + +func (m *TestAllTypes) GetMapStringNestedMessage() map[string]*TestAllTypes_NestedMessage { + if m != nil { + return m.MapStringNestedMessage + } + return nil +} + +func (m *TestAllTypes) GetMapStringForeignMessage() map[string]*ForeignMessage { + if m != nil { + return m.MapStringForeignMessage + } + return nil +} + +func (m *TestAllTypes) GetMapStringNestedEnum() map[string]TestAllTypes_NestedEnum { + if m != nil { + return m.MapStringNestedEnum + } + return nil +} + +func (m *TestAllTypes) GetMapStringForeignEnum() map[string]ForeignEnum { + if m != nil { + return m.MapStringForeignEnum + } + return nil +} + +func (m *TestAllTypes) GetOneofUint32() uint32 { + if x, ok := m.GetOneofField().(*TestAllTypes_OneofUint32); ok { + return x.OneofUint32 + } + return 0 +} + +func (m *TestAllTypes) GetOneofNestedMessage() *TestAllTypes_NestedMessage { + if x, ok := m.GetOneofField().(*TestAllTypes_OneofNestedMessage); ok { + return x.OneofNestedMessage + } + return nil +} + +func (m *TestAllTypes) GetOneofString() string { + if x, ok := m.GetOneofField().(*TestAllTypes_OneofString); ok { + return x.OneofString + } + return "" +} + +func (m *TestAllTypes) GetOneofBytes() []byte { + if x, ok := m.GetOneofField().(*TestAllTypes_OneofBytes); ok { + return x.OneofBytes + } + return nil +} + +func (m *TestAllTypes) GetOneofBool() bool { + if x, ok := m.GetOneofField().(*TestAllTypes_OneofBool); ok { + return x.OneofBool + } + return false +} + +func (m *TestAllTypes) GetOneofUint64() uint64 { + if x, ok := m.GetOneofField().(*TestAllTypes_OneofUint64); ok { + return x.OneofUint64 + } + return 0 +} + +func (m *TestAllTypes) GetOneofFloat() float32 { + if x, ok := m.GetOneofField().(*TestAllTypes_OneofFloat); ok { + return x.OneofFloat + } + return 0 +} + +func (m *TestAllTypes) GetOneofDouble() float64 { + if x, ok := m.GetOneofField().(*TestAllTypes_OneofDouble); ok { + return x.OneofDouble + } + return 0 +} + +func (m *TestAllTypes) GetOneofEnum() TestAllTypes_NestedEnum { + if x, ok := m.GetOneofField().(*TestAllTypes_OneofEnum); ok { + return x.OneofEnum + } + return TestAllTypes_FOO +} + +func (m *TestAllTypes) GetOptionalBoolWrapper() *google_protobuf5.BoolValue { + if m != nil { + return m.OptionalBoolWrapper + } + return nil +} + +func (m *TestAllTypes) GetOptionalInt32Wrapper() *google_protobuf5.Int32Value { + if m != nil { + return m.OptionalInt32Wrapper + } + return nil +} + +func (m *TestAllTypes) GetOptionalInt64Wrapper() *google_protobuf5.Int64Value { + if m != nil { + return m.OptionalInt64Wrapper + } + return nil +} + +func (m *TestAllTypes) GetOptionalUint32Wrapper() *google_protobuf5.UInt32Value { + if m != nil { + return m.OptionalUint32Wrapper + } + return nil +} + +func (m *TestAllTypes) GetOptionalUint64Wrapper() *google_protobuf5.UInt64Value { + if m != nil { + return m.OptionalUint64Wrapper + } + return nil +} + +func (m *TestAllTypes) GetOptionalFloatWrapper() *google_protobuf5.FloatValue { + if m != nil { + return m.OptionalFloatWrapper + } + return nil +} + +func (m *TestAllTypes) GetOptionalDoubleWrapper() *google_protobuf5.DoubleValue { + if m != nil { + return m.OptionalDoubleWrapper + } + return nil +} + +func (m *TestAllTypes) GetOptionalStringWrapper() *google_protobuf5.StringValue { + if m != nil { + return m.OptionalStringWrapper + } + return nil +} + +func (m *TestAllTypes) GetOptionalBytesWrapper() *google_protobuf5.BytesValue { + if m != nil { + return m.OptionalBytesWrapper + } + return nil +} + +func (m *TestAllTypes) GetRepeatedBoolWrapper() []*google_protobuf5.BoolValue { + if m != nil { + return m.RepeatedBoolWrapper + } + return nil +} + +func (m *TestAllTypes) GetRepeatedInt32Wrapper() []*google_protobuf5.Int32Value { + if m != nil { + return m.RepeatedInt32Wrapper + } + return nil +} + +func (m *TestAllTypes) GetRepeatedInt64Wrapper() []*google_protobuf5.Int64Value { + if m != nil { + return m.RepeatedInt64Wrapper + } + return nil +} + +func (m *TestAllTypes) GetRepeatedUint32Wrapper() []*google_protobuf5.UInt32Value { + if m != nil { + return m.RepeatedUint32Wrapper + } + return nil +} + +func (m *TestAllTypes) GetRepeatedUint64Wrapper() []*google_protobuf5.UInt64Value { + if m != nil { + return m.RepeatedUint64Wrapper + } + return nil +} + +func (m *TestAllTypes) GetRepeatedFloatWrapper() []*google_protobuf5.FloatValue { + if m != nil { + return m.RepeatedFloatWrapper + } + return nil +} + +func (m *TestAllTypes) GetRepeatedDoubleWrapper() []*google_protobuf5.DoubleValue { + if m != nil { + return m.RepeatedDoubleWrapper + } + return nil +} + +func (m *TestAllTypes) GetRepeatedStringWrapper() []*google_protobuf5.StringValue { + if m != nil { + return m.RepeatedStringWrapper + } + return nil +} + +func (m *TestAllTypes) GetRepeatedBytesWrapper() []*google_protobuf5.BytesValue { + if m != nil { + return m.RepeatedBytesWrapper + } + return nil +} + +func (m *TestAllTypes) GetOptionalDuration() *google_protobuf1.Duration { + if m != nil { + return m.OptionalDuration + } + return nil +} + +func (m *TestAllTypes) GetOptionalTimestamp() *google_protobuf4.Timestamp { + if m != nil { + return m.OptionalTimestamp + } + return nil +} + +func (m *TestAllTypes) GetOptionalFieldMask() *google_protobuf2.FieldMask { + if m != nil { + return m.OptionalFieldMask + } + return nil +} + +func (m *TestAllTypes) GetOptionalStruct() *google_protobuf3.Struct { + if m != nil { + return m.OptionalStruct + } + return nil +} + +func (m *TestAllTypes) GetOptionalAny() *google_protobuf.Any { + if m != nil { + return m.OptionalAny + } + return nil +} + +func (m *TestAllTypes) GetOptionalValue() *google_protobuf3.Value { + if m != nil { + return m.OptionalValue + } + return nil +} + +func (m *TestAllTypes) GetRepeatedDuration() []*google_protobuf1.Duration { + if m != nil { + return m.RepeatedDuration + } + return nil +} + +func (m *TestAllTypes) GetRepeatedTimestamp() []*google_protobuf4.Timestamp { + if m != nil { + return m.RepeatedTimestamp + } + return nil +} + +func (m *TestAllTypes) GetRepeatedFieldmask() []*google_protobuf2.FieldMask { + if m != nil { + return m.RepeatedFieldmask + } + return nil +} + +func (m *TestAllTypes) GetRepeatedStruct() []*google_protobuf3.Struct { + if m != nil { + return m.RepeatedStruct + } + return nil +} + +func (m *TestAllTypes) GetRepeatedAny() []*google_protobuf.Any { + if m != nil { + return m.RepeatedAny + } + return nil +} + +func (m *TestAllTypes) GetRepeatedValue() []*google_protobuf3.Value { + if m != nil { + return m.RepeatedValue + } + return nil +} + +func (m *TestAllTypes) GetFieldname1() int32 { + if m != nil { + return m.Fieldname1 + } + return 0 +} + +func (m *TestAllTypes) GetFieldName2() int32 { + if m != nil { + return m.FieldName2 + } + return 0 +} + +func (m *TestAllTypes) GetXFieldName3() int32 { + if m != nil { + return m.XFieldName3 + } + return 0 +} + +func (m *TestAllTypes) GetField_Name4_() int32 { + if m != nil { + return m.Field_Name4_ + } + return 0 +} + +func (m *TestAllTypes) GetField0Name5() int32 { + if m != nil { + return m.Field0Name5 + } + return 0 +} + +func (m *TestAllTypes) GetField_0Name6() int32 { + if m != nil { + return m.Field_0Name6 + } + return 0 +} + +func (m *TestAllTypes) GetFieldName7() int32 { + if m != nil { + return m.FieldName7 + } + return 0 +} + +func (m *TestAllTypes) GetFieldName8() int32 { + if m != nil { + return m.FieldName8 + } + return 0 +} + +func (m *TestAllTypes) GetField_Name9() int32 { + if m != nil { + return m.Field_Name9 + } + return 0 +} + +func (m *TestAllTypes) GetField_Name10() int32 { + if m != nil { + return m.Field_Name10 + } + return 0 +} + +func (m *TestAllTypes) GetFIELD_NAME11() int32 { + if m != nil { + return m.FIELD_NAME11 + } + return 0 +} + +func (m *TestAllTypes) GetFIELDName12() int32 { + if m != nil { + return m.FIELDName12 + } + return 0 +} + +func (m *TestAllTypes) GetXFieldName13() int32 { + if m != nil { + return m.XFieldName13 + } + return 0 +} + +func (m *TestAllTypes) GetX_FieldName14() int32 { + if m != nil { + return m.X_FieldName14 + } + return 0 +} + +func (m *TestAllTypes) GetField_Name15() int32 { + if m != nil { + return m.Field_Name15 + } + return 0 +} + +func (m *TestAllTypes) GetField__Name16() int32 { + if m != nil { + return m.Field__Name16 + } + return 0 +} + +func (m *TestAllTypes) GetFieldName17__() int32 { + if m != nil { + return m.FieldName17__ + } + return 0 +} + +func (m *TestAllTypes) GetFieldName18__() int32 { + if m != nil { + return m.FieldName18__ + } + return 0 +} + +// XXX_OneofFuncs is for the internal use of the proto package. +func (*TestAllTypes) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { + return _TestAllTypes_OneofMarshaler, _TestAllTypes_OneofUnmarshaler, _TestAllTypes_OneofSizer, []interface{}{ + (*TestAllTypes_OneofUint32)(nil), + (*TestAllTypes_OneofNestedMessage)(nil), + (*TestAllTypes_OneofString)(nil), + (*TestAllTypes_OneofBytes)(nil), + (*TestAllTypes_OneofBool)(nil), + (*TestAllTypes_OneofUint64)(nil), + (*TestAllTypes_OneofFloat)(nil), + (*TestAllTypes_OneofDouble)(nil), + (*TestAllTypes_OneofEnum)(nil), + } +} + +func _TestAllTypes_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { + m := msg.(*TestAllTypes) + // oneof_field + switch x := m.OneofField.(type) { + case *TestAllTypes_OneofUint32: + b.EncodeVarint(111<<3 | proto.WireVarint) + b.EncodeVarint(uint64(x.OneofUint32)) + case *TestAllTypes_OneofNestedMessage: + b.EncodeVarint(112<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.OneofNestedMessage); err != nil { + return err + } + case *TestAllTypes_OneofString: + b.EncodeVarint(113<<3 | proto.WireBytes) + b.EncodeStringBytes(x.OneofString) + case *TestAllTypes_OneofBytes: + b.EncodeVarint(114<<3 | proto.WireBytes) + b.EncodeRawBytes(x.OneofBytes) + case *TestAllTypes_OneofBool: + t := uint64(0) + if x.OneofBool { + t = 1 + } + b.EncodeVarint(115<<3 | proto.WireVarint) + b.EncodeVarint(t) + case *TestAllTypes_OneofUint64: + b.EncodeVarint(116<<3 | proto.WireVarint) + b.EncodeVarint(uint64(x.OneofUint64)) + case *TestAllTypes_OneofFloat: + b.EncodeVarint(117<<3 | proto.WireFixed32) + b.EncodeFixed32(uint64(math.Float32bits(x.OneofFloat))) + case *TestAllTypes_OneofDouble: + b.EncodeVarint(118<<3 | proto.WireFixed64) + b.EncodeFixed64(math.Float64bits(x.OneofDouble)) + case *TestAllTypes_OneofEnum: + b.EncodeVarint(119<<3 | proto.WireVarint) + b.EncodeVarint(uint64(x.OneofEnum)) + case nil: + default: + return fmt.Errorf("TestAllTypes.OneofField has unexpected type %T", x) + } + return nil +} + +func _TestAllTypes_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { + m := msg.(*TestAllTypes) + switch tag { + case 111: // oneof_field.oneof_uint32 + if wire != proto.WireVarint { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeVarint() + m.OneofField = &TestAllTypes_OneofUint32{uint32(x)} + return true, err + case 112: // oneof_field.oneof_nested_message + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(TestAllTypes_NestedMessage) + err := b.DecodeMessage(msg) + m.OneofField = &TestAllTypes_OneofNestedMessage{msg} + return true, err + case 113: // oneof_field.oneof_string + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeStringBytes() + m.OneofField = &TestAllTypes_OneofString{x} + return true, err + case 114: // oneof_field.oneof_bytes + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeRawBytes(true) + m.OneofField = &TestAllTypes_OneofBytes{x} + return true, err + case 115: // oneof_field.oneof_bool + if wire != proto.WireVarint { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeVarint() + m.OneofField = &TestAllTypes_OneofBool{x != 0} + return true, err + case 116: // oneof_field.oneof_uint64 + if wire != proto.WireVarint { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeVarint() + m.OneofField = &TestAllTypes_OneofUint64{x} + return true, err + case 117: // oneof_field.oneof_float + if wire != proto.WireFixed32 { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeFixed32() + m.OneofField = &TestAllTypes_OneofFloat{math.Float32frombits(uint32(x))} + return true, err + case 118: // oneof_field.oneof_double + if wire != proto.WireFixed64 { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeFixed64() + m.OneofField = &TestAllTypes_OneofDouble{math.Float64frombits(x)} + return true, err + case 119: // oneof_field.oneof_enum + if wire != proto.WireVarint { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeVarint() + m.OneofField = &TestAllTypes_OneofEnum{TestAllTypes_NestedEnum(x)} + return true, err + default: + return false, nil + } +} + +func _TestAllTypes_OneofSizer(msg proto.Message) (n int) { + m := msg.(*TestAllTypes) + // oneof_field + switch x := m.OneofField.(type) { + case *TestAllTypes_OneofUint32: + n += proto.SizeVarint(111<<3 | proto.WireVarint) + n += proto.SizeVarint(uint64(x.OneofUint32)) + case *TestAllTypes_OneofNestedMessage: + s := proto.Size(x.OneofNestedMessage) + n += proto.SizeVarint(112<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *TestAllTypes_OneofString: + n += proto.SizeVarint(113<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(len(x.OneofString))) + n += len(x.OneofString) + case *TestAllTypes_OneofBytes: + n += proto.SizeVarint(114<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(len(x.OneofBytes))) + n += len(x.OneofBytes) + case *TestAllTypes_OneofBool: + n += proto.SizeVarint(115<<3 | proto.WireVarint) + n += 1 + case *TestAllTypes_OneofUint64: + n += proto.SizeVarint(116<<3 | proto.WireVarint) + n += proto.SizeVarint(uint64(x.OneofUint64)) + case *TestAllTypes_OneofFloat: + n += proto.SizeVarint(117<<3 | proto.WireFixed32) + n += 4 + case *TestAllTypes_OneofDouble: + n += proto.SizeVarint(118<<3 | proto.WireFixed64) + n += 8 + case *TestAllTypes_OneofEnum: + n += proto.SizeVarint(119<<3 | proto.WireVarint) + n += proto.SizeVarint(uint64(x.OneofEnum)) + case nil: + default: + panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) + } + return n +} + +type TestAllTypes_NestedMessage struct { + A int32 `protobuf:"varint,1,opt,name=a" json:"a,omitempty"` + Corecursive *TestAllTypes `protobuf:"bytes,2,opt,name=corecursive" json:"corecursive,omitempty"` +} + +func (m *TestAllTypes_NestedMessage) Reset() { *m = TestAllTypes_NestedMessage{} } +func (m *TestAllTypes_NestedMessage) String() string { return proto.CompactTextString(m) } +func (*TestAllTypes_NestedMessage) ProtoMessage() {} +func (*TestAllTypes_NestedMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2, 0} } + +func (m *TestAllTypes_NestedMessage) GetA() int32 { + if m != nil { + return m.A + } + return 0 +} + +func (m *TestAllTypes_NestedMessage) GetCorecursive() *TestAllTypes { + if m != nil { + return m.Corecursive + } + return nil +} + +type ForeignMessage struct { + C int32 `protobuf:"varint,1,opt,name=c" json:"c,omitempty"` +} + +func (m *ForeignMessage) Reset() { *m = ForeignMessage{} } +func (m *ForeignMessage) String() string { return proto.CompactTextString(m) } +func (*ForeignMessage) ProtoMessage() {} +func (*ForeignMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } + +func (m *ForeignMessage) GetC() int32 { + if m != nil { + return m.C + } + return 0 +} + +func init() { + proto.RegisterType((*ConformanceRequest)(nil), "conformance.ConformanceRequest") + proto.RegisterType((*ConformanceResponse)(nil), "conformance.ConformanceResponse") + proto.RegisterType((*TestAllTypes)(nil), "conformance.TestAllTypes") + proto.RegisterType((*TestAllTypes_NestedMessage)(nil), "conformance.TestAllTypes.NestedMessage") + proto.RegisterType((*ForeignMessage)(nil), "conformance.ForeignMessage") + proto.RegisterEnum("conformance.WireFormat", WireFormat_name, WireFormat_value) + proto.RegisterEnum("conformance.ForeignEnum", ForeignEnum_name, ForeignEnum_value) + proto.RegisterEnum("conformance.TestAllTypes_NestedEnum", TestAllTypes_NestedEnum_name, TestAllTypes_NestedEnum_value) +} + +func init() { proto.RegisterFile("conformance_proto/conformance.proto", fileDescriptor0) } + +var fileDescriptor0 = []byte{ + // 2737 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x5a, 0xd9, 0x72, 0xdb, 0xc8, + 0xd5, 0x16, 0x08, 0x59, 0x4b, 0x93, 0x92, 0xa8, 0xd6, 0xd6, 0x96, 0x5d, 0x63, 0x58, 0xb2, 0x7f, + 0xd3, 0xf6, 0x8c, 0xac, 0x05, 0x86, 0x65, 0xcf, 0x3f, 0x8e, 0x45, 0x9b, 0xb4, 0xe4, 0x8c, 0x25, + 0x17, 0x64, 0x8d, 0xab, 0x9c, 0x0b, 0x06, 0xa6, 0x20, 0x15, 0xc7, 0x24, 0xc1, 0x01, 0x48, 0x4f, + 0x94, 0xcb, 0xbc, 0x41, 0xf6, 0x7d, 0xbd, 0xcf, 0x7a, 0x93, 0xa4, 0x92, 0xab, 0x54, 0x6e, 0xb2, + 0x27, 0x95, 0x3d, 0x79, 0x85, 0xbc, 0x43, 0x52, 0xbd, 0xa2, 0xbb, 0x01, 0x50, 0xf4, 0x54, 0x0d, + 0x25, 0x1e, 0x7c, 0xfd, 0x9d, 0xd3, 0xe7, 0x1c, 0x7c, 0x2d, 0x1c, 0x18, 0x2c, 0xd7, 0x83, 0xf6, + 0x51, 0x10, 0xb6, 0xbc, 0x76, 0xdd, 0xaf, 0x75, 0xc2, 0xa0, 0x1b, 0xdc, 0x90, 0x2c, 0x2b, 0xc4, + 0x02, 0xf3, 0x92, 0x69, 0xf1, 0xec, 0x71, 0x10, 0x1c, 0x37, 0xfd, 0x1b, 0xe4, 0xd2, 0x8b, 0xde, + 0xd1, 0x0d, 0xaf, 0x7d, 0x42, 0x71, 0x8b, 0x6f, 0xe8, 0x97, 0x0e, 0x7b, 0xa1, 0xd7, 0x6d, 0x04, + 0x6d, 0x76, 0xdd, 0xd2, 0xaf, 0x1f, 0x35, 0xfc, 0xe6, 0x61, 0xad, 0xe5, 0x45, 0x2f, 0x19, 0xe2, + 0xbc, 0x8e, 0x88, 0xba, 0x61, 0xaf, 0xde, 0x65, 0x57, 0x2f, 0xe8, 0x57, 0xbb, 0x8d, 0x96, 0x1f, + 0x75, 0xbd, 0x56, 0x27, 0x2b, 0x80, 0x0f, 0x43, 0xaf, 0xd3, 0xf1, 0xc3, 0x88, 0x5e, 0x5f, 0xfa, + 0x85, 0x01, 0xe0, 0xfd, 0x78, 0x2f, 0xae, 0xff, 0x41, 0xcf, 0x8f, 0xba, 0xf0, 0x3a, 0x28, 0xf2, + 0x15, 0xb5, 0x8e, 0x77, 0xd2, 0x0c, 0xbc, 0x43, 0x64, 0x58, 0x46, 0xa9, 0xb0, 0x3d, 0xe4, 0x4e, + 0xf1, 0x2b, 0x4f, 0xe8, 0x05, 0xb8, 0x0c, 0x0a, 0xef, 0x47, 0x41, 0x5b, 0x00, 0x73, 0x96, 0x51, + 0x1a, 0xdf, 0x1e, 0x72, 0xf3, 0xd8, 0xca, 0x41, 0x7b, 0x60, 0x21, 0xa4, 0xe4, 0xfe, 0x61, 0x2d, + 0xe8, 0x75, 0x3b, 0xbd, 0x6e, 0x8d, 0x78, 0xed, 0x22, 0xd3, 0x32, 0x4a, 0x93, 0xeb, 0x0b, 0x2b, + 0x72, 0x9a, 0x9f, 0x35, 0x42, 0xbf, 0x4a, 0x2e, 0xbb, 0x73, 0x62, 0xdd, 0x1e, 0x59, 0x46, 0xcd, + 0xe5, 0x71, 0x30, 0xca, 0x1c, 0x2e, 0x7d, 0x2a, 0x07, 0x66, 0x94, 0x4d, 0x44, 0x9d, 0xa0, 0x1d, + 0xf9, 0xf0, 0x22, 0xc8, 0x77, 0xbc, 0x30, 0xf2, 0x6b, 0x7e, 0x18, 0x06, 0x21, 0xd9, 0x00, 0x8e, + 0x0b, 0x10, 0x63, 0x05, 0xdb, 0xe0, 0x55, 0x30, 0x15, 0xf9, 0x61, 0xc3, 0x6b, 0x36, 0x3e, 0xc9, + 0x61, 0x23, 0x0c, 0x36, 0x29, 0x2e, 0x50, 0xe8, 0x65, 0x30, 0x11, 0xf6, 0xda, 0x38, 0xc1, 0x0c, + 0xc8, 0xf7, 0x59, 0x60, 0x66, 0x0a, 0x4b, 0x4b, 0x9d, 0x39, 0x68, 0xea, 0x86, 0xd3, 0x52, 0xb7, + 0x08, 0x46, 0xa3, 0x97, 0x8d, 0x4e, 0xc7, 0x3f, 0x44, 0x67, 0xd8, 0x75, 0x6e, 0x28, 0x8f, 0x81, + 0x91, 0xd0, 0x8f, 0x7a, 0xcd, 0xee, 0xd2, 0x7f, 0xaa, 0xa0, 0xf0, 0xd4, 0x8f, 0xba, 0x5b, 0xcd, + 0xe6, 0xd3, 0x93, 0x8e, 0x1f, 0xc1, 0xcb, 0x60, 0x32, 0xe8, 0xe0, 0x5e, 0xf3, 0x9a, 0xb5, 0x46, + 0xbb, 0xbb, 0xb1, 0x4e, 0x12, 0x70, 0xc6, 0x9d, 0xe0, 0xd6, 0x1d, 0x6c, 0xd4, 0x61, 0x8e, 0x4d, + 0xf6, 0x65, 0x2a, 0x30, 0xc7, 0x86, 0x57, 0xc0, 0x94, 0x80, 0xf5, 0x28, 0x1d, 0xde, 0xd5, 0x84, + 0x2b, 0x56, 0x1f, 0x10, 0x6b, 0x02, 0xe8, 0xd8, 0x64, 0x57, 0xc3, 0x2a, 0x50, 0x63, 0x8c, 0x28, + 0x23, 0xde, 0xde, 0x74, 0x0c, 0xdc, 0x4f, 0x32, 0x46, 0x94, 0x11, 0xd7, 0x08, 0xaa, 0x40, 0xc7, + 0x86, 0x57, 0x41, 0x51, 0x00, 0x8f, 0x1a, 0x9f, 0xf0, 0x0f, 0x37, 0xd6, 0xd1, 0xa8, 0x65, 0x94, + 0x46, 0x5d, 0x41, 0x50, 0xa5, 0xe6, 0x24, 0xd4, 0xb1, 0xd1, 0x98, 0x65, 0x94, 0x46, 0x34, 0xa8, + 0x63, 0xc3, 0xeb, 0x60, 0x3a, 0x76, 0xcf, 0x69, 0xc7, 0x2d, 0xa3, 0x34, 0xe5, 0x0a, 0x8e, 0x7d, + 0x66, 0x4f, 0x01, 0x3b, 0x36, 0x02, 0x96, 0x51, 0x2a, 0xea, 0x60, 0xc7, 0x56, 0x52, 0x7f, 0xd4, + 0x0c, 0xbc, 0x2e, 0xca, 0x5b, 0x46, 0x29, 0x17, 0xa7, 0xbe, 0x8a, 0x8d, 0xca, 0xfe, 0x0f, 0x83, + 0xde, 0x8b, 0xa6, 0x8f, 0x0a, 0x96, 0x51, 0x32, 0xe2, 0xfd, 0x3f, 0x20, 0x56, 0xb8, 0x0c, 0xc4, + 0xca, 0xda, 0x8b, 0x20, 0x68, 0xa2, 0x09, 0xcb, 0x28, 0x8d, 0xb9, 0x05, 0x6e, 0x2c, 0x07, 0x41, + 0x53, 0xcd, 0x66, 0x37, 0x6c, 0xb4, 0x8f, 0xd1, 0x24, 0xee, 0x2a, 0x29, 0x9b, 0xc4, 0xaa, 0x44, + 0xf7, 0xe2, 0xa4, 0xeb, 0x47, 0x68, 0x0a, 0xb7, 0x71, 0x1c, 0x5d, 0x19, 0x1b, 0x61, 0x0d, 0x2c, + 0x08, 0x58, 0x9b, 0xde, 0xde, 0x2d, 0x3f, 0x8a, 0xbc, 0x63, 0x1f, 0x41, 0xcb, 0x28, 0xe5, 0xd7, + 0xaf, 0x28, 0x37, 0xb6, 0xdc, 0xa2, 0x2b, 0xbb, 0x04, 0xff, 0x98, 0xc2, 0xdd, 0x39, 0xce, 0xa3, + 0x98, 0xe1, 0x01, 0x40, 0x71, 0x96, 0x82, 0xd0, 0x6f, 0x1c, 0xb7, 0x85, 0x87, 0x19, 0xe2, 0xe1, + 0x9c, 0xe2, 0xa1, 0x4a, 0x31, 0x9c, 0x75, 0x5e, 0x24, 0x53, 0xb1, 0xc3, 0xf7, 0xc0, 0xac, 0x1e, + 0xb7, 0xdf, 0xee, 0xb5, 0xd0, 0x1c, 0x51, 0xa3, 0x4b, 0xa7, 0x05, 0x5d, 0x69, 0xf7, 0x5a, 0x2e, + 0x54, 0x23, 0xc6, 0x36, 0xf8, 0x2e, 0x98, 0x4b, 0x84, 0x4b, 0x88, 0xe7, 0x09, 0x31, 0x4a, 0x8b, + 0x95, 0x90, 0xcd, 0x68, 0x81, 0x12, 0x36, 0x47, 0x62, 0xa3, 0xd5, 0xaa, 0x75, 0x1a, 0x7e, 0xdd, + 0x47, 0x08, 0xd7, 0xac, 0x9c, 0x1b, 0xcb, 0xc5, 0xeb, 0x68, 0xdd, 0x9e, 0xe0, 0xcb, 0xf0, 0x8a, + 0xd4, 0x0a, 0xf5, 0x20, 0x3c, 0x44, 0x67, 0x19, 0xde, 0x88, 0xdb, 0xe1, 0x7e, 0x10, 0x1e, 0xc2, + 0x2a, 0x98, 0x0e, 0xfd, 0x7a, 0x2f, 0x8c, 0x1a, 0xaf, 0x7c, 0x91, 0xd6, 0x73, 0x24, 0xad, 0x67, + 0x33, 0x73, 0xe0, 0x16, 0xc5, 0x1a, 0x9e, 0xce, 0xcb, 0x60, 0x32, 0xf4, 0x3b, 0xbe, 0x87, 0xf3, + 0x48, 0x6f, 0xe6, 0x0b, 0x96, 0x89, 0xd5, 0x86, 0x5b, 0x85, 0xda, 0xc8, 0x30, 0xc7, 0x46, 0x96, + 0x65, 0x62, 0xb5, 0x91, 0x60, 0x54, 0x1b, 0x04, 0x8c, 0xa9, 0xcd, 0x45, 0xcb, 0xc4, 0x6a, 0xc3, + 0xcd, 0xb1, 0xda, 0x28, 0x40, 0xc7, 0x46, 0x4b, 0x96, 0x89, 0xd5, 0x46, 0x06, 0x6a, 0x8c, 0x4c, + 0x6d, 0x96, 0x2d, 0x13, 0xab, 0x0d, 0x37, 0xef, 0x27, 0x19, 0x99, 0xda, 0x5c, 0xb2, 0x4c, 0xac, + 0x36, 0x32, 0x90, 0xaa, 0x8d, 0x00, 0x72, 0x59, 0xb8, 0x6c, 0x99, 0x58, 0x6d, 0xb8, 0x5d, 0x52, + 0x1b, 0x15, 0xea, 0xd8, 0xe8, 0xff, 0x2c, 0x13, 0xab, 0x8d, 0x02, 0xa5, 0x6a, 0x13, 0xbb, 0xe7, + 0xb4, 0x57, 0x2c, 0x13, 0xab, 0x8d, 0x08, 0x40, 0x52, 0x1b, 0x0d, 0xec, 0xd8, 0xa8, 0x64, 0x99, + 0x58, 0x6d, 0x54, 0x30, 0x55, 0x9b, 0x38, 0x08, 0xa2, 0x36, 0x57, 0x2d, 0x13, 0xab, 0x8d, 0x08, + 0x81, 0xab, 0x8d, 0x80, 0x31, 0xb5, 0xb9, 0x66, 0x99, 0x58, 0x6d, 0xb8, 0x39, 0x56, 0x1b, 0x01, + 0x24, 0x6a, 0x73, 0xdd, 0x32, 0xb1, 0xda, 0x70, 0x23, 0x57, 0x9b, 0x38, 0x42, 0xaa, 0x36, 0x6f, + 0x5a, 0x26, 0x56, 0x1b, 0x11, 0x9f, 0x50, 0x9b, 0x98, 0x8d, 0xa8, 0xcd, 0x5b, 0x96, 0x89, 0xd5, + 0x46, 0xd0, 0x71, 0xb5, 0x11, 0x30, 0x4d, 0x6d, 0x56, 0x2d, 0xf3, 0xb5, 0xd4, 0x86, 0xf3, 0x24, + 0xd4, 0x26, 0xce, 0x92, 0xa6, 0x36, 0x6b, 0xc4, 0x43, 0x7f, 0xb5, 0x11, 0xc9, 0x4c, 0xa8, 0x8d, + 0x1e, 0x37, 0x11, 0x85, 0x0d, 0xcb, 0x1c, 0x5c, 0x6d, 0xd4, 0x88, 0xb9, 0xda, 0x24, 0xc2, 0x25, + 0xc4, 0x36, 0x21, 0xee, 0xa3, 0x36, 0x5a, 0xa0, 0x5c, 0x6d, 0xb4, 0x6a, 0x31, 0xb5, 0x71, 0x70, + 0xcd, 0xa8, 0xda, 0xa8, 0x75, 0x13, 0x6a, 0x23, 0xd6, 0x11, 0xb5, 0xb9, 0xc5, 0xf0, 0x46, 0xdc, + 0x0e, 0x44, 0x6d, 0x9e, 0x82, 0xa9, 0x96, 0xd7, 0xa1, 0x02, 0xc1, 0x64, 0x62, 0x93, 0x24, 0xf5, + 0xcd, 0xec, 0x0c, 0x3c, 0xf6, 0x3a, 0x44, 0x3b, 0xc8, 0x47, 0xa5, 0xdd, 0x0d, 0x4f, 0xdc, 0x89, + 0x96, 0x6c, 0x93, 0x58, 0x1d, 0x9b, 0xa9, 0xca, 0xed, 0xc1, 0x58, 0x1d, 0x9b, 0x7c, 0x28, 0xac, + 0xcc, 0x06, 0x9f, 0x83, 0x69, 0xcc, 0x4a, 0xe5, 0x87, 0xab, 0xd0, 0x1d, 0xc2, 0xbb, 0xd2, 0x97, + 0x97, 0x4a, 0x13, 0xfd, 0xa4, 0xcc, 0x38, 0x3c, 0xd9, 0x2a, 0x73, 0x3b, 0x36, 0x17, 0xae, 0xb7, + 0x07, 0xe4, 0x76, 0x6c, 0xfa, 0xa9, 0x72, 0x73, 0x2b, 0xe7, 0xa6, 0x22, 0xc7, 0xb5, 0xee, 0xff, + 0x07, 0xe0, 0xa6, 0x02, 0xb8, 0xaf, 0xc5, 0x2d, 0x5b, 0x65, 0x6e, 0xc7, 0xe6, 0xf2, 0xf8, 0xce, + 0x80, 0xdc, 0x8e, 0xbd, 0xaf, 0xc5, 0x2d, 0x5b, 0xe1, 0xc7, 0xc1, 0x0c, 0xe6, 0x66, 0xda, 0x26, + 0x24, 0xf5, 0x2e, 0x61, 0x5f, 0xed, 0xcb, 0xce, 0x74, 0x96, 0xfd, 0xa0, 0xfc, 0x38, 0x50, 0xd5, + 0xae, 0x78, 0x70, 0x6c, 0xa1, 0xc4, 0x1f, 0x19, 0xd4, 0x83, 0x63, 0xb3, 0x1f, 0x9a, 0x07, 0x61, + 0x87, 0x47, 0x60, 0x8e, 0xe4, 0x87, 0x6f, 0x42, 0x28, 0xf8, 0x3d, 0xe2, 0x63, 0xbd, 0x7f, 0x8e, + 0x18, 0x98, 0xff, 0xa4, 0x5e, 0x70, 0xc8, 0xfa, 0x15, 0xd5, 0x0f, 0xae, 0x04, 0xdf, 0xcb, 0xd6, + 0xc0, 0x7e, 0x1c, 0x9b, 0xff, 0xd4, 0xfd, 0xc4, 0x57, 0xd4, 0xfb, 0x95, 0x1e, 0x1a, 0xe5, 0x41, + 0xef, 0x57, 0x72, 0x9c, 0x68, 0xf7, 0x2b, 0x3d, 0x62, 0x9e, 0x81, 0x62, 0xcc, 0xca, 0xce, 0x98, + 0xfb, 0x84, 0xf6, 0xad, 0xd3, 0x69, 0xe9, 0xe9, 0x43, 0x79, 0x27, 0x5b, 0x8a, 0x11, 0xee, 0x02, + 0xec, 0x89, 0x9c, 0x46, 0xf4, 0x48, 0x7a, 0x40, 0x58, 0xaf, 0xf5, 0x65, 0xc5, 0xe7, 0x14, 0xfe, + 0x9f, 0x52, 0xe6, 0x5b, 0xb1, 0x45, 0xb4, 0x3b, 0x95, 0x42, 0x76, 0x7e, 0x55, 0x06, 0x69, 0x77, + 0x02, 0xa5, 0x9f, 0x52, 0xbb, 0x4b, 0x56, 0x9e, 0x04, 0xc6, 0x4d, 0x8f, 0xbc, 0xea, 0x00, 0x49, + 0xa0, 0xcb, 0xc9, 0x69, 0x18, 0x27, 0x41, 0x32, 0xc2, 0x0e, 0x38, 0x2b, 0x11, 0x6b, 0x87, 0xe4, + 0x43, 0xe2, 0xe1, 0xe6, 0x00, 0x1e, 0x94, 0x63, 0x91, 0x7a, 0x9a, 0x6f, 0xa5, 0x5e, 0x84, 0x11, + 0x58, 0x94, 0x3c, 0xea, 0xa7, 0xe6, 0x36, 0x71, 0xe9, 0x0c, 0xe0, 0x52, 0x3d, 0x33, 0xa9, 0xcf, + 0x85, 0x56, 0xfa, 0x55, 0x78, 0x0c, 0xe6, 0x93, 0xdb, 0x24, 0x47, 0xdf, 0xce, 0x20, 0xf7, 0x80, + 0xb4, 0x0d, 0x7c, 0xf4, 0x49, 0xf7, 0x80, 0x76, 0x05, 0xbe, 0x0f, 0x16, 0x52, 0x76, 0x47, 0x3c, + 0x3d, 0x22, 0x9e, 0x36, 0x06, 0xdf, 0x5a, 0xec, 0x6a, 0xb6, 0x95, 0x72, 0x09, 0x2e, 0x83, 0x42, + 0xd0, 0xf6, 0x83, 0x23, 0x7e, 0xdc, 0x04, 0xf8, 0x11, 0x7b, 0x7b, 0xc8, 0xcd, 0x13, 0x2b, 0x3b, + 0x3c, 0x3e, 0x06, 0x66, 0x29, 0x48, 0xab, 0x6d, 0xe7, 0xb5, 0x1e, 0xb7, 0xb6, 0x87, 0x5c, 0x48, + 0x68, 0xd4, 0x5a, 0x8a, 0x08, 0x58, 0xb7, 0x7f, 0xc0, 0x27, 0x12, 0xc4, 0xca, 0x7a, 0xf7, 0x22, + 0xa0, 0x5f, 0x59, 0xdb, 0x86, 0x6c, 0xbc, 0x01, 0x88, 0x91, 0x76, 0xe1, 0x05, 0x00, 0x18, 0x04, + 0xdf, 0x87, 0x11, 0x7e, 0x10, 0xdd, 0x1e, 0x72, 0xc7, 0x29, 0x02, 0xdf, 0x5b, 0xca, 0x56, 0x1d, + 0x1b, 0x75, 0x2d, 0xa3, 0x34, 0xac, 0x6c, 0xd5, 0xb1, 0x63, 0x47, 0x54, 0x7b, 0x7a, 0xf8, 0xf1, + 0x58, 0x38, 0xa2, 0x62, 0x22, 0x78, 0x98, 0x90, 0xbc, 0xc2, 0x8f, 0xc6, 0x82, 0x87, 0x09, 0x43, + 0x85, 0x47, 0x43, 0xca, 0xf6, 0xe1, 0xe0, 0x8f, 0x78, 0x22, 0x66, 0x52, 0x9e, 0x3d, 0xe9, 0x69, + 0x8c, 0x88, 0x0c, 0x9b, 0xa6, 0xa1, 0x5f, 0x19, 0x24, 0xf7, 0x8b, 0x2b, 0x74, 0xdc, 0xb6, 0xc2, + 0xe7, 0x3c, 0x2b, 0x78, 0xab, 0xef, 0x79, 0xcd, 0x9e, 0x1f, 0x3f, 0xa6, 0x61, 0xd3, 0x33, 0xba, + 0x0e, 0xba, 0x60, 0x5e, 0x9d, 0xd1, 0x08, 0xc6, 0x5f, 0x1b, 0xec, 0xd1, 0x56, 0x67, 0x24, 0x7a, + 0x47, 0x29, 0x67, 0x95, 0x49, 0x4e, 0x06, 0xa7, 0x63, 0x0b, 0xce, 0xdf, 0xf4, 0xe1, 0x74, 0xec, + 0x24, 0xa7, 0x63, 0x73, 0xce, 0x03, 0xe9, 0x21, 0xbf, 0xa7, 0x06, 0xfa, 0x5b, 0x4a, 0x7a, 0x3e, + 0x41, 0x7a, 0x20, 0x45, 0x3a, 0xa7, 0x0e, 0x89, 0xb2, 0x68, 0xa5, 0x58, 0x7f, 0xd7, 0x8f, 0x96, + 0x07, 0x3b, 0xa7, 0x8e, 0x94, 0xd2, 0x32, 0x40, 0x1a, 0x47, 0xb0, 0xfe, 0x3e, 0x2b, 0x03, 0xa4, + 0x97, 0xb4, 0x0c, 0x10, 0x5b, 0x5a, 0xa8, 0xb4, 0xd3, 0x04, 0xe9, 0x1f, 0xb2, 0x42, 0xa5, 0xcd, + 0xa7, 0x85, 0x4a, 0x8d, 0x69, 0xb4, 0x4c, 0x61, 0x38, 0xed, 0x1f, 0xb3, 0x68, 0xe9, 0x4d, 0xa8, + 0xd1, 0x52, 0x63, 0x5a, 0x06, 0xc8, 0x3d, 0x2a, 0x58, 0xff, 0x94, 0x95, 0x01, 0x72, 0xdb, 0x6a, + 0x19, 0x20, 0x36, 0xce, 0xb9, 0x27, 0x3d, 0x1c, 0x28, 0xcd, 0xff, 0x67, 0x83, 0xc8, 0x60, 0xdf, + 0xe6, 0x97, 0x1f, 0x0a, 0xa5, 0x20, 0xd5, 0x91, 0x81, 0x60, 0xfc, 0x8b, 0xc1, 0x9e, 0xb4, 0xfa, + 0x35, 0xbf, 0x32, 0x58, 0xc8, 0xe0, 0x94, 0x1a, 0xea, 0xaf, 0x7d, 0x38, 0x45, 0xf3, 0x2b, 0x53, + 0x08, 0xa9, 0x46, 0xda, 0x30, 0x42, 0x90, 0xfe, 0x8d, 0x92, 0x9e, 0xd2, 0xfc, 0xea, 0xcc, 0x22, + 0x8b, 0x56, 0x8a, 0xf5, 0xef, 0xfd, 0x68, 0x45, 0xf3, 0xab, 0x13, 0x8e, 0xb4, 0x0c, 0xa8, 0xcd, + 0xff, 0x8f, 0xac, 0x0c, 0xc8, 0xcd, 0xaf, 0x0c, 0x03, 0xd2, 0x42, 0xd5, 0x9a, 0xff, 0x9f, 0x59, + 0xa1, 0x2a, 0xcd, 0xaf, 0x8e, 0x0e, 0xd2, 0x68, 0xb5, 0xe6, 0xff, 0x57, 0x16, 0xad, 0xd2, 0xfc, + 0xea, 0xb3, 0x68, 0x5a, 0x06, 0xd4, 0xe6, 0xff, 0x77, 0x56, 0x06, 0xe4, 0xe6, 0x57, 0x06, 0x0e, + 0x9c, 0xf3, 0xa1, 0x34, 0xd7, 0xe5, 0xef, 0x70, 0xd0, 0x77, 0x73, 0x6c, 0x4e, 0x96, 0xd8, 0x3b, + 0x43, 0xc4, 0x33, 0x5f, 0x6e, 0x81, 0x8f, 0x80, 0x18, 0x1a, 0xd6, 0xc4, 0xcb, 0x1a, 0xf4, 0xbd, + 0x5c, 0xc6, 0xf9, 0xf1, 0x94, 0x43, 0x5c, 0xe1, 0x5f, 0x98, 0xe0, 0x47, 0xc1, 0x8c, 0x34, 0xc4, + 0xe6, 0x2f, 0x8e, 0xd0, 0xf7, 0xb3, 0xc8, 0xaa, 0x18, 0xf3, 0xd8, 0x8b, 0x5e, 0xc6, 0x64, 0xc2, + 0x04, 0xb7, 0xd4, 0xb9, 0x70, 0xaf, 0xde, 0x45, 0x3f, 0xa0, 0x44, 0x0b, 0x69, 0x45, 0xe8, 0xd5, + 0xbb, 0xca, 0xc4, 0xb8, 0x57, 0xef, 0xc2, 0x4d, 0x20, 0x66, 0x8b, 0x35, 0xaf, 0x7d, 0x82, 0x7e, + 0x48, 0xd7, 0xcf, 0x26, 0xd6, 0x6f, 0xb5, 0x4f, 0xdc, 0x3c, 0x87, 0x6e, 0xb5, 0x4f, 0xe0, 0x5d, + 0x69, 0xd6, 0xfc, 0x0a, 0x97, 0x01, 0xfd, 0x88, 0xae, 0x9d, 0x4f, 0xac, 0xa5, 0x55, 0x12, 0xd3, + 0x4d, 0xf2, 0x15, 0x97, 0x27, 0x6e, 0x50, 0x5e, 0x9e, 0x1f, 0xe7, 0x48, 0xb5, 0xfb, 0x95, 0x47, + 0xf4, 0xa5, 0x54, 0x1e, 0x41, 0x14, 0x97, 0xe7, 0x27, 0xb9, 0x0c, 0x85, 0x93, 0xca, 0xc3, 0x97, + 0xc5, 0xe5, 0x91, 0xb9, 0x48, 0x79, 0x48, 0x75, 0x7e, 0x9a, 0xc5, 0x25, 0x55, 0x27, 0x1e, 0x0a, + 0xb2, 0x55, 0xb8, 0x3a, 0xf2, 0xad, 0x82, 0xab, 0xf3, 0x4b, 0x4a, 0x94, 0x5d, 0x1d, 0xe9, 0xee, + 0x60, 0xd5, 0x11, 0x14, 0xb8, 0x3a, 0x3f, 0xa3, 0xeb, 0x33, 0xaa, 0xc3, 0xa1, 0xac, 0x3a, 0x62, + 0x25, 0xad, 0xce, 0xcf, 0xe9, 0xda, 0xcc, 0xea, 0x70, 0x38, 0xad, 0xce, 0x05, 0x00, 0xc8, 0xfe, + 0xdb, 0x5e, 0xcb, 0x5f, 0x43, 0x9f, 0x36, 0xc9, 0x6b, 0x28, 0xc9, 0x04, 0x2d, 0x90, 0xa7, 0xfd, + 0x8b, 0xbf, 0xae, 0xa3, 0xcf, 0xc8, 0x88, 0x5d, 0x6c, 0x82, 0x17, 0x41, 0xa1, 0x16, 0x43, 0x36, + 0xd0, 0x67, 0x19, 0xa4, 0xca, 0x21, 0x1b, 0x70, 0x09, 0x4c, 0x50, 0x04, 0x81, 0xd8, 0x35, 0xf4, + 0x39, 0x9d, 0x86, 0xfc, 0x3d, 0x49, 0xbe, 0xad, 0x62, 0xc8, 0x4d, 0xf4, 0x79, 0x8a, 0x90, 0x6d, + 0x70, 0x99, 0xd3, 0xac, 0x12, 0x1e, 0x07, 0x7d, 0x41, 0x01, 0x61, 0x1e, 0x47, 0xec, 0x08, 0x7f, + 0xbb, 0x85, 0xbe, 0xa8, 0x3b, 0xba, 0x85, 0x01, 0x22, 0xb4, 0x4d, 0xf4, 0x25, 0x3d, 0xda, 0xcd, + 0x78, 0xcb, 0xf8, 0xeb, 0x6d, 0xf4, 0x65, 0x9d, 0xe2, 0x36, 0x5c, 0x02, 0x85, 0xaa, 0x40, 0xac, + 0xad, 0xa2, 0xaf, 0xb0, 0x38, 0x04, 0xc9, 0xda, 0x2a, 0xc1, 0xec, 0x54, 0xde, 0x7d, 0x50, 0xdb, + 0xdd, 0x7a, 0x5c, 0x59, 0x5b, 0x43, 0x5f, 0xe5, 0x18, 0x6c, 0xa4, 0xb6, 0x18, 0x43, 0x72, 0xbd, + 0x8e, 0xbe, 0xa6, 0x60, 0x88, 0x0d, 0x5e, 0x02, 0x93, 0x35, 0x29, 0xbf, 0x6b, 0x1b, 0xe8, 0xeb, + 0x09, 0x6f, 0x1b, 0x14, 0x55, 0x8d, 0x51, 0x36, 0xfa, 0x46, 0x02, 0x65, 0xc7, 0x09, 0xa4, 0xa0, + 0x9b, 0xe8, 0x9b, 0x72, 0x02, 0x09, 0x48, 0xca, 0x32, 0xdd, 0x9d, 0x83, 0xbe, 0x95, 0x00, 0x39, + 0xd8, 0x9f, 0x14, 0xd3, 0xad, 0x5a, 0x0d, 0x7d, 0x3b, 0x81, 0xba, 0x85, 0x51, 0x52, 0x4c, 0x9b, + 0xb5, 0x1a, 0xfa, 0x4e, 0x22, 0xaa, 0xcd, 0xc5, 0xe7, 0x60, 0x42, 0x7d, 0xd0, 0x29, 0x00, 0xc3, + 0x63, 0x6f, 0x44, 0x0d, 0x0f, 0xbe, 0x0d, 0xf2, 0xf5, 0x40, 0xbc, 0xd4, 0x40, 0xb9, 0xd3, 0x5e, + 0x80, 0xc8, 0xe8, 0xc5, 0x7b, 0x00, 0x26, 0x87, 0x94, 0xb0, 0x08, 0xcc, 0x97, 0xfe, 0x09, 0x73, + 0x81, 0x7f, 0x85, 0xb3, 0xe0, 0x0c, 0xbd, 0x7d, 0x72, 0xc4, 0x46, 0xbf, 0xdc, 0xc9, 0x6d, 0x1a, + 0x31, 0x83, 0x3c, 0x90, 0x94, 0x19, 0xcc, 0x14, 0x06, 0x53, 0x66, 0x28, 0x83, 0xd9, 0xb4, 0xd1, + 0xa3, 0xcc, 0x31, 0x91, 0xc2, 0x31, 0x91, 0xce, 0xa1, 0x8c, 0x18, 0x65, 0x8e, 0xe1, 0x14, 0x8e, + 0xe1, 0x24, 0x47, 0x62, 0x94, 0x28, 0x73, 0x4c, 0xa7, 0x70, 0x4c, 0xa7, 0x73, 0x28, 0x23, 0x43, + 0x99, 0x03, 0xa6, 0x70, 0x40, 0x99, 0xe3, 0x01, 0x98, 0x4f, 0x1f, 0x0c, 0xca, 0x2c, 0xa3, 0x29, + 0x2c, 0xa3, 0x19, 0x2c, 0xea, 0xf0, 0x4f, 0x66, 0x19, 0x49, 0x61, 0x19, 0x91, 0x59, 0xaa, 0x00, + 0x65, 0x8d, 0xf7, 0x64, 0x9e, 0xa9, 0x14, 0x9e, 0xa9, 0x2c, 0x1e, 0x6d, 0x7c, 0x27, 0xf3, 0x14, + 0x53, 0x78, 0x8a, 0xa9, 0xdd, 0x26, 0x0f, 0xe9, 0x4e, 0xeb, 0xd7, 0x9c, 0xcc, 0xb0, 0x05, 0x66, + 0x52, 0xe6, 0x71, 0xa7, 0x51, 0x18, 0x32, 0xc5, 0x5d, 0x50, 0xd4, 0x87, 0x6f, 0xf2, 0xfa, 0xb1, + 0x94, 0xf5, 0x63, 0x29, 0x4d, 0xa2, 0x0f, 0xda, 0x64, 0x8e, 0xf1, 0x14, 0x8e, 0xf1, 0xe4, 0x36, + 0xf4, 0x89, 0xda, 0x69, 0x14, 0x05, 0x99, 0x22, 0x04, 0xe7, 0xfa, 0x8c, 0xcc, 0x52, 0xa8, 0xde, + 0x91, 0xa9, 0x5e, 0xe3, 0x7d, 0x95, 0xe4, 0xf3, 0x18, 0x9c, 0xef, 0x37, 0x33, 0x4b, 0x71, 0xba, + 0xa6, 0x3a, 0xed, 0xfb, 0x0a, 0x4b, 0x72, 0xd4, 0xa4, 0x0d, 0x97, 0x36, 0x2b, 0x4b, 0x71, 0x72, + 0x47, 0x76, 0x32, 0xe8, 0x4b, 0x2d, 0xc9, 0x9b, 0x07, 0xce, 0x66, 0xce, 0xcb, 0x52, 0xdc, 0xad, + 0xa8, 0xee, 0xb2, 0x5f, 0x75, 0xc5, 0x2e, 0x96, 0x6e, 0x03, 0x20, 0x4d, 0xf6, 0x46, 0x81, 0x59, + 0xdd, 0xdb, 0x2b, 0x0e, 0xe1, 0x5f, 0xca, 0x5b, 0x6e, 0xd1, 0xa0, 0xbf, 0x3c, 0x2f, 0xe6, 0xb0, + 0xbb, 0xdd, 0xca, 0xc3, 0xe2, 0x7f, 0xf9, 0x7f, 0x46, 0x79, 0x42, 0x8c, 0xa2, 0xf0, 0xa9, 0xb2, + 0xf4, 0x06, 0x98, 0xd4, 0x06, 0x92, 0x05, 0x60, 0xd4, 0xf9, 0x81, 0x52, 0xbf, 0x76, 0x13, 0x80, + 0xf8, 0xdf, 0x30, 0xc1, 0x29, 0x90, 0x3f, 0xd8, 0xdd, 0x7f, 0x52, 0xb9, 0xbf, 0x53, 0xdd, 0xa9, + 0x3c, 0x28, 0x0e, 0xc1, 0x02, 0x18, 0x7b, 0xe2, 0xee, 0x3d, 0xdd, 0x2b, 0x1f, 0x54, 0x8b, 0x06, + 0x1c, 0x03, 0xc3, 0x8f, 0xf6, 0xf7, 0x76, 0x8b, 0xb9, 0x6b, 0xf7, 0x40, 0x5e, 0x9e, 0x07, 0x4e, + 0x81, 0x7c, 0x75, 0xcf, 0xad, 0xec, 0x3c, 0xdc, 0xad, 0xd1, 0x48, 0x25, 0x03, 0x8d, 0x58, 0x31, + 0x3c, 0x2f, 0xe6, 0xca, 0x17, 0xc1, 0x85, 0x7a, 0xd0, 0x4a, 0xfc, 0x61, 0x26, 0x25, 0xe7, 0xc5, + 0x08, 0xb1, 0x6e, 0xfc, 0x2f, 0x00, 0x00, 0xff, 0xff, 0x33, 0xc2, 0x0c, 0xb6, 0xeb, 0x26, 0x00, + 0x00, +} diff --git a/vendor/github.com/golang/protobuf/_conformance/conformance_proto/conformance.proto b/vendor/github.com/golang/protobuf/_conformance/conformance_proto/conformance.proto new file mode 100644 index 00000000..95a8fd13 --- /dev/null +++ b/vendor/github.com/golang/protobuf/_conformance/conformance_proto/conformance.proto @@ -0,0 +1,285 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// 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 +// OWNER 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. + +syntax = "proto3"; +package conformance; +option java_package = "com.google.protobuf.conformance"; + +import "google/protobuf/any.proto"; +import "google/protobuf/duration.proto"; +import "google/protobuf/field_mask.proto"; +import "google/protobuf/struct.proto"; +import "google/protobuf/timestamp.proto"; +import "google/protobuf/wrappers.proto"; + +// This defines the conformance testing protocol. This protocol exists between +// the conformance test suite itself and the code being tested. For each test, +// the suite will send a ConformanceRequest message and expect a +// ConformanceResponse message. +// +// You can either run the tests in two different ways: +// +// 1. in-process (using the interface in conformance_test.h). +// +// 2. as a sub-process communicating over a pipe. Information about how to +// do this is in conformance_test_runner.cc. +// +// Pros/cons of the two approaches: +// +// - running as a sub-process is much simpler for languages other than C/C++. +// +// - running as a sub-process may be more tricky in unusual environments like +// iOS apps, where fork/stdin/stdout are not available. + +enum WireFormat { + UNSPECIFIED = 0; + PROTOBUF = 1; + JSON = 2; +} + +// Represents a single test case's input. The testee should: +// +// 1. parse this proto (which should always succeed) +// 2. parse the protobuf or JSON payload in "payload" (which may fail) +// 3. if the parse succeeded, serialize the message in the requested format. +message ConformanceRequest { + // The payload (whether protobuf of JSON) is always for a TestAllTypes proto + // (see below). + oneof payload { + bytes protobuf_payload = 1; + string json_payload = 2; + } + + // Which format should the testee serialize its message to? + WireFormat requested_output_format = 3; +} + +// Represents a single test case's output. +message ConformanceResponse { + oneof result { + // This string should be set to indicate parsing failed. The string can + // provide more information about the parse error if it is available. + // + // Setting this string does not necessarily mean the testee failed the + // test. Some of the test cases are intentionally invalid input. + string parse_error = 1; + + // If the input was successfully parsed but errors occurred when + // serializing it to the requested output format, set the error message in + // this field. + string serialize_error = 6; + + // This should be set if some other error occurred. This will always + // indicate that the test failed. The string can provide more information + // about the failure. + string runtime_error = 2; + + // If the input was successfully parsed and the requested output was + // protobuf, serialize it to protobuf and set it in this field. + bytes protobuf_payload = 3; + + // If the input was successfully parsed and the requested output was JSON, + // serialize to JSON and set it in this field. + string json_payload = 4; + + // For when the testee skipped the test, likely because a certain feature + // wasn't supported, like JSON input/output. + string skipped = 5; + } +} + +// This proto includes every type of field in both singular and repeated +// forms. +message TestAllTypes { + message NestedMessage { + int32 a = 1; + TestAllTypes corecursive = 2; + } + + enum NestedEnum { + FOO = 0; + BAR = 1; + BAZ = 2; + NEG = -1; // Intentionally negative. + } + + // Singular + int32 optional_int32 = 1; + int64 optional_int64 = 2; + uint32 optional_uint32 = 3; + uint64 optional_uint64 = 4; + sint32 optional_sint32 = 5; + sint64 optional_sint64 = 6; + fixed32 optional_fixed32 = 7; + fixed64 optional_fixed64 = 8; + sfixed32 optional_sfixed32 = 9; + sfixed64 optional_sfixed64 = 10; + float optional_float = 11; + double optional_double = 12; + bool optional_bool = 13; + string optional_string = 14; + bytes optional_bytes = 15; + + NestedMessage optional_nested_message = 18; + ForeignMessage optional_foreign_message = 19; + + NestedEnum optional_nested_enum = 21; + ForeignEnum optional_foreign_enum = 22; + + string optional_string_piece = 24 [ctype=STRING_PIECE]; + string optional_cord = 25 [ctype=CORD]; + + TestAllTypes recursive_message = 27; + + // Repeated + repeated int32 repeated_int32 = 31; + repeated int64 repeated_int64 = 32; + repeated uint32 repeated_uint32 = 33; + repeated uint64 repeated_uint64 = 34; + repeated sint32 repeated_sint32 = 35; + repeated sint64 repeated_sint64 = 36; + repeated fixed32 repeated_fixed32 = 37; + repeated fixed64 repeated_fixed64 = 38; + repeated sfixed32 repeated_sfixed32 = 39; + repeated sfixed64 repeated_sfixed64 = 40; + repeated float repeated_float = 41; + repeated double repeated_double = 42; + repeated bool repeated_bool = 43; + repeated string repeated_string = 44; + repeated bytes repeated_bytes = 45; + + repeated NestedMessage repeated_nested_message = 48; + repeated ForeignMessage repeated_foreign_message = 49; + + repeated NestedEnum repeated_nested_enum = 51; + repeated ForeignEnum repeated_foreign_enum = 52; + + repeated string repeated_string_piece = 54 [ctype=STRING_PIECE]; + repeated string repeated_cord = 55 [ctype=CORD]; + + // Map + map < int32, int32> map_int32_int32 = 56; + map < int64, int64> map_int64_int64 = 57; + map < uint32, uint32> map_uint32_uint32 = 58; + map < uint64, uint64> map_uint64_uint64 = 59; + map < sint32, sint32> map_sint32_sint32 = 60; + map < sint64, sint64> map_sint64_sint64 = 61; + map < fixed32, fixed32> map_fixed32_fixed32 = 62; + map < fixed64, fixed64> map_fixed64_fixed64 = 63; + map map_sfixed32_sfixed32 = 64; + map map_sfixed64_sfixed64 = 65; + map < int32, float> map_int32_float = 66; + map < int32, double> map_int32_double = 67; + map < bool, bool> map_bool_bool = 68; + map < string, string> map_string_string = 69; + map < string, bytes> map_string_bytes = 70; + map < string, NestedMessage> map_string_nested_message = 71; + map < string, ForeignMessage> map_string_foreign_message = 72; + map < string, NestedEnum> map_string_nested_enum = 73; + map < string, ForeignEnum> map_string_foreign_enum = 74; + + oneof oneof_field { + uint32 oneof_uint32 = 111; + NestedMessage oneof_nested_message = 112; + string oneof_string = 113; + bytes oneof_bytes = 114; + bool oneof_bool = 115; + uint64 oneof_uint64 = 116; + float oneof_float = 117; + double oneof_double = 118; + NestedEnum oneof_enum = 119; + } + + // Well-known types + google.protobuf.BoolValue optional_bool_wrapper = 201; + google.protobuf.Int32Value optional_int32_wrapper = 202; + google.protobuf.Int64Value optional_int64_wrapper = 203; + google.protobuf.UInt32Value optional_uint32_wrapper = 204; + google.protobuf.UInt64Value optional_uint64_wrapper = 205; + google.protobuf.FloatValue optional_float_wrapper = 206; + google.protobuf.DoubleValue optional_double_wrapper = 207; + google.protobuf.StringValue optional_string_wrapper = 208; + google.protobuf.BytesValue optional_bytes_wrapper = 209; + + repeated google.protobuf.BoolValue repeated_bool_wrapper = 211; + repeated google.protobuf.Int32Value repeated_int32_wrapper = 212; + repeated google.protobuf.Int64Value repeated_int64_wrapper = 213; + repeated google.protobuf.UInt32Value repeated_uint32_wrapper = 214; + repeated google.protobuf.UInt64Value repeated_uint64_wrapper = 215; + repeated google.protobuf.FloatValue repeated_float_wrapper = 216; + repeated google.protobuf.DoubleValue repeated_double_wrapper = 217; + repeated google.protobuf.StringValue repeated_string_wrapper = 218; + repeated google.protobuf.BytesValue repeated_bytes_wrapper = 219; + + google.protobuf.Duration optional_duration = 301; + google.protobuf.Timestamp optional_timestamp = 302; + google.protobuf.FieldMask optional_field_mask = 303; + google.protobuf.Struct optional_struct = 304; + google.protobuf.Any optional_any = 305; + google.protobuf.Value optional_value = 306; + + repeated google.protobuf.Duration repeated_duration = 311; + repeated google.protobuf.Timestamp repeated_timestamp = 312; + repeated google.protobuf.FieldMask repeated_fieldmask = 313; + repeated google.protobuf.Struct repeated_struct = 324; + repeated google.protobuf.Any repeated_any = 315; + repeated google.protobuf.Value repeated_value = 316; + + // Test field-name-to-JSON-name convention. + // (protobuf says names can be any valid C/C++ identifier.) + int32 fieldname1 = 401; + int32 field_name2 = 402; + int32 _field_name3 = 403; + int32 field__name4_ = 404; + int32 field0name5 = 405; + int32 field_0_name6 = 406; + int32 fieldName7 = 407; + int32 FieldName8 = 408; + int32 field_Name9 = 409; + int32 Field_Name10 = 410; + int32 FIELD_NAME11 = 411; + int32 FIELD_name12 = 412; + int32 __field_name13 = 413; + int32 __Field_name14 = 414; + int32 field__name15 = 415; + int32 field__Name16 = 416; + int32 field_name17__ = 417; + int32 Field_name18__ = 418; +} + +message ForeignMessage { + int32 c = 1; +} + +enum ForeignEnum { + FOREIGN_FOO = 0; + FOREIGN_BAR = 1; + FOREIGN_BAZ = 2; +} diff --git a/vendor/github.com/golang/protobuf/descriptor/descriptor.go b/vendor/github.com/golang/protobuf/descriptor/descriptor.go new file mode 100644 index 00000000..ac7e51bf --- /dev/null +++ b/vendor/github.com/golang/protobuf/descriptor/descriptor.go @@ -0,0 +1,93 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2016 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// 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 +// OWNER 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. + +// Package descriptor provides functions for obtaining protocol buffer +// descriptors for generated Go types. +// +// These functions cannot go in package proto because they depend on the +// generated protobuf descriptor messages, which themselves depend on proto. +package descriptor + +import ( + "bytes" + "compress/gzip" + "fmt" + "io/ioutil" + + "github.com/golang/protobuf/proto" + protobuf "github.com/golang/protobuf/protoc-gen-go/descriptor" +) + +// extractFile extracts a FileDescriptorProto from a gzip'd buffer. +func extractFile(gz []byte) (*protobuf.FileDescriptorProto, error) { + r, err := gzip.NewReader(bytes.NewReader(gz)) + if err != nil { + return nil, fmt.Errorf("failed to open gzip reader: %v", err) + } + defer r.Close() + + b, err := ioutil.ReadAll(r) + if err != nil { + return nil, fmt.Errorf("failed to uncompress descriptor: %v", err) + } + + fd := new(protobuf.FileDescriptorProto) + if err := proto.Unmarshal(b, fd); err != nil { + return nil, fmt.Errorf("malformed FileDescriptorProto: %v", err) + } + + return fd, nil +} + +// Message is a proto.Message with a method to return its descriptor. +// +// Message types generated by the protocol compiler always satisfy +// the Message interface. +type Message interface { + proto.Message + Descriptor() ([]byte, []int) +} + +// ForMessage returns a FileDescriptorProto and a DescriptorProto from within it +// describing the given message. +func ForMessage(msg Message) (fd *protobuf.FileDescriptorProto, md *protobuf.DescriptorProto) { + gz, path := msg.Descriptor() + fd, err := extractFile(gz) + if err != nil { + panic(fmt.Sprintf("invalid FileDescriptorProto for %T: %v", msg, err)) + } + + md = fd.MessageType[path[0]] + for _, i := range path[1:] { + md = md.NestedType[i] + } + return fd, md +} diff --git a/vendor/github.com/golang/protobuf/descriptor/descriptor_test.go b/vendor/github.com/golang/protobuf/descriptor/descriptor_test.go new file mode 100644 index 00000000..27b0729c --- /dev/null +++ b/vendor/github.com/golang/protobuf/descriptor/descriptor_test.go @@ -0,0 +1,32 @@ +package descriptor_test + +import ( + "fmt" + "testing" + + "github.com/golang/protobuf/descriptor" + tpb "github.com/golang/protobuf/proto/testdata" + protobuf "github.com/golang/protobuf/protoc-gen-go/descriptor" +) + +func TestMessage(t *testing.T) { + var msg *protobuf.DescriptorProto + fd, md := descriptor.ForMessage(msg) + if pkg, want := fd.GetPackage(), "google.protobuf"; pkg != want { + t.Errorf("descriptor.ForMessage(%T).GetPackage() = %q; want %q", msg, pkg, want) + } + if name, want := md.GetName(), "DescriptorProto"; name != want { + t.Fatalf("descriptor.ForMessage(%T).GetName() = %q; want %q", msg, name, want) + } +} + +func Example_Options() { + var msg *tpb.MyMessageSet + _, md := descriptor.ForMessage(msg) + if md.GetOptions().GetMessageSetWireFormat() { + fmt.Printf("%v uses option message_set_wire_format.\n", md.GetName()) + } + + // Output: + // MyMessageSet uses option message_set_wire_format. +} diff --git a/vendor/github.com/golang/protobuf/jsonpb/jsonpb.go b/vendor/github.com/golang/protobuf/jsonpb/jsonpb.go new file mode 100644 index 00000000..110ae138 --- /dev/null +++ b/vendor/github.com/golang/protobuf/jsonpb/jsonpb.go @@ -0,0 +1,1083 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2015 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// 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 +// OWNER 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. + +/* +Package jsonpb provides marshaling and unmarshaling between protocol buffers and JSON. +It follows the specification at https://developers.google.com/protocol-buffers/docs/proto3#json. + +This package produces a different output than the standard "encoding/json" package, +which does not operate correctly on protocol buffers. +*/ +package jsonpb + +import ( + "bytes" + "encoding/json" + "errors" + "fmt" + "io" + "math" + "reflect" + "sort" + "strconv" + "strings" + "time" + + "github.com/golang/protobuf/proto" + + stpb "github.com/golang/protobuf/ptypes/struct" +) + +// Marshaler is a configurable object for converting between +// protocol buffer objects and a JSON representation for them. +type Marshaler struct { + // Whether to render enum values as integers, as opposed to string values. + EnumsAsInts bool + + // Whether to render fields with zero values. + EmitDefaults bool + + // A string to indent each level by. The presence of this field will + // also cause a space to appear between the field separator and + // value, and for newlines to be appear between fields and array + // elements. + Indent string + + // Whether to use the original (.proto) name for fields. + OrigName bool + + // A custom URL resolver to use when marshaling Any messages to JSON. + // If unset, the default resolution strategy is to extract the + // fully-qualified type name from the type URL and pass that to + // proto.MessageType(string). + AnyResolver AnyResolver +} + +// AnyResolver takes a type URL, present in an Any message, and resolves it into +// an instance of the associated message. +type AnyResolver interface { + Resolve(typeUrl string) (proto.Message, error) +} + +func defaultResolveAny(typeUrl string) (proto.Message, error) { + // Only the part of typeUrl after the last slash is relevant. + mname := typeUrl + if slash := strings.LastIndex(mname, "/"); slash >= 0 { + mname = mname[slash+1:] + } + mt := proto.MessageType(mname) + if mt == nil { + return nil, fmt.Errorf("unknown message type %q", mname) + } + return reflect.New(mt.Elem()).Interface().(proto.Message), nil +} + +// JSONPBMarshaler is implemented by protobuf messages that customize the +// way they are marshaled to JSON. Messages that implement this should +// also implement JSONPBUnmarshaler so that the custom format can be +// parsed. +type JSONPBMarshaler interface { + MarshalJSONPB(*Marshaler) ([]byte, error) +} + +// JSONPBUnmarshaler is implemented by protobuf messages that customize +// the way they are unmarshaled from JSON. Messages that implement this +// should also implement JSONPBMarshaler so that the custom format can be +// produced. +type JSONPBUnmarshaler interface { + UnmarshalJSONPB(*Unmarshaler, []byte) error +} + +// Marshal marshals a protocol buffer into JSON. +func (m *Marshaler) Marshal(out io.Writer, pb proto.Message) error { + writer := &errWriter{writer: out} + return m.marshalObject(writer, pb, "", "") +} + +// MarshalToString converts a protocol buffer object to JSON string. +func (m *Marshaler) MarshalToString(pb proto.Message) (string, error) { + var buf bytes.Buffer + if err := m.Marshal(&buf, pb); err != nil { + return "", err + } + return buf.String(), nil +} + +type int32Slice []int32 + +var nonFinite = map[string]float64{ + `"NaN"`: math.NaN(), + `"Infinity"`: math.Inf(1), + `"-Infinity"`: math.Inf(-1), +} + +// For sorting extensions ids to ensure stable output. +func (s int32Slice) Len() int { return len(s) } +func (s int32Slice) Less(i, j int) bool { return s[i] < s[j] } +func (s int32Slice) Swap(i, j int) { s[i], s[j] = s[j], s[i] } + +type wkt interface { + XXX_WellKnownType() string +} + +// marshalObject writes a struct to the Writer. +func (m *Marshaler) marshalObject(out *errWriter, v proto.Message, indent, typeURL string) error { + if jsm, ok := v.(JSONPBMarshaler); ok { + b, err := jsm.MarshalJSONPB(m) + if err != nil { + return err + } + if typeURL != "" { + // we are marshaling this object to an Any type + var js map[string]*json.RawMessage + if err = json.Unmarshal(b, &js); err != nil { + return fmt.Errorf("type %T produced invalid JSON: %v", v, err) + } + turl, err := json.Marshal(typeURL) + if err != nil { + return fmt.Errorf("failed to marshal type URL %q to JSON: %v", typeURL, err) + } + js["@type"] = (*json.RawMessage)(&turl) + if b, err = json.Marshal(js); err != nil { + return err + } + } + + out.write(string(b)) + return out.err + } + + s := reflect.ValueOf(v).Elem() + + // Handle well-known types. + if wkt, ok := v.(wkt); ok { + switch wkt.XXX_WellKnownType() { + case "DoubleValue", "FloatValue", "Int64Value", "UInt64Value", + "Int32Value", "UInt32Value", "BoolValue", "StringValue", "BytesValue": + // "Wrappers use the same representation in JSON + // as the wrapped primitive type, ..." + sprop := proto.GetProperties(s.Type()) + return m.marshalValue(out, sprop.Prop[0], s.Field(0), indent) + case "Any": + // Any is a bit more involved. + return m.marshalAny(out, v, indent) + case "Duration": + // "Generated output always contains 3, 6, or 9 fractional digits, + // depending on required precision." + s, ns := s.Field(0).Int(), s.Field(1).Int() + d := time.Duration(s)*time.Second + time.Duration(ns)*time.Nanosecond + x := fmt.Sprintf("%.9f", d.Seconds()) + x = strings.TrimSuffix(x, "000") + x = strings.TrimSuffix(x, "000") + out.write(`"`) + out.write(x) + out.write(`s"`) + return out.err + case "Struct", "ListValue": + // Let marshalValue handle the `Struct.fields` map or the `ListValue.values` slice. + // TODO: pass the correct Properties if needed. + return m.marshalValue(out, &proto.Properties{}, s.Field(0), indent) + case "Timestamp": + // "RFC 3339, where generated output will always be Z-normalized + // and uses 3, 6 or 9 fractional digits." + s, ns := s.Field(0).Int(), s.Field(1).Int() + t := time.Unix(s, ns).UTC() + // time.RFC3339Nano isn't exactly right (we need to get 3/6/9 fractional digits). + x := t.Format("2006-01-02T15:04:05.000000000") + x = strings.TrimSuffix(x, "000") + x = strings.TrimSuffix(x, "000") + out.write(`"`) + out.write(x) + out.write(`Z"`) + return out.err + case "Value": + // Value has a single oneof. + kind := s.Field(0) + if kind.IsNil() { + // "absence of any variant indicates an error" + return errors.New("nil Value") + } + // oneof -> *T -> T -> T.F + x := kind.Elem().Elem().Field(0) + // TODO: pass the correct Properties if needed. + return m.marshalValue(out, &proto.Properties{}, x, indent) + } + } + + out.write("{") + if m.Indent != "" { + out.write("\n") + } + + firstField := true + + if typeURL != "" { + if err := m.marshalTypeURL(out, indent, typeURL); err != nil { + return err + } + firstField = false + } + + for i := 0; i < s.NumField(); i++ { + value := s.Field(i) + valueField := s.Type().Field(i) + if strings.HasPrefix(valueField.Name, "XXX_") { + continue + } + + // IsNil will panic on most value kinds. + switch value.Kind() { + case reflect.Chan, reflect.Func, reflect.Interface: + if value.IsNil() { + continue + } + } + + if !m.EmitDefaults { + switch value.Kind() { + case reflect.Bool: + if !value.Bool() { + continue + } + case reflect.Int32, reflect.Int64: + if value.Int() == 0 { + continue + } + case reflect.Uint32, reflect.Uint64: + if value.Uint() == 0 { + continue + } + case reflect.Float32, reflect.Float64: + if value.Float() == 0 { + continue + } + case reflect.String: + if value.Len() == 0 { + continue + } + case reflect.Map, reflect.Ptr, reflect.Slice: + if value.IsNil() { + continue + } + } + } + + // Oneof fields need special handling. + if valueField.Tag.Get("protobuf_oneof") != "" { + // value is an interface containing &T{real_value}. + sv := value.Elem().Elem() // interface -> *T -> T + value = sv.Field(0) + valueField = sv.Type().Field(0) + } + prop := jsonProperties(valueField, m.OrigName) + if !firstField { + m.writeSep(out) + } + if err := m.marshalField(out, prop, value, indent); err != nil { + return err + } + firstField = false + } + + // Handle proto2 extensions. + if ep, ok := v.(proto.Message); ok { + extensions := proto.RegisteredExtensions(v) + // Sort extensions for stable output. + ids := make([]int32, 0, len(extensions)) + for id, desc := range extensions { + if !proto.HasExtension(ep, desc) { + continue + } + ids = append(ids, id) + } + sort.Sort(int32Slice(ids)) + for _, id := range ids { + desc := extensions[id] + if desc == nil { + // unknown extension + continue + } + ext, extErr := proto.GetExtension(ep, desc) + if extErr != nil { + return extErr + } + value := reflect.ValueOf(ext) + var prop proto.Properties + prop.Parse(desc.Tag) + prop.JSONName = fmt.Sprintf("[%s]", desc.Name) + if !firstField { + m.writeSep(out) + } + if err := m.marshalField(out, &prop, value, indent); err != nil { + return err + } + firstField = false + } + + } + + if m.Indent != "" { + out.write("\n") + out.write(indent) + } + out.write("}") + return out.err +} + +func (m *Marshaler) writeSep(out *errWriter) { + if m.Indent != "" { + out.write(",\n") + } else { + out.write(",") + } +} + +func (m *Marshaler) marshalAny(out *errWriter, any proto.Message, indent string) error { + // "If the Any contains a value that has a special JSON mapping, + // it will be converted as follows: {"@type": xxx, "value": yyy}. + // Otherwise, the value will be converted into a JSON object, + // and the "@type" field will be inserted to indicate the actual data type." + v := reflect.ValueOf(any).Elem() + turl := v.Field(0).String() + val := v.Field(1).Bytes() + + var msg proto.Message + var err error + if m.AnyResolver != nil { + msg, err = m.AnyResolver.Resolve(turl) + } else { + msg, err = defaultResolveAny(turl) + } + if err != nil { + return err + } + + if err := proto.Unmarshal(val, msg); err != nil { + return err + } + + if _, ok := msg.(wkt); ok { + out.write("{") + if m.Indent != "" { + out.write("\n") + } + if err := m.marshalTypeURL(out, indent, turl); err != nil { + return err + } + m.writeSep(out) + if m.Indent != "" { + out.write(indent) + out.write(m.Indent) + out.write(`"value": `) + } else { + out.write(`"value":`) + } + if err := m.marshalObject(out, msg, indent+m.Indent, ""); err != nil { + return err + } + if m.Indent != "" { + out.write("\n") + out.write(indent) + } + out.write("}") + return out.err + } + + return m.marshalObject(out, msg, indent, turl) +} + +func (m *Marshaler) marshalTypeURL(out *errWriter, indent, typeURL string) error { + if m.Indent != "" { + out.write(indent) + out.write(m.Indent) + } + out.write(`"@type":`) + if m.Indent != "" { + out.write(" ") + } + b, err := json.Marshal(typeURL) + if err != nil { + return err + } + out.write(string(b)) + return out.err +} + +// marshalField writes field description and value to the Writer. +func (m *Marshaler) marshalField(out *errWriter, prop *proto.Properties, v reflect.Value, indent string) error { + if m.Indent != "" { + out.write(indent) + out.write(m.Indent) + } + out.write(`"`) + out.write(prop.JSONName) + out.write(`":`) + if m.Indent != "" { + out.write(" ") + } + if err := m.marshalValue(out, prop, v, indent); err != nil { + return err + } + return nil +} + +// marshalValue writes the value to the Writer. +func (m *Marshaler) marshalValue(out *errWriter, prop *proto.Properties, v reflect.Value, indent string) error { + var err error + v = reflect.Indirect(v) + + // Handle nil pointer + if v.Kind() == reflect.Invalid { + out.write("null") + return out.err + } + + // Handle repeated elements. + if v.Kind() == reflect.Slice && v.Type().Elem().Kind() != reflect.Uint8 { + out.write("[") + comma := "" + for i := 0; i < v.Len(); i++ { + sliceVal := v.Index(i) + out.write(comma) + if m.Indent != "" { + out.write("\n") + out.write(indent) + out.write(m.Indent) + out.write(m.Indent) + } + if err := m.marshalValue(out, prop, sliceVal, indent+m.Indent); err != nil { + return err + } + comma = "," + } + if m.Indent != "" { + out.write("\n") + out.write(indent) + out.write(m.Indent) + } + out.write("]") + return out.err + } + + // Handle well-known types. + // Most are handled up in marshalObject (because 99% are messages). + if wkt, ok := v.Interface().(wkt); ok { + switch wkt.XXX_WellKnownType() { + case "NullValue": + out.write("null") + return out.err + } + } + + // Handle enumerations. + if !m.EnumsAsInts && prop.Enum != "" { + // Unknown enum values will are stringified by the proto library as their + // value. Such values should _not_ be quoted or they will be interpreted + // as an enum string instead of their value. + enumStr := v.Interface().(fmt.Stringer).String() + var valStr string + if v.Kind() == reflect.Ptr { + valStr = strconv.Itoa(int(v.Elem().Int())) + } else { + valStr = strconv.Itoa(int(v.Int())) + } + isKnownEnum := enumStr != valStr + if isKnownEnum { + out.write(`"`) + } + out.write(enumStr) + if isKnownEnum { + out.write(`"`) + } + return out.err + } + + // Handle nested messages. + if v.Kind() == reflect.Struct { + return m.marshalObject(out, v.Addr().Interface().(proto.Message), indent+m.Indent, "") + } + + // Handle maps. + // Since Go randomizes map iteration, we sort keys for stable output. + if v.Kind() == reflect.Map { + out.write(`{`) + keys := v.MapKeys() + sort.Sort(mapKeys(keys)) + for i, k := range keys { + if i > 0 { + out.write(`,`) + } + if m.Indent != "" { + out.write("\n") + out.write(indent) + out.write(m.Indent) + out.write(m.Indent) + } + + b, err := json.Marshal(k.Interface()) + if err != nil { + return err + } + s := string(b) + + // If the JSON is not a string value, encode it again to make it one. + if !strings.HasPrefix(s, `"`) { + b, err := json.Marshal(s) + if err != nil { + return err + } + s = string(b) + } + + out.write(s) + out.write(`:`) + if m.Indent != "" { + out.write(` `) + } + + if err := m.marshalValue(out, prop, v.MapIndex(k), indent+m.Indent); err != nil { + return err + } + } + if m.Indent != "" { + out.write("\n") + out.write(indent) + out.write(m.Indent) + } + out.write(`}`) + return out.err + } + + // Handle non-finite floats, e.g. NaN, Infinity and -Infinity. + if v.Kind() == reflect.Float32 || v.Kind() == reflect.Float64 { + f := v.Float() + var sval string + switch { + case math.IsInf(f, 1): + sval = `"Infinity"` + case math.IsInf(f, -1): + sval = `"-Infinity"` + case math.IsNaN(f): + sval = `"NaN"` + } + if sval != "" { + out.write(sval) + return out.err + } + } + + // Default handling defers to the encoding/json library. + b, err := json.Marshal(v.Interface()) + if err != nil { + return err + } + needToQuote := string(b[0]) != `"` && (v.Kind() == reflect.Int64 || v.Kind() == reflect.Uint64) + if needToQuote { + out.write(`"`) + } + out.write(string(b)) + if needToQuote { + out.write(`"`) + } + return out.err +} + +// Unmarshaler is a configurable object for converting from a JSON +// representation to a protocol buffer object. +type Unmarshaler struct { + // Whether to allow messages to contain unknown fields, as opposed to + // failing to unmarshal. + AllowUnknownFields bool + + // A custom URL resolver to use when unmarshaling Any messages from JSON. + // If unset, the default resolution strategy is to extract the + // fully-qualified type name from the type URL and pass that to + // proto.MessageType(string). + AnyResolver AnyResolver +} + +// UnmarshalNext unmarshals the next protocol buffer from a JSON object stream. +// This function is lenient and will decode any options permutations of the +// related Marshaler. +func (u *Unmarshaler) UnmarshalNext(dec *json.Decoder, pb proto.Message) error { + inputValue := json.RawMessage{} + if err := dec.Decode(&inputValue); err != nil { + return err + } + return u.unmarshalValue(reflect.ValueOf(pb).Elem(), inputValue, nil) +} + +// Unmarshal unmarshals a JSON object stream into a protocol +// buffer. This function is lenient and will decode any options +// permutations of the related Marshaler. +func (u *Unmarshaler) Unmarshal(r io.Reader, pb proto.Message) error { + dec := json.NewDecoder(r) + return u.UnmarshalNext(dec, pb) +} + +// UnmarshalNext unmarshals the next protocol buffer from a JSON object stream. +// This function is lenient and will decode any options permutations of the +// related Marshaler. +func UnmarshalNext(dec *json.Decoder, pb proto.Message) error { + return new(Unmarshaler).UnmarshalNext(dec, pb) +} + +// Unmarshal unmarshals a JSON object stream into a protocol +// buffer. This function is lenient and will decode any options +// permutations of the related Marshaler. +func Unmarshal(r io.Reader, pb proto.Message) error { + return new(Unmarshaler).Unmarshal(r, pb) +} + +// UnmarshalString will populate the fields of a protocol buffer based +// on a JSON string. This function is lenient and will decode any options +// permutations of the related Marshaler. +func UnmarshalString(str string, pb proto.Message) error { + return new(Unmarshaler).Unmarshal(strings.NewReader(str), pb) +} + +// unmarshalValue converts/copies a value into the target. +// prop may be nil. +func (u *Unmarshaler) unmarshalValue(target reflect.Value, inputValue json.RawMessage, prop *proto.Properties) error { + targetType := target.Type() + + // Allocate memory for pointer fields. + if targetType.Kind() == reflect.Ptr { + // If input value is "null" and target is a pointer type, then the field should be treated as not set + // UNLESS the target is structpb.Value, in which case it should be set to structpb.NullValue. + _, isJSONPBUnmarshaler := target.Interface().(JSONPBUnmarshaler) + if string(inputValue) == "null" && targetType != reflect.TypeOf(&stpb.Value{}) && !isJSONPBUnmarshaler { + return nil + } + target.Set(reflect.New(targetType.Elem())) + + return u.unmarshalValue(target.Elem(), inputValue, prop) + } + + if jsu, ok := target.Addr().Interface().(JSONPBUnmarshaler); ok { + return jsu.UnmarshalJSONPB(u, []byte(inputValue)) + } + + // Handle well-known types that are not pointers. + if w, ok := target.Addr().Interface().(wkt); ok { + switch w.XXX_WellKnownType() { + case "DoubleValue", "FloatValue", "Int64Value", "UInt64Value", + "Int32Value", "UInt32Value", "BoolValue", "StringValue", "BytesValue": + return u.unmarshalValue(target.Field(0), inputValue, prop) + case "Any": + // Use json.RawMessage pointer type instead of value to support pre-1.8 version. + // 1.8 changed RawMessage.MarshalJSON from pointer type to value type, see + // https://github.com/golang/go/issues/14493 + var jsonFields map[string]*json.RawMessage + if err := json.Unmarshal(inputValue, &jsonFields); err != nil { + return err + } + + val, ok := jsonFields["@type"] + if !ok || val == nil { + return errors.New("Any JSON doesn't have '@type'") + } + + var turl string + if err := json.Unmarshal([]byte(*val), &turl); err != nil { + return fmt.Errorf("can't unmarshal Any's '@type': %q", *val) + } + target.Field(0).SetString(turl) + + var m proto.Message + var err error + if u.AnyResolver != nil { + m, err = u.AnyResolver.Resolve(turl) + } else { + m, err = defaultResolveAny(turl) + } + if err != nil { + return err + } + + if _, ok := m.(wkt); ok { + val, ok := jsonFields["value"] + if !ok { + return errors.New("Any JSON doesn't have 'value'") + } + + if err := u.unmarshalValue(reflect.ValueOf(m).Elem(), *val, nil); err != nil { + return fmt.Errorf("can't unmarshal Any nested proto %T: %v", m, err) + } + } else { + delete(jsonFields, "@type") + nestedProto, err := json.Marshal(jsonFields) + if err != nil { + return fmt.Errorf("can't generate JSON for Any's nested proto to be unmarshaled: %v", err) + } + + if err = u.unmarshalValue(reflect.ValueOf(m).Elem(), nestedProto, nil); err != nil { + return fmt.Errorf("can't unmarshal Any nested proto %T: %v", m, err) + } + } + + b, err := proto.Marshal(m) + if err != nil { + return fmt.Errorf("can't marshal proto %T into Any.Value: %v", m, err) + } + target.Field(1).SetBytes(b) + + return nil + case "Duration": + unq, err := strconv.Unquote(string(inputValue)) + if err != nil { + return err + } + + d, err := time.ParseDuration(unq) + if err != nil { + return fmt.Errorf("bad Duration: %v", err) + } + + ns := d.Nanoseconds() + s := ns / 1e9 + ns %= 1e9 + target.Field(0).SetInt(s) + target.Field(1).SetInt(ns) + return nil + case "Timestamp": + unq, err := strconv.Unquote(string(inputValue)) + if err != nil { + return err + } + + t, err := time.Parse(time.RFC3339Nano, unq) + if err != nil { + return fmt.Errorf("bad Timestamp: %v", err) + } + + target.Field(0).SetInt(t.Unix()) + target.Field(1).SetInt(int64(t.Nanosecond())) + return nil + case "Struct": + var m map[string]json.RawMessage + if err := json.Unmarshal(inputValue, &m); err != nil { + return fmt.Errorf("bad StructValue: %v", err) + } + + target.Field(0).Set(reflect.ValueOf(map[string]*stpb.Value{})) + for k, jv := range m { + pv := &stpb.Value{} + if err := u.unmarshalValue(reflect.ValueOf(pv).Elem(), jv, prop); err != nil { + return fmt.Errorf("bad value in StructValue for key %q: %v", k, err) + } + target.Field(0).SetMapIndex(reflect.ValueOf(k), reflect.ValueOf(pv)) + } + return nil + case "ListValue": + var s []json.RawMessage + if err := json.Unmarshal(inputValue, &s); err != nil { + return fmt.Errorf("bad ListValue: %v", err) + } + + target.Field(0).Set(reflect.ValueOf(make([]*stpb.Value, len(s), len(s)))) + for i, sv := range s { + if err := u.unmarshalValue(target.Field(0).Index(i), sv, prop); err != nil { + return err + } + } + return nil + case "Value": + ivStr := string(inputValue) + if ivStr == "null" { + target.Field(0).Set(reflect.ValueOf(&stpb.Value_NullValue{})) + } else if v, err := strconv.ParseFloat(ivStr, 0); err == nil { + target.Field(0).Set(reflect.ValueOf(&stpb.Value_NumberValue{v})) + } else if v, err := strconv.Unquote(ivStr); err == nil { + target.Field(0).Set(reflect.ValueOf(&stpb.Value_StringValue{v})) + } else if v, err := strconv.ParseBool(ivStr); err == nil { + target.Field(0).Set(reflect.ValueOf(&stpb.Value_BoolValue{v})) + } else if err := json.Unmarshal(inputValue, &[]json.RawMessage{}); err == nil { + lv := &stpb.ListValue{} + target.Field(0).Set(reflect.ValueOf(&stpb.Value_ListValue{lv})) + return u.unmarshalValue(reflect.ValueOf(lv).Elem(), inputValue, prop) + } else if err := json.Unmarshal(inputValue, &map[string]json.RawMessage{}); err == nil { + sv := &stpb.Struct{} + target.Field(0).Set(reflect.ValueOf(&stpb.Value_StructValue{sv})) + return u.unmarshalValue(reflect.ValueOf(sv).Elem(), inputValue, prop) + } else { + return fmt.Errorf("unrecognized type for Value %q", ivStr) + } + return nil + } + } + + // Handle enums, which have an underlying type of int32, + // and may appear as strings. + // The case of an enum appearing as a number is handled + // at the bottom of this function. + if inputValue[0] == '"' && prop != nil && prop.Enum != "" { + vmap := proto.EnumValueMap(prop.Enum) + // Don't need to do unquoting; valid enum names + // are from a limited character set. + s := inputValue[1 : len(inputValue)-1] + n, ok := vmap[string(s)] + if !ok { + return fmt.Errorf("unknown value %q for enum %s", s, prop.Enum) + } + if target.Kind() == reflect.Ptr { // proto2 + target.Set(reflect.New(targetType.Elem())) + target = target.Elem() + } + target.SetInt(int64(n)) + return nil + } + + // Handle nested messages. + if targetType.Kind() == reflect.Struct { + var jsonFields map[string]json.RawMessage + if err := json.Unmarshal(inputValue, &jsonFields); err != nil { + return err + } + + consumeField := func(prop *proto.Properties) (json.RawMessage, bool) { + // Be liberal in what names we accept; both orig_name and camelName are okay. + fieldNames := acceptedJSONFieldNames(prop) + + vOrig, okOrig := jsonFields[fieldNames.orig] + vCamel, okCamel := jsonFields[fieldNames.camel] + if !okOrig && !okCamel { + return nil, false + } + // If, for some reason, both are present in the data, favour the camelName. + var raw json.RawMessage + if okOrig { + raw = vOrig + delete(jsonFields, fieldNames.orig) + } + if okCamel { + raw = vCamel + delete(jsonFields, fieldNames.camel) + } + return raw, true + } + + sprops := proto.GetProperties(targetType) + for i := 0; i < target.NumField(); i++ { + ft := target.Type().Field(i) + if strings.HasPrefix(ft.Name, "XXX_") { + continue + } + + valueForField, ok := consumeField(sprops.Prop[i]) + if !ok { + continue + } + + if err := u.unmarshalValue(target.Field(i), valueForField, sprops.Prop[i]); err != nil { + return err + } + } + // Check for any oneof fields. + if len(jsonFields) > 0 { + for _, oop := range sprops.OneofTypes { + raw, ok := consumeField(oop.Prop) + if !ok { + continue + } + nv := reflect.New(oop.Type.Elem()) + target.Field(oop.Field).Set(nv) + if err := u.unmarshalValue(nv.Elem().Field(0), raw, oop.Prop); err != nil { + return err + } + } + } + // Handle proto2 extensions. + if len(jsonFields) > 0 { + if ep, ok := target.Addr().Interface().(proto.Message); ok { + for _, ext := range proto.RegisteredExtensions(ep) { + name := fmt.Sprintf("[%s]", ext.Name) + raw, ok := jsonFields[name] + if !ok { + continue + } + delete(jsonFields, name) + nv := reflect.New(reflect.TypeOf(ext.ExtensionType).Elem()) + if err := u.unmarshalValue(nv.Elem(), raw, nil); err != nil { + return err + } + if err := proto.SetExtension(ep, ext, nv.Interface()); err != nil { + return err + } + } + } + } + if !u.AllowUnknownFields && len(jsonFields) > 0 { + // Pick any field to be the scapegoat. + var f string + for fname := range jsonFields { + f = fname + break + } + return fmt.Errorf("unknown field %q in %v", f, targetType) + } + return nil + } + + // Handle arrays (which aren't encoded bytes) + if targetType.Kind() == reflect.Slice && targetType.Elem().Kind() != reflect.Uint8 { + var slc []json.RawMessage + if err := json.Unmarshal(inputValue, &slc); err != nil { + return err + } + if slc != nil { + l := len(slc) + target.Set(reflect.MakeSlice(targetType, l, l)) + for i := 0; i < l; i++ { + if err := u.unmarshalValue(target.Index(i), slc[i], prop); err != nil { + return err + } + } + } + return nil + } + + // Handle maps (whose keys are always strings) + if targetType.Kind() == reflect.Map { + var mp map[string]json.RawMessage + if err := json.Unmarshal(inputValue, &mp); err != nil { + return err + } + if mp != nil { + target.Set(reflect.MakeMap(targetType)) + var keyprop, valprop *proto.Properties + if prop != nil { + // These could still be nil if the protobuf metadata is broken somehow. + // TODO: This won't work because the fields are unexported. + // We should probably just reparse them. + //keyprop, valprop = prop.mkeyprop, prop.mvalprop + } + for ks, raw := range mp { + // Unmarshal map key. The core json library already decoded the key into a + // string, so we handle that specially. Other types were quoted post-serialization. + var k reflect.Value + if targetType.Key().Kind() == reflect.String { + k = reflect.ValueOf(ks) + } else { + k = reflect.New(targetType.Key()).Elem() + if err := u.unmarshalValue(k, json.RawMessage(ks), keyprop); err != nil { + return err + } + } + + // Unmarshal map value. + v := reflect.New(targetType.Elem()).Elem() + if err := u.unmarshalValue(v, raw, valprop); err != nil { + return err + } + target.SetMapIndex(k, v) + } + } + return nil + } + + // 64-bit integers can be encoded as strings. In this case we drop + // the quotes and proceed as normal. + isNum := targetType.Kind() == reflect.Int64 || targetType.Kind() == reflect.Uint64 + if isNum && strings.HasPrefix(string(inputValue), `"`) { + inputValue = inputValue[1 : len(inputValue)-1] + } + + // Non-finite numbers can be encoded as strings. + isFloat := targetType.Kind() == reflect.Float32 || targetType.Kind() == reflect.Float64 + if isFloat { + if num, ok := nonFinite[string(inputValue)]; ok { + target.SetFloat(num) + return nil + } + } + + // Use the encoding/json for parsing other value types. + return json.Unmarshal(inputValue, target.Addr().Interface()) +} + +// jsonProperties returns parsed proto.Properties for the field and corrects JSONName attribute. +func jsonProperties(f reflect.StructField, origName bool) *proto.Properties { + var prop proto.Properties + prop.Init(f.Type, f.Name, f.Tag.Get("protobuf"), &f) + if origName || prop.JSONName == "" { + prop.JSONName = prop.OrigName + } + return &prop +} + +type fieldNames struct { + orig, camel string +} + +func acceptedJSONFieldNames(prop *proto.Properties) fieldNames { + opts := fieldNames{orig: prop.OrigName, camel: prop.OrigName} + if prop.JSONName != "" { + opts.camel = prop.JSONName + } + return opts +} + +// Writer wrapper inspired by https://blog.golang.org/errors-are-values +type errWriter struct { + writer io.Writer + err error +} + +func (w *errWriter) write(str string) { + if w.err != nil { + return + } + _, w.err = w.writer.Write([]byte(str)) +} + +// Map fields may have key types of non-float scalars, strings and enums. +// The easiest way to sort them in some deterministic order is to use fmt. +// If this turns out to be inefficient we can always consider other options, +// such as doing a Schwartzian transform. +// +// Numeric keys are sorted in numeric order per +// https://developers.google.com/protocol-buffers/docs/proto#maps. +type mapKeys []reflect.Value + +func (s mapKeys) Len() int { return len(s) } +func (s mapKeys) Swap(i, j int) { s[i], s[j] = s[j], s[i] } +func (s mapKeys) Less(i, j int) bool { + if k := s[i].Kind(); k == s[j].Kind() { + switch k { + case reflect.Int32, reflect.Int64: + return s[i].Int() < s[j].Int() + case reflect.Uint32, reflect.Uint64: + return s[i].Uint() < s[j].Uint() + } + } + return fmt.Sprint(s[i].Interface()) < fmt.Sprint(s[j].Interface()) +} diff --git a/vendor/github.com/golang/protobuf/jsonpb/jsonpb_test.go b/vendor/github.com/golang/protobuf/jsonpb/jsonpb_test.go new file mode 100644 index 00000000..2428d056 --- /dev/null +++ b/vendor/github.com/golang/protobuf/jsonpb/jsonpb_test.go @@ -0,0 +1,896 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2015 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// 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 +// OWNER 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. + +package jsonpb + +import ( + "bytes" + "encoding/json" + "io" + "math" + "reflect" + "strings" + "testing" + + "github.com/golang/protobuf/proto" + + pb "github.com/golang/protobuf/jsonpb/jsonpb_test_proto" + proto3pb "github.com/golang/protobuf/proto/proto3_proto" + "github.com/golang/protobuf/ptypes" + anypb "github.com/golang/protobuf/ptypes/any" + durpb "github.com/golang/protobuf/ptypes/duration" + stpb "github.com/golang/protobuf/ptypes/struct" + tspb "github.com/golang/protobuf/ptypes/timestamp" + wpb "github.com/golang/protobuf/ptypes/wrappers" +) + +var ( + marshaler = Marshaler{} + + marshalerAllOptions = Marshaler{ + Indent: " ", + } + + simpleObject = &pb.Simple{ + OInt32: proto.Int32(-32), + OInt64: proto.Int64(-6400000000), + OUint32: proto.Uint32(32), + OUint64: proto.Uint64(6400000000), + OSint32: proto.Int32(-13), + OSint64: proto.Int64(-2600000000), + OFloat: proto.Float32(3.14), + ODouble: proto.Float64(6.02214179e23), + OBool: proto.Bool(true), + OString: proto.String("hello \"there\""), + OBytes: []byte("beep boop"), + } + + simpleObjectJSON = `{` + + `"oBool":true,` + + `"oInt32":-32,` + + `"oInt64":"-6400000000",` + + `"oUint32":32,` + + `"oUint64":"6400000000",` + + `"oSint32":-13,` + + `"oSint64":"-2600000000",` + + `"oFloat":3.14,` + + `"oDouble":6.02214179e+23,` + + `"oString":"hello \"there\"",` + + `"oBytes":"YmVlcCBib29w"` + + `}` + + simpleObjectPrettyJSON = `{ + "oBool": true, + "oInt32": -32, + "oInt64": "-6400000000", + "oUint32": 32, + "oUint64": "6400000000", + "oSint32": -13, + "oSint64": "-2600000000", + "oFloat": 3.14, + "oDouble": 6.02214179e+23, + "oString": "hello \"there\"", + "oBytes": "YmVlcCBib29w" +}` + + repeatsObject = &pb.Repeats{ + RBool: []bool{true, false, true}, + RInt32: []int32{-3, -4, -5}, + RInt64: []int64{-123456789, -987654321}, + RUint32: []uint32{1, 2, 3}, + RUint64: []uint64{6789012345, 3456789012}, + RSint32: []int32{-1, -2, -3}, + RSint64: []int64{-6789012345, -3456789012}, + RFloat: []float32{3.14, 6.28}, + RDouble: []float64{299792458 * 1e20, 6.62606957e-34}, + RString: []string{"happy", "days"}, + RBytes: [][]byte{[]byte("skittles"), []byte("m&m's")}, + } + + repeatsObjectJSON = `{` + + `"rBool":[true,false,true],` + + `"rInt32":[-3,-4,-5],` + + `"rInt64":["-123456789","-987654321"],` + + `"rUint32":[1,2,3],` + + `"rUint64":["6789012345","3456789012"],` + + `"rSint32":[-1,-2,-3],` + + `"rSint64":["-6789012345","-3456789012"],` + + `"rFloat":[3.14,6.28],` + + `"rDouble":[2.99792458e+28,6.62606957e-34],` + + `"rString":["happy","days"],` + + `"rBytes":["c2tpdHRsZXM=","bSZtJ3M="]` + + `}` + + repeatsObjectPrettyJSON = `{ + "rBool": [ + true, + false, + true + ], + "rInt32": [ + -3, + -4, + -5 + ], + "rInt64": [ + "-123456789", + "-987654321" + ], + "rUint32": [ + 1, + 2, + 3 + ], + "rUint64": [ + "6789012345", + "3456789012" + ], + "rSint32": [ + -1, + -2, + -3 + ], + "rSint64": [ + "-6789012345", + "-3456789012" + ], + "rFloat": [ + 3.14, + 6.28 + ], + "rDouble": [ + 2.99792458e+28, + 6.62606957e-34 + ], + "rString": [ + "happy", + "days" + ], + "rBytes": [ + "c2tpdHRsZXM=", + "bSZtJ3M=" + ] +}` + + innerSimple = &pb.Simple{OInt32: proto.Int32(-32)} + innerSimple2 = &pb.Simple{OInt64: proto.Int64(25)} + innerRepeats = &pb.Repeats{RString: []string{"roses", "red"}} + innerRepeats2 = &pb.Repeats{RString: []string{"violets", "blue"}} + complexObject = &pb.Widget{ + Color: pb.Widget_GREEN.Enum(), + RColor: []pb.Widget_Color{pb.Widget_RED, pb.Widget_GREEN, pb.Widget_BLUE}, + Simple: innerSimple, + RSimple: []*pb.Simple{innerSimple, innerSimple2}, + Repeats: innerRepeats, + RRepeats: []*pb.Repeats{innerRepeats, innerRepeats2}, + } + + complexObjectJSON = `{"color":"GREEN",` + + `"rColor":["RED","GREEN","BLUE"],` + + `"simple":{"oInt32":-32},` + + `"rSimple":[{"oInt32":-32},{"oInt64":"25"}],` + + `"repeats":{"rString":["roses","red"]},` + + `"rRepeats":[{"rString":["roses","red"]},{"rString":["violets","blue"]}]` + + `}` + + complexObjectPrettyJSON = `{ + "color": "GREEN", + "rColor": [ + "RED", + "GREEN", + "BLUE" + ], + "simple": { + "oInt32": -32 + }, + "rSimple": [ + { + "oInt32": -32 + }, + { + "oInt64": "25" + } + ], + "repeats": { + "rString": [ + "roses", + "red" + ] + }, + "rRepeats": [ + { + "rString": [ + "roses", + "red" + ] + }, + { + "rString": [ + "violets", + "blue" + ] + } + ] +}` + + colorPrettyJSON = `{ + "color": 2 +}` + + colorListPrettyJSON = `{ + "color": 1000, + "rColor": [ + "RED" + ] +}` + + nummyPrettyJSON = `{ + "nummy": { + "1": 2, + "3": 4 + } +}` + + objjyPrettyJSON = `{ + "objjy": { + "1": { + "dub": 1 + } + } +}` + realNumber = &pb.Real{Value: proto.Float64(3.14159265359)} + realNumberName = "Pi" + complexNumber = &pb.Complex{Imaginary: proto.Float64(0.5772156649)} + realNumberJSON = `{` + + `"value":3.14159265359,` + + `"[jsonpb.Complex.real_extension]":{"imaginary":0.5772156649},` + + `"[jsonpb.name]":"Pi"` + + `}` + + anySimple = &pb.KnownTypes{ + An: &anypb.Any{ + TypeUrl: "something.example.com/jsonpb.Simple", + Value: []byte{ + // &pb.Simple{OBool:true} + 1 << 3, 1, + }, + }, + } + anySimpleJSON = `{"an":{"@type":"something.example.com/jsonpb.Simple","oBool":true}}` + anySimplePrettyJSON = `{ + "an": { + "@type": "something.example.com/jsonpb.Simple", + "oBool": true + } +}` + + anyWellKnown = &pb.KnownTypes{ + An: &anypb.Any{ + TypeUrl: "type.googleapis.com/google.protobuf.Duration", + Value: []byte{ + // &durpb.Duration{Seconds: 1, Nanos: 212000000 } + 1 << 3, 1, // seconds + 2 << 3, 0x80, 0xba, 0x8b, 0x65, // nanos + }, + }, + } + anyWellKnownJSON = `{"an":{"@type":"type.googleapis.com/google.protobuf.Duration","value":"1.212s"}}` + anyWellKnownPrettyJSON = `{ + "an": { + "@type": "type.googleapis.com/google.protobuf.Duration", + "value": "1.212s" + } +}` + + nonFinites = &pb.NonFinites{ + FNan: proto.Float32(float32(math.NaN())), + FPinf: proto.Float32(float32(math.Inf(1))), + FNinf: proto.Float32(float32(math.Inf(-1))), + DNan: proto.Float64(float64(math.NaN())), + DPinf: proto.Float64(float64(math.Inf(1))), + DNinf: proto.Float64(float64(math.Inf(-1))), + } + nonFinitesJSON = `{` + + `"fNan":"NaN",` + + `"fPinf":"Infinity",` + + `"fNinf":"-Infinity",` + + `"dNan":"NaN",` + + `"dPinf":"Infinity",` + + `"dNinf":"-Infinity"` + + `}` +) + +func init() { + if err := proto.SetExtension(realNumber, pb.E_Name, &realNumberName); err != nil { + panic(err) + } + if err := proto.SetExtension(realNumber, pb.E_Complex_RealExtension, complexNumber); err != nil { + panic(err) + } +} + +var marshalingTests = []struct { + desc string + marshaler Marshaler + pb proto.Message + json string +}{ + {"simple flat object", marshaler, simpleObject, simpleObjectJSON}, + {"simple pretty object", marshalerAllOptions, simpleObject, simpleObjectPrettyJSON}, + {"non-finite floats fields object", marshaler, nonFinites, nonFinitesJSON}, + {"repeated fields flat object", marshaler, repeatsObject, repeatsObjectJSON}, + {"repeated fields pretty object", marshalerAllOptions, repeatsObject, repeatsObjectPrettyJSON}, + {"nested message/enum flat object", marshaler, complexObject, complexObjectJSON}, + {"nested message/enum pretty object", marshalerAllOptions, complexObject, complexObjectPrettyJSON}, + {"enum-string flat object", Marshaler{}, + &pb.Widget{Color: pb.Widget_BLUE.Enum()}, `{"color":"BLUE"}`}, + {"enum-value pretty object", Marshaler{EnumsAsInts: true, Indent: " "}, + &pb.Widget{Color: pb.Widget_BLUE.Enum()}, colorPrettyJSON}, + {"unknown enum value object", marshalerAllOptions, + &pb.Widget{Color: pb.Widget_Color(1000).Enum(), RColor: []pb.Widget_Color{pb.Widget_RED}}, colorListPrettyJSON}, + {"repeated proto3 enum", Marshaler{}, + &proto3pb.Message{RFunny: []proto3pb.Message_Humour{ + proto3pb.Message_PUNS, + proto3pb.Message_SLAPSTICK, + }}, + `{"rFunny":["PUNS","SLAPSTICK"]}`}, + {"repeated proto3 enum as int", Marshaler{EnumsAsInts: true}, + &proto3pb.Message{RFunny: []proto3pb.Message_Humour{ + proto3pb.Message_PUNS, + proto3pb.Message_SLAPSTICK, + }}, + `{"rFunny":[1,2]}`}, + {"empty value", marshaler, &pb.Simple3{}, `{}`}, + {"empty value emitted", Marshaler{EmitDefaults: true}, &pb.Simple3{}, `{"dub":0}`}, + {"empty repeated emitted", Marshaler{EmitDefaults: true}, &pb.SimpleSlice3{}, `{"slices":[]}`}, + {"empty map emitted", Marshaler{EmitDefaults: true}, &pb.SimpleMap3{}, `{"stringy":{}}`}, + {"nested struct null", Marshaler{EmitDefaults: true}, &pb.SimpleNull3{}, `{"simple":null}`}, + {"map", marshaler, &pb.Mappy{Nummy: map[int64]int32{1: 2, 3: 4}}, `{"nummy":{"1":2,"3":4}}`}, + {"map", marshalerAllOptions, &pb.Mappy{Nummy: map[int64]int32{1: 2, 3: 4}}, nummyPrettyJSON}, + {"map", marshaler, + &pb.Mappy{Strry: map[string]string{`"one"`: "two", "three": "four"}}, + `{"strry":{"\"one\"":"two","three":"four"}}`}, + {"map", marshaler, + &pb.Mappy{Objjy: map[int32]*pb.Simple3{1: {Dub: 1}}}, `{"objjy":{"1":{"dub":1}}}`}, + {"map", marshalerAllOptions, + &pb.Mappy{Objjy: map[int32]*pb.Simple3{1: {Dub: 1}}}, objjyPrettyJSON}, + {"map", marshaler, &pb.Mappy{Buggy: map[int64]string{1234: "yup"}}, + `{"buggy":{"1234":"yup"}}`}, + {"map", marshaler, &pb.Mappy{Booly: map[bool]bool{false: true}}, `{"booly":{"false":true}}`}, + // TODO: This is broken. + //{"map", marshaler, &pb.Mappy{Enumy: map[string]pb.Numeral{"XIV": pb.Numeral_ROMAN}}, `{"enumy":{"XIV":"ROMAN"}`}, + {"map", Marshaler{EnumsAsInts: true}, &pb.Mappy{Enumy: map[string]pb.Numeral{"XIV": pb.Numeral_ROMAN}}, `{"enumy":{"XIV":2}}`}, + {"map", marshaler, &pb.Mappy{S32Booly: map[int32]bool{1: true, 3: false, 10: true, 12: false}}, `{"s32booly":{"1":true,"3":false,"10":true,"12":false}}`}, + {"map", marshaler, &pb.Mappy{S64Booly: map[int64]bool{1: true, 3: false, 10: true, 12: false}}, `{"s64booly":{"1":true,"3":false,"10":true,"12":false}}`}, + {"map", marshaler, &pb.Mappy{U32Booly: map[uint32]bool{1: true, 3: false, 10: true, 12: false}}, `{"u32booly":{"1":true,"3":false,"10":true,"12":false}}`}, + {"map", marshaler, &pb.Mappy{U64Booly: map[uint64]bool{1: true, 3: false, 10: true, 12: false}}, `{"u64booly":{"1":true,"3":false,"10":true,"12":false}}`}, + {"proto2 map", marshaler, &pb.Maps{MInt64Str: map[int64]string{213: "cat"}}, + `{"mInt64Str":{"213":"cat"}}`}, + {"proto2 map", marshaler, + &pb.Maps{MBoolSimple: map[bool]*pb.Simple{true: {OInt32: proto.Int32(1)}}}, + `{"mBoolSimple":{"true":{"oInt32":1}}}`}, + {"oneof, not set", marshaler, &pb.MsgWithOneof{}, `{}`}, + {"oneof, set", marshaler, &pb.MsgWithOneof{Union: &pb.MsgWithOneof_Title{"Grand Poobah"}}, `{"title":"Grand Poobah"}`}, + {"force orig_name", Marshaler{OrigName: true}, &pb.Simple{OInt32: proto.Int32(4)}, + `{"o_int32":4}`}, + {"proto2 extension", marshaler, realNumber, realNumberJSON}, + {"Any with message", marshaler, anySimple, anySimpleJSON}, + {"Any with message and indent", marshalerAllOptions, anySimple, anySimplePrettyJSON}, + {"Any with WKT", marshaler, anyWellKnown, anyWellKnownJSON}, + {"Any with WKT and indent", marshalerAllOptions, anyWellKnown, anyWellKnownPrettyJSON}, + {"Duration", marshaler, &pb.KnownTypes{Dur: &durpb.Duration{Seconds: 3}}, `{"dur":"3.000s"}`}, + {"Struct", marshaler, &pb.KnownTypes{St: &stpb.Struct{ + Fields: map[string]*stpb.Value{ + "one": {Kind: &stpb.Value_StringValue{"loneliest number"}}, + "two": {Kind: &stpb.Value_NullValue{stpb.NullValue_NULL_VALUE}}, + }, + }}, `{"st":{"one":"loneliest number","two":null}}`}, + {"empty ListValue", marshaler, &pb.KnownTypes{Lv: &stpb.ListValue{}}, `{"lv":[]}`}, + {"basic ListValue", marshaler, &pb.KnownTypes{Lv: &stpb.ListValue{Values: []*stpb.Value{ + {Kind: &stpb.Value_StringValue{"x"}}, + {Kind: &stpb.Value_NullValue{}}, + {Kind: &stpb.Value_NumberValue{3}}, + {Kind: &stpb.Value_BoolValue{true}}, + }}}, `{"lv":["x",null,3,true]}`}, + {"Timestamp", marshaler, &pb.KnownTypes{Ts: &tspb.Timestamp{Seconds: 14e8, Nanos: 21e6}}, `{"ts":"2014-05-13T16:53:20.021Z"}`}, + {"number Value", marshaler, &pb.KnownTypes{Val: &stpb.Value{Kind: &stpb.Value_NumberValue{1}}}, `{"val":1}`}, + {"null Value", marshaler, &pb.KnownTypes{Val: &stpb.Value{Kind: &stpb.Value_NullValue{stpb.NullValue_NULL_VALUE}}}, `{"val":null}`}, + {"string number value", marshaler, &pb.KnownTypes{Val: &stpb.Value{Kind: &stpb.Value_StringValue{"9223372036854775807"}}}, `{"val":"9223372036854775807"}`}, + {"list of lists Value", marshaler, &pb.KnownTypes{Val: &stpb.Value{ + Kind: &stpb.Value_ListValue{&stpb.ListValue{ + Values: []*stpb.Value{ + {Kind: &stpb.Value_StringValue{"x"}}, + {Kind: &stpb.Value_ListValue{&stpb.ListValue{ + Values: []*stpb.Value{ + {Kind: &stpb.Value_ListValue{&stpb.ListValue{ + Values: []*stpb.Value{{Kind: &stpb.Value_StringValue{"y"}}}, + }}}, + {Kind: &stpb.Value_StringValue{"z"}}, + }, + }}}, + }, + }}, + }}, `{"val":["x",[["y"],"z"]]}`}, + + {"DoubleValue", marshaler, &pb.KnownTypes{Dbl: &wpb.DoubleValue{Value: 1.2}}, `{"dbl":1.2}`}, + {"FloatValue", marshaler, &pb.KnownTypes{Flt: &wpb.FloatValue{Value: 1.2}}, `{"flt":1.2}`}, + {"Int64Value", marshaler, &pb.KnownTypes{I64: &wpb.Int64Value{Value: -3}}, `{"i64":"-3"}`}, + {"UInt64Value", marshaler, &pb.KnownTypes{U64: &wpb.UInt64Value{Value: 3}}, `{"u64":"3"}`}, + {"Int32Value", marshaler, &pb.KnownTypes{I32: &wpb.Int32Value{Value: -4}}, `{"i32":-4}`}, + {"UInt32Value", marshaler, &pb.KnownTypes{U32: &wpb.UInt32Value{Value: 4}}, `{"u32":4}`}, + {"BoolValue", marshaler, &pb.KnownTypes{Bool: &wpb.BoolValue{Value: true}}, `{"bool":true}`}, + {"StringValue", marshaler, &pb.KnownTypes{Str: &wpb.StringValue{Value: "plush"}}, `{"str":"plush"}`}, + {"BytesValue", marshaler, &pb.KnownTypes{Bytes: &wpb.BytesValue{Value: []byte("wow")}}, `{"bytes":"d293"}`}, +} + +func TestMarshaling(t *testing.T) { + for _, tt := range marshalingTests { + json, err := tt.marshaler.MarshalToString(tt.pb) + if err != nil { + t.Errorf("%s: marshaling error: %v", tt.desc, err) + } else if tt.json != json { + t.Errorf("%s: got [%v] want [%v]", tt.desc, json, tt.json) + } + } +} + +func TestMarshalJSONPBMarshaler(t *testing.T) { + rawJson := `{ "foo": "bar", "baz": [0, 1, 2, 3] }` + msg := dynamicMessage{rawJson: rawJson} + str, err := new(Marshaler).MarshalToString(&msg) + if err != nil { + t.Errorf("an unexpected error occurred when marshalling JSONPBMarshaler: %v", err) + } + if str != rawJson { + t.Errorf("marshalling JSON produced incorrect output: got %s, wanted %s", str, rawJson) + } +} + +func TestMarshalAnyJSONPBMarshaler(t *testing.T) { + msg := dynamicMessage{rawJson: `{ "foo": "bar", "baz": [0, 1, 2, 3] }`} + a, err := ptypes.MarshalAny(&msg) + if err != nil { + t.Errorf("an unexpected error occurred when marshalling to Any: %v", err) + } + str, err := new(Marshaler).MarshalToString(a) + if err != nil { + t.Errorf("an unexpected error occurred when marshalling Any to JSON: %v", err) + } + // after custom marshaling, it's round-tripped through JSON decoding/encoding already, + // so the keys are sorted, whitespace is compacted, and "@type" key has been added + expected := `{"@type":"type.googleapis.com/` + dynamicMessageName + `","baz":[0,1,2,3],"foo":"bar"}` + if str != expected { + t.Errorf("marshalling JSON produced incorrect output: got %s, wanted %s", str, expected) + } +} + +var unmarshalingTests = []struct { + desc string + unmarshaler Unmarshaler + json string + pb proto.Message +}{ + {"simple flat object", Unmarshaler{}, simpleObjectJSON, simpleObject}, + {"simple pretty object", Unmarshaler{}, simpleObjectPrettyJSON, simpleObject}, + {"repeated fields flat object", Unmarshaler{}, repeatsObjectJSON, repeatsObject}, + {"repeated fields pretty object", Unmarshaler{}, repeatsObjectPrettyJSON, repeatsObject}, + {"nested message/enum flat object", Unmarshaler{}, complexObjectJSON, complexObject}, + {"nested message/enum pretty object", Unmarshaler{}, complexObjectPrettyJSON, complexObject}, + {"enum-string object", Unmarshaler{}, `{"color":"BLUE"}`, &pb.Widget{Color: pb.Widget_BLUE.Enum()}}, + {"enum-value object", Unmarshaler{}, "{\n \"color\": 2\n}", &pb.Widget{Color: pb.Widget_BLUE.Enum()}}, + {"unknown field with allowed option", Unmarshaler{AllowUnknownFields: true}, `{"unknown": "foo"}`, new(pb.Simple)}, + {"proto3 enum string", Unmarshaler{}, `{"hilarity":"PUNS"}`, &proto3pb.Message{Hilarity: proto3pb.Message_PUNS}}, + {"proto3 enum value", Unmarshaler{}, `{"hilarity":1}`, &proto3pb.Message{Hilarity: proto3pb.Message_PUNS}}, + {"unknown enum value object", + Unmarshaler{}, + "{\n \"color\": 1000,\n \"r_color\": [\n \"RED\"\n ]\n}", + &pb.Widget{Color: pb.Widget_Color(1000).Enum(), RColor: []pb.Widget_Color{pb.Widget_RED}}}, + {"repeated proto3 enum", Unmarshaler{}, `{"rFunny":["PUNS","SLAPSTICK"]}`, + &proto3pb.Message{RFunny: []proto3pb.Message_Humour{ + proto3pb.Message_PUNS, + proto3pb.Message_SLAPSTICK, + }}}, + {"repeated proto3 enum as int", Unmarshaler{}, `{"rFunny":[1,2]}`, + &proto3pb.Message{RFunny: []proto3pb.Message_Humour{ + proto3pb.Message_PUNS, + proto3pb.Message_SLAPSTICK, + }}}, + {"repeated proto3 enum as mix of strings and ints", Unmarshaler{}, `{"rFunny":["PUNS",2]}`, + &proto3pb.Message{RFunny: []proto3pb.Message_Humour{ + proto3pb.Message_PUNS, + proto3pb.Message_SLAPSTICK, + }}}, + {"unquoted int64 object", Unmarshaler{}, `{"oInt64":-314}`, &pb.Simple{OInt64: proto.Int64(-314)}}, + {"unquoted uint64 object", Unmarshaler{}, `{"oUint64":123}`, &pb.Simple{OUint64: proto.Uint64(123)}}, + {"NaN", Unmarshaler{}, `{"oDouble":"NaN"}`, &pb.Simple{ODouble: proto.Float64(math.NaN())}}, + {"Inf", Unmarshaler{}, `{"oFloat":"Infinity"}`, &pb.Simple{OFloat: proto.Float32(float32(math.Inf(1)))}}, + {"-Inf", Unmarshaler{}, `{"oDouble":"-Infinity"}`, &pb.Simple{ODouble: proto.Float64(math.Inf(-1))}}, + {"map", Unmarshaler{}, `{"nummy":{"1":2,"3":4}}`, &pb.Mappy{Nummy: map[int64]int32{1: 2, 3: 4}}}, + {"map", Unmarshaler{}, `{"strry":{"\"one\"":"two","three":"four"}}`, &pb.Mappy{Strry: map[string]string{`"one"`: "two", "three": "four"}}}, + {"map", Unmarshaler{}, `{"objjy":{"1":{"dub":1}}}`, &pb.Mappy{Objjy: map[int32]*pb.Simple3{1: {Dub: 1}}}}, + {"proto2 extension", Unmarshaler{}, realNumberJSON, realNumber}, + {"Any with message", Unmarshaler{}, anySimpleJSON, anySimple}, + {"Any with message and indent", Unmarshaler{}, anySimplePrettyJSON, anySimple}, + {"Any with WKT", Unmarshaler{}, anyWellKnownJSON, anyWellKnown}, + {"Any with WKT and indent", Unmarshaler{}, anyWellKnownPrettyJSON, anyWellKnown}, + // TODO: This is broken. + //{"map", Unmarshaler{}, `{"enumy":{"XIV":"ROMAN"}`, &pb.Mappy{Enumy: map[string]pb.Numeral{"XIV": pb.Numeral_ROMAN}}}, + {"map", Unmarshaler{}, `{"enumy":{"XIV":2}}`, &pb.Mappy{Enumy: map[string]pb.Numeral{"XIV": pb.Numeral_ROMAN}}}, + {"oneof", Unmarshaler{}, `{"salary":31000}`, &pb.MsgWithOneof{Union: &pb.MsgWithOneof_Salary{31000}}}, + {"oneof spec name", Unmarshaler{}, `{"Country":"Australia"}`, &pb.MsgWithOneof{Union: &pb.MsgWithOneof_Country{"Australia"}}}, + {"oneof orig_name", Unmarshaler{}, `{"Country":"Australia"}`, &pb.MsgWithOneof{Union: &pb.MsgWithOneof_Country{"Australia"}}}, + {"oneof spec name2", Unmarshaler{}, `{"homeAddress":"Australia"}`, &pb.MsgWithOneof{Union: &pb.MsgWithOneof_HomeAddress{"Australia"}}}, + {"oneof orig_name2", Unmarshaler{}, `{"home_address":"Australia"}`, &pb.MsgWithOneof{Union: &pb.MsgWithOneof_HomeAddress{"Australia"}}}, + {"orig_name input", Unmarshaler{}, `{"o_bool":true}`, &pb.Simple{OBool: proto.Bool(true)}}, + {"camelName input", Unmarshaler{}, `{"oBool":true}`, &pb.Simple{OBool: proto.Bool(true)}}, + + {"Duration", Unmarshaler{}, `{"dur":"3.000s"}`, &pb.KnownTypes{Dur: &durpb.Duration{Seconds: 3}}}, + {"null Duration", Unmarshaler{}, `{"dur":null}`, &pb.KnownTypes{Dur: nil}}, + {"Timestamp", Unmarshaler{}, `{"ts":"2014-05-13T16:53:20.021Z"}`, &pb.KnownTypes{Ts: &tspb.Timestamp{Seconds: 14e8, Nanos: 21e6}}}, + {"PreEpochTimestamp", Unmarshaler{}, `{"ts":"1969-12-31T23:59:58.999999995Z"}`, &pb.KnownTypes{Ts: &tspb.Timestamp{Seconds: -2, Nanos: 999999995}}}, + {"ZeroTimeTimestamp", Unmarshaler{}, `{"ts":"0001-01-01T00:00:00Z"}`, &pb.KnownTypes{Ts: &tspb.Timestamp{Seconds: -62135596800, Nanos: 0}}}, + {"null Timestamp", Unmarshaler{}, `{"ts":null}`, &pb.KnownTypes{Ts: nil}}, + {"null Struct", Unmarshaler{}, `{"st": null}`, &pb.KnownTypes{St: nil}}, + {"empty Struct", Unmarshaler{}, `{"st": {}}`, &pb.KnownTypes{St: &stpb.Struct{}}}, + {"basic Struct", Unmarshaler{}, `{"st": {"a": "x", "b": null, "c": 3, "d": true}}`, &pb.KnownTypes{St: &stpb.Struct{Fields: map[string]*stpb.Value{ + "a": {Kind: &stpb.Value_StringValue{"x"}}, + "b": {Kind: &stpb.Value_NullValue{}}, + "c": {Kind: &stpb.Value_NumberValue{3}}, + "d": {Kind: &stpb.Value_BoolValue{true}}, + }}}}, + {"nested Struct", Unmarshaler{}, `{"st": {"a": {"b": 1, "c": [{"d": true}, "f"]}}}`, &pb.KnownTypes{St: &stpb.Struct{Fields: map[string]*stpb.Value{ + "a": {Kind: &stpb.Value_StructValue{&stpb.Struct{Fields: map[string]*stpb.Value{ + "b": {Kind: &stpb.Value_NumberValue{1}}, + "c": {Kind: &stpb.Value_ListValue{&stpb.ListValue{Values: []*stpb.Value{ + {Kind: &stpb.Value_StructValue{&stpb.Struct{Fields: map[string]*stpb.Value{"d": {Kind: &stpb.Value_BoolValue{true}}}}}}, + {Kind: &stpb.Value_StringValue{"f"}}, + }}}}, + }}}}, + }}}}, + {"null ListValue", Unmarshaler{}, `{"lv": null}`, &pb.KnownTypes{Lv: nil}}, + {"empty ListValue", Unmarshaler{}, `{"lv": []}`, &pb.KnownTypes{Lv: &stpb.ListValue{}}}, + {"basic ListValue", Unmarshaler{}, `{"lv": ["x", null, 3, true]}`, &pb.KnownTypes{Lv: &stpb.ListValue{Values: []*stpb.Value{ + {Kind: &stpb.Value_StringValue{"x"}}, + {Kind: &stpb.Value_NullValue{}}, + {Kind: &stpb.Value_NumberValue{3}}, + {Kind: &stpb.Value_BoolValue{true}}, + }}}}, + {"number Value", Unmarshaler{}, `{"val":1}`, &pb.KnownTypes{Val: &stpb.Value{Kind: &stpb.Value_NumberValue{1}}}}, + {"null Value", Unmarshaler{}, `{"val":null}`, &pb.KnownTypes{Val: &stpb.Value{Kind: &stpb.Value_NullValue{stpb.NullValue_NULL_VALUE}}}}, + {"bool Value", Unmarshaler{}, `{"val":true}`, &pb.KnownTypes{Val: &stpb.Value{Kind: &stpb.Value_BoolValue{true}}}}, + {"string Value", Unmarshaler{}, `{"val":"x"}`, &pb.KnownTypes{Val: &stpb.Value{Kind: &stpb.Value_StringValue{"x"}}}}, + {"string number value", Unmarshaler{}, `{"val":"9223372036854775807"}`, &pb.KnownTypes{Val: &stpb.Value{Kind: &stpb.Value_StringValue{"9223372036854775807"}}}}, + {"list of lists Value", Unmarshaler{}, `{"val":["x", [["y"], "z"]]}`, &pb.KnownTypes{Val: &stpb.Value{ + Kind: &stpb.Value_ListValue{&stpb.ListValue{ + Values: []*stpb.Value{ + {Kind: &stpb.Value_StringValue{"x"}}, + {Kind: &stpb.Value_ListValue{&stpb.ListValue{ + Values: []*stpb.Value{ + {Kind: &stpb.Value_ListValue{&stpb.ListValue{ + Values: []*stpb.Value{{Kind: &stpb.Value_StringValue{"y"}}}, + }}}, + {Kind: &stpb.Value_StringValue{"z"}}, + }, + }}}, + }, + }}}}}, + + {"DoubleValue", Unmarshaler{}, `{"dbl":1.2}`, &pb.KnownTypes{Dbl: &wpb.DoubleValue{Value: 1.2}}}, + {"FloatValue", Unmarshaler{}, `{"flt":1.2}`, &pb.KnownTypes{Flt: &wpb.FloatValue{Value: 1.2}}}, + {"Int64Value", Unmarshaler{}, `{"i64":"-3"}`, &pb.KnownTypes{I64: &wpb.Int64Value{Value: -3}}}, + {"UInt64Value", Unmarshaler{}, `{"u64":"3"}`, &pb.KnownTypes{U64: &wpb.UInt64Value{Value: 3}}}, + {"Int32Value", Unmarshaler{}, `{"i32":-4}`, &pb.KnownTypes{I32: &wpb.Int32Value{Value: -4}}}, + {"UInt32Value", Unmarshaler{}, `{"u32":4}`, &pb.KnownTypes{U32: &wpb.UInt32Value{Value: 4}}}, + {"BoolValue", Unmarshaler{}, `{"bool":true}`, &pb.KnownTypes{Bool: &wpb.BoolValue{Value: true}}}, + {"StringValue", Unmarshaler{}, `{"str":"plush"}`, &pb.KnownTypes{Str: &wpb.StringValue{Value: "plush"}}}, + {"BytesValue", Unmarshaler{}, `{"bytes":"d293"}`, &pb.KnownTypes{Bytes: &wpb.BytesValue{Value: []byte("wow")}}}, + + // Ensure that `null` as a value ends up with a nil pointer instead of a [type]Value struct. + {"null DoubleValue", Unmarshaler{}, `{"dbl":null}`, &pb.KnownTypes{Dbl: nil}}, + {"null FloatValue", Unmarshaler{}, `{"flt":null}`, &pb.KnownTypes{Flt: nil}}, + {"null Int64Value", Unmarshaler{}, `{"i64":null}`, &pb.KnownTypes{I64: nil}}, + {"null UInt64Value", Unmarshaler{}, `{"u64":null}`, &pb.KnownTypes{U64: nil}}, + {"null Int32Value", Unmarshaler{}, `{"i32":null}`, &pb.KnownTypes{I32: nil}}, + {"null UInt32Value", Unmarshaler{}, `{"u32":null}`, &pb.KnownTypes{U32: nil}}, + {"null BoolValue", Unmarshaler{}, `{"bool":null}`, &pb.KnownTypes{Bool: nil}}, + {"null StringValue", Unmarshaler{}, `{"str":null}`, &pb.KnownTypes{Str: nil}}, + {"null BytesValue", Unmarshaler{}, `{"bytes":null}`, &pb.KnownTypes{Bytes: nil}}, +} + +func TestUnmarshaling(t *testing.T) { + for _, tt := range unmarshalingTests { + // Make a new instance of the type of our expected object. + p := reflect.New(reflect.TypeOf(tt.pb).Elem()).Interface().(proto.Message) + + err := tt.unmarshaler.Unmarshal(strings.NewReader(tt.json), p) + if err != nil { + t.Errorf("%s: %v", tt.desc, err) + continue + } + + // For easier diffs, compare text strings of the protos. + exp := proto.MarshalTextString(tt.pb) + act := proto.MarshalTextString(p) + if string(exp) != string(act) { + t.Errorf("%s: got [%s] want [%s]", tt.desc, act, exp) + } + } +} + +func TestUnmarshalNullArray(t *testing.T) { + var repeats pb.Repeats + if err := UnmarshalString(`{"rBool":null}`, &repeats); err != nil { + t.Fatal(err) + } + if !reflect.DeepEqual(repeats, pb.Repeats{}) { + t.Errorf("got non-nil fields in [%#v]", repeats) + } +} + +func TestUnmarshalNullObject(t *testing.T) { + var maps pb.Maps + if err := UnmarshalString(`{"mInt64Str":null}`, &maps); err != nil { + t.Fatal(err) + } + if !reflect.DeepEqual(maps, pb.Maps{}) { + t.Errorf("got non-nil fields in [%#v]", maps) + } +} + +func TestUnmarshalNext(t *testing.T) { + // We only need to check against a few, not all of them. + tests := unmarshalingTests[:5] + + // Create a buffer with many concatenated JSON objects. + var b bytes.Buffer + for _, tt := range tests { + b.WriteString(tt.json) + } + + dec := json.NewDecoder(&b) + for _, tt := range tests { + // Make a new instance of the type of our expected object. + p := reflect.New(reflect.TypeOf(tt.pb).Elem()).Interface().(proto.Message) + + err := tt.unmarshaler.UnmarshalNext(dec, p) + if err != nil { + t.Errorf("%s: %v", tt.desc, err) + continue + } + + // For easier diffs, compare text strings of the protos. + exp := proto.MarshalTextString(tt.pb) + act := proto.MarshalTextString(p) + if string(exp) != string(act) { + t.Errorf("%s: got [%s] want [%s]", tt.desc, act, exp) + } + } + + p := &pb.Simple{} + err := new(Unmarshaler).UnmarshalNext(dec, p) + if err != io.EOF { + t.Errorf("eof: got %v, expected io.EOF", err) + } +} + +var unmarshalingShouldError = []struct { + desc string + in string + pb proto.Message +}{ + {"a value", "666", new(pb.Simple)}, + {"gibberish", "{adskja123;l23=-=", new(pb.Simple)}, + {"unknown field", `{"unknown": "foo"}`, new(pb.Simple)}, + {"unknown enum name", `{"hilarity":"DAVE"}`, new(proto3pb.Message)}, +} + +func TestUnmarshalingBadInput(t *testing.T) { + for _, tt := range unmarshalingShouldError { + err := UnmarshalString(tt.in, tt.pb) + if err == nil { + t.Errorf("an error was expected when parsing %q instead of an object", tt.desc) + } + } +} + +type funcResolver func(turl string) (proto.Message, error) + +func (fn funcResolver) Resolve(turl string) (proto.Message, error) { + return fn(turl) +} + +func TestAnyWithCustomResolver(t *testing.T) { + var resolvedTypeUrls []string + resolver := funcResolver(func(turl string) (proto.Message, error) { + resolvedTypeUrls = append(resolvedTypeUrls, turl) + return new(pb.Simple), nil + }) + msg := &pb.Simple{ + OBytes: []byte{1, 2, 3, 4}, + OBool: proto.Bool(true), + OString: proto.String("foobar"), + OInt64: proto.Int64(1020304), + } + msgBytes, err := proto.Marshal(msg) + if err != nil { + t.Errorf("an unexpected error occurred when marshaling message: %v", err) + } + // make an Any with a type URL that won't resolve w/out custom resolver + any := &anypb.Any{ + TypeUrl: "https://foobar.com/some.random.MessageKind", + Value: msgBytes, + } + + m := Marshaler{AnyResolver: resolver} + js, err := m.MarshalToString(any) + if err != nil { + t.Errorf("an unexpected error occurred when marshaling any to JSON: %v", err) + } + if len(resolvedTypeUrls) != 1 { + t.Errorf("custom resolver was not invoked during marshaling") + } else if resolvedTypeUrls[0] != "https://foobar.com/some.random.MessageKind" { + t.Errorf("custom resolver was invoked with wrong URL: got %q, wanted %q", resolvedTypeUrls[0], "https://foobar.com/some.random.MessageKind") + } + wanted := `{"@type":"https://foobar.com/some.random.MessageKind","oBool":true,"oInt64":"1020304","oString":"foobar","oBytes":"AQIDBA=="}` + if js != wanted { + t.Errorf("marshalling JSON produced incorrect output: got %s, wanted %s", js, wanted) + } + + u := Unmarshaler{AnyResolver: resolver} + roundTrip := &anypb.Any{} + err = u.Unmarshal(bytes.NewReader([]byte(js)), roundTrip) + if err != nil { + t.Errorf("an unexpected error occurred when unmarshaling any from JSON: %v", err) + } + if len(resolvedTypeUrls) != 2 { + t.Errorf("custom resolver was not invoked during marshaling") + } else if resolvedTypeUrls[1] != "https://foobar.com/some.random.MessageKind" { + t.Errorf("custom resolver was invoked with wrong URL: got %q, wanted %q", resolvedTypeUrls[1], "https://foobar.com/some.random.MessageKind") + } + if !proto.Equal(any, roundTrip) { + t.Errorf("message contents not set correctly after unmarshalling JSON: got %s, wanted %s", roundTrip, any) + } +} + +func TestUnmarshalJSONPBUnmarshaler(t *testing.T) { + rawJson := `{ "foo": "bar", "baz": [0, 1, 2, 3] }` + var msg dynamicMessage + if err := Unmarshal(strings.NewReader(rawJson), &msg); err != nil { + t.Errorf("an unexpected error occurred when parsing into JSONPBUnmarshaler: %v", err) + } + if msg.rawJson != rawJson { + t.Errorf("message contents not set correctly after unmarshalling JSON: got %s, wanted %s", msg.rawJson, rawJson) + } +} + +func TestUnmarshalNullWithJSONPBUnmarshaler(t *testing.T) { + rawJson := `{"stringField":null}` + var ptrFieldMsg ptrFieldMessage + if err := Unmarshal(strings.NewReader(rawJson), &ptrFieldMsg); err != nil { + t.Errorf("unmarshal error: %v", err) + } + + want := ptrFieldMessage{StringField: &stringField{IsSet: true, StringValue: "null"}} + if !proto.Equal(&ptrFieldMsg, &want) { + t.Errorf("unmarshal result StringField: got %v, want %v", ptrFieldMsg, want) + } +} + +func TestUnmarshalAnyJSONPBUnmarshaler(t *testing.T) { + rawJson := `{ "@type": "blah.com/` + dynamicMessageName + `", "foo": "bar", "baz": [0, 1, 2, 3] }` + var got anypb.Any + if err := Unmarshal(strings.NewReader(rawJson), &got); err != nil { + t.Errorf("an unexpected error occurred when parsing into JSONPBUnmarshaler: %v", err) + } + + dm := &dynamicMessage{rawJson: `{"baz":[0,1,2,3],"foo":"bar"}`} + var want anypb.Any + if b, err := proto.Marshal(dm); err != nil { + t.Errorf("an unexpected error occurred when marshaling message: %v", err) + } else { + want.TypeUrl = "blah.com/" + dynamicMessageName + want.Value = b + } + + if !proto.Equal(&got, &want) { + t.Errorf("message contents not set correctly after unmarshalling JSON: got %s, wanted %s", got, want) + } +} + +const ( + dynamicMessageName = "google.protobuf.jsonpb.testing.dynamicMessage" +) + +func init() { + // we register the custom type below so that we can use it in Any types + proto.RegisterType((*dynamicMessage)(nil), dynamicMessageName) +} + +type ptrFieldMessage struct { + StringField *stringField `protobuf:"bytes,1,opt,name=stringField"` +} + +func (m *ptrFieldMessage) Reset() { +} + +func (m *ptrFieldMessage) String() string { + return m.StringField.StringValue +} + +func (m *ptrFieldMessage) ProtoMessage() { +} + +type stringField struct { + IsSet bool `protobuf:"varint,1,opt,name=isSet"` + StringValue string `protobuf:"bytes,2,opt,name=stringValue"` +} + +func (s *stringField) Reset() { +} + +func (s *stringField) String() string { + return s.StringValue +} + +func (s *stringField) ProtoMessage() { +} + +func (s *stringField) UnmarshalJSONPB(jum *Unmarshaler, js []byte) error { + s.IsSet = true + s.StringValue = string(js) + return nil +} + +// dynamicMessage implements protobuf.Message but is not a normal generated message type. +// It provides implementations of JSONPBMarshaler and JSONPBUnmarshaler for JSON support. +type dynamicMessage struct { + rawJson string `protobuf:"bytes,1,opt,name=rawJson"` +} + +func (m *dynamicMessage) Reset() { + m.rawJson = "{}" +} + +func (m *dynamicMessage) String() string { + return m.rawJson +} + +func (m *dynamicMessage) ProtoMessage() { +} + +func (m *dynamicMessage) MarshalJSONPB(jm *Marshaler) ([]byte, error) { + return []byte(m.rawJson), nil +} + +func (m *dynamicMessage) UnmarshalJSONPB(jum *Unmarshaler, js []byte) error { + m.rawJson = string(js) + return nil +} diff --git a/vendor/github.com/golang/protobuf/jsonpb/jsonpb_test_proto/Makefile b/vendor/github.com/golang/protobuf/jsonpb/jsonpb_test_proto/Makefile new file mode 100644 index 00000000..eeda8ae5 --- /dev/null +++ b/vendor/github.com/golang/protobuf/jsonpb/jsonpb_test_proto/Makefile @@ -0,0 +1,33 @@ +# Go support for Protocol Buffers - Google's data interchange format +# +# Copyright 2015 The Go Authors. All rights reserved. +# https://github.com/golang/protobuf +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# 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 +# OWNER 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. + +regenerate: + protoc --go_out=Mgoogle/protobuf/any.proto=github.com/golang/protobuf/ptypes/any,Mgoogle/protobuf/duration.proto=github.com/golang/protobuf/ptypes/duration,Mgoogle/protobuf/struct.proto=github.com/golang/protobuf/ptypes/struct,Mgoogle/protobuf/timestamp.proto=github.com/golang/protobuf/ptypes/timestamp,Mgoogle/protobuf/wrappers.proto=github.com/golang/protobuf/ptypes/wrappers:. *.proto diff --git a/vendor/github.com/golang/protobuf/jsonpb/jsonpb_test_proto/more_test_objects.pb.go b/vendor/github.com/golang/protobuf/jsonpb/jsonpb_test_proto/more_test_objects.pb.go new file mode 100644 index 00000000..ebb180e8 --- /dev/null +++ b/vendor/github.com/golang/protobuf/jsonpb/jsonpb_test_proto/more_test_objects.pb.go @@ -0,0 +1,266 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: more_test_objects.proto + +/* +Package jsonpb is a generated protocol buffer package. + +It is generated from these files: + more_test_objects.proto + test_objects.proto + +It has these top-level messages: + Simple3 + SimpleSlice3 + SimpleMap3 + SimpleNull3 + Mappy + Simple + NonFinites + Repeats + Widget + Maps + MsgWithOneof + Real + Complex + KnownTypes +*/ +package jsonpb + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package + +type Numeral int32 + +const ( + Numeral_UNKNOWN Numeral = 0 + Numeral_ARABIC Numeral = 1 + Numeral_ROMAN Numeral = 2 +) + +var Numeral_name = map[int32]string{ + 0: "UNKNOWN", + 1: "ARABIC", + 2: "ROMAN", +} +var Numeral_value = map[string]int32{ + "UNKNOWN": 0, + "ARABIC": 1, + "ROMAN": 2, +} + +func (x Numeral) String() string { + return proto.EnumName(Numeral_name, int32(x)) +} +func (Numeral) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } + +type Simple3 struct { + Dub float64 `protobuf:"fixed64,1,opt,name=dub" json:"dub,omitempty"` +} + +func (m *Simple3) Reset() { *m = Simple3{} } +func (m *Simple3) String() string { return proto.CompactTextString(m) } +func (*Simple3) ProtoMessage() {} +func (*Simple3) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } + +func (m *Simple3) GetDub() float64 { + if m != nil { + return m.Dub + } + return 0 +} + +type SimpleSlice3 struct { + Slices []string `protobuf:"bytes,1,rep,name=slices" json:"slices,omitempty"` +} + +func (m *SimpleSlice3) Reset() { *m = SimpleSlice3{} } +func (m *SimpleSlice3) String() string { return proto.CompactTextString(m) } +func (*SimpleSlice3) ProtoMessage() {} +func (*SimpleSlice3) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } + +func (m *SimpleSlice3) GetSlices() []string { + if m != nil { + return m.Slices + } + return nil +} + +type SimpleMap3 struct { + Stringy map[string]string `protobuf:"bytes,1,rep,name=stringy" json:"stringy,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` +} + +func (m *SimpleMap3) Reset() { *m = SimpleMap3{} } +func (m *SimpleMap3) String() string { return proto.CompactTextString(m) } +func (*SimpleMap3) ProtoMessage() {} +func (*SimpleMap3) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } + +func (m *SimpleMap3) GetStringy() map[string]string { + if m != nil { + return m.Stringy + } + return nil +} + +type SimpleNull3 struct { + Simple *Simple3 `protobuf:"bytes,1,opt,name=simple" json:"simple,omitempty"` +} + +func (m *SimpleNull3) Reset() { *m = SimpleNull3{} } +func (m *SimpleNull3) String() string { return proto.CompactTextString(m) } +func (*SimpleNull3) ProtoMessage() {} +func (*SimpleNull3) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } + +func (m *SimpleNull3) GetSimple() *Simple3 { + if m != nil { + return m.Simple + } + return nil +} + +type Mappy struct { + Nummy map[int64]int32 `protobuf:"bytes,1,rep,name=nummy" json:"nummy,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"varint,2,opt,name=value"` + Strry map[string]string `protobuf:"bytes,2,rep,name=strry" json:"strry,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + Objjy map[int32]*Simple3 `protobuf:"bytes,3,rep,name=objjy" json:"objjy,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + Buggy map[int64]string `protobuf:"bytes,4,rep,name=buggy" json:"buggy,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + Booly map[bool]bool `protobuf:"bytes,5,rep,name=booly" json:"booly,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"varint,2,opt,name=value"` + Enumy map[string]Numeral `protobuf:"bytes,6,rep,name=enumy" json:"enumy,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"varint,2,opt,name=value,enum=jsonpb.Numeral"` + S32Booly map[int32]bool `protobuf:"bytes,7,rep,name=s32booly" json:"s32booly,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"varint,2,opt,name=value"` + S64Booly map[int64]bool `protobuf:"bytes,8,rep,name=s64booly" json:"s64booly,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"varint,2,opt,name=value"` + U32Booly map[uint32]bool `protobuf:"bytes,9,rep,name=u32booly" json:"u32booly,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"varint,2,opt,name=value"` + U64Booly map[uint64]bool `protobuf:"bytes,10,rep,name=u64booly" json:"u64booly,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"varint,2,opt,name=value"` +} + +func (m *Mappy) Reset() { *m = Mappy{} } +func (m *Mappy) String() string { return proto.CompactTextString(m) } +func (*Mappy) ProtoMessage() {} +func (*Mappy) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} } + +func (m *Mappy) GetNummy() map[int64]int32 { + if m != nil { + return m.Nummy + } + return nil +} + +func (m *Mappy) GetStrry() map[string]string { + if m != nil { + return m.Strry + } + return nil +} + +func (m *Mappy) GetObjjy() map[int32]*Simple3 { + if m != nil { + return m.Objjy + } + return nil +} + +func (m *Mappy) GetBuggy() map[int64]string { + if m != nil { + return m.Buggy + } + return nil +} + +func (m *Mappy) GetBooly() map[bool]bool { + if m != nil { + return m.Booly + } + return nil +} + +func (m *Mappy) GetEnumy() map[string]Numeral { + if m != nil { + return m.Enumy + } + return nil +} + +func (m *Mappy) GetS32Booly() map[int32]bool { + if m != nil { + return m.S32Booly + } + return nil +} + +func (m *Mappy) GetS64Booly() map[int64]bool { + if m != nil { + return m.S64Booly + } + return nil +} + +func (m *Mappy) GetU32Booly() map[uint32]bool { + if m != nil { + return m.U32Booly + } + return nil +} + +func (m *Mappy) GetU64Booly() map[uint64]bool { + if m != nil { + return m.U64Booly + } + return nil +} + +func init() { + proto.RegisterType((*Simple3)(nil), "jsonpb.Simple3") + proto.RegisterType((*SimpleSlice3)(nil), "jsonpb.SimpleSlice3") + proto.RegisterType((*SimpleMap3)(nil), "jsonpb.SimpleMap3") + proto.RegisterType((*SimpleNull3)(nil), "jsonpb.SimpleNull3") + proto.RegisterType((*Mappy)(nil), "jsonpb.Mappy") + proto.RegisterEnum("jsonpb.Numeral", Numeral_name, Numeral_value) +} + +func init() { proto.RegisterFile("more_test_objects.proto", fileDescriptor0) } + +var fileDescriptor0 = []byte{ + // 526 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x94, 0xdd, 0x6b, 0xdb, 0x3c, + 0x14, 0x87, 0x5f, 0x27, 0xf5, 0xd7, 0x49, 0xfb, 0x2e, 0x88, 0xb1, 0x99, 0xf4, 0x62, 0xc5, 0xb0, + 0xad, 0x0c, 0xe6, 0x8b, 0x78, 0x74, 0x5d, 0x77, 0x95, 0x8e, 0x5e, 0x94, 0x11, 0x07, 0x1c, 0xc2, + 0x2e, 0x4b, 0xdc, 0x99, 0x90, 0xcc, 0x5f, 0xd8, 0xd6, 0xc0, 0xd7, 0xfb, 0xbb, 0x07, 0xe3, 0x48, + 0x72, 0x2d, 0x07, 0x85, 0x6c, 0x77, 0x52, 0x7e, 0xcf, 0xe3, 0x73, 0x24, 0x1d, 0x02, 0x2f, 0xd3, + 0xbc, 0x8c, 0x1f, 0xea, 0xb8, 0xaa, 0x1f, 0xf2, 0x68, 0x17, 0x3f, 0xd6, 0x95, 0x57, 0x94, 0x79, + 0x9d, 0x13, 0x63, 0x57, 0xe5, 0x59, 0x11, 0xb9, 0xe7, 0x60, 0x2e, 0xb7, 0x69, 0x91, 0xc4, 0x3e, + 0x19, 0xc3, 0xf0, 0x3b, 0x8d, 0x1c, 0xed, 0x42, 0xbb, 0xd4, 0x42, 0x5c, 0xba, 0x6f, 0xe0, 0x94, + 0x87, 0xcb, 0x64, 0xfb, 0x18, 0xfb, 0xe4, 0x05, 0x18, 0x15, 0xae, 0x2a, 0x47, 0xbb, 0x18, 0x5e, + 0xda, 0xa1, 0xd8, 0xb9, 0xbf, 0x34, 0x00, 0x0e, 0xce, 0xd7, 0x85, 0x4f, 0x3e, 0x81, 0x59, 0xd5, + 0xe5, 0x36, 0xdb, 0x34, 0x8c, 0x1b, 0x4d, 0x5f, 0x79, 0xbc, 0x9a, 0xd7, 0x41, 0xde, 0x92, 0x13, + 0x77, 0x59, 0x5d, 0x36, 0x61, 0xcb, 0x4f, 0x6e, 0xe0, 0x54, 0x0e, 0xb0, 0xa7, 0x1f, 0x71, 0xc3, + 0x7a, 0xb2, 0x43, 0x5c, 0x92, 0xe7, 0xa0, 0xff, 0x5c, 0x27, 0x34, 0x76, 0x06, 0xec, 0x37, 0xbe, + 0xb9, 0x19, 0x5c, 0x6b, 0xee, 0x15, 0x8c, 0xf8, 0xf7, 0x03, 0x9a, 0x24, 0x3e, 0x79, 0x0b, 0x46, + 0xc5, 0xb6, 0xcc, 0x1e, 0x4d, 0x9f, 0xf5, 0x9b, 0xf0, 0x43, 0x11, 0xbb, 0xbf, 0x2d, 0xd0, 0xe7, + 0xeb, 0xa2, 0x68, 0x88, 0x07, 0x7a, 0x46, 0xd3, 0xb4, 0x6d, 0xdb, 0x69, 0x0d, 0x96, 0x7a, 0x01, + 0x46, 0xbc, 0x5f, 0x8e, 0x21, 0x5f, 0xd5, 0x65, 0xd9, 0x38, 0x03, 0x15, 0xbf, 0xc4, 0x48, 0xf0, + 0x0c, 0x43, 0x3e, 0x8f, 0x76, 0xbb, 0xc6, 0x19, 0xaa, 0xf8, 0x05, 0x46, 0x82, 0x67, 0x18, 0xf2, + 0x11, 0xdd, 0x6c, 0x1a, 0xe7, 0x44, 0xc5, 0xdf, 0x62, 0x24, 0x78, 0x86, 0x31, 0x3e, 0xcf, 0x93, + 0xc6, 0xd1, 0x95, 0x3c, 0x46, 0x2d, 0x8f, 0x6b, 0xe4, 0xe3, 0x8c, 0xa6, 0x8d, 0x63, 0xa8, 0xf8, + 0x3b, 0x8c, 0x04, 0xcf, 0x30, 0xf2, 0x11, 0xac, 0xca, 0x9f, 0xf2, 0x12, 0x26, 0x53, 0xce, 0xf7, + 0x8e, 0x2c, 0x52, 0x6e, 0x3d, 0xc1, 0x4c, 0xbc, 0xfa, 0xc0, 0x45, 0x4b, 0x29, 0x8a, 0xb4, 0x15, + 0xc5, 0x16, 0x45, 0xda, 0x56, 0xb4, 0x55, 0xe2, 0xaa, 0x5f, 0x91, 0x4a, 0x15, 0x69, 0x5b, 0x11, + 0x94, 0x62, 0xbf, 0x62, 0x0b, 0x4f, 0xae, 0x01, 0xba, 0x87, 0x96, 0xe7, 0x6f, 0xa8, 0x98, 0x3f, + 0x5d, 0x9a, 0x3f, 0x34, 0xbb, 0x27, 0xff, 0x97, 0xc9, 0x9d, 0xdc, 0x03, 0x74, 0x8f, 0x2f, 0x9b, + 0x3a, 0x37, 0x5f, 0xcb, 0xa6, 0x62, 0x92, 0xfb, 0x4d, 0x74, 0x73, 0x71, 0xac, 0x7d, 0x7b, 0xdf, + 0x7c, 0xba, 0x10, 0xd9, 0xb4, 0x14, 0xa6, 0xb5, 0xd7, 0x7e, 0x37, 0x2b, 0x8a, 0x83, 0xf7, 0xda, + 0xff, 0xbf, 0x6b, 0x3f, 0xa0, 0x69, 0x5c, 0xae, 0x13, 0xf9, 0x53, 0x9f, 0xe1, 0xac, 0x37, 0x43, + 0x8a, 0xcb, 0x38, 0xdc, 0x07, 0xca, 0xf2, 0xab, 0x1e, 0x3b, 0xfe, 0xbe, 0xbc, 0x3a, 0x54, 0xf9, + 0xec, 0x6f, 0xe4, 0x43, 0x95, 0x4f, 0x8e, 0xc8, 0xef, 0xde, 0x83, 0x29, 0x6e, 0x82, 0x8c, 0xc0, + 0x5c, 0x05, 0x5f, 0x83, 0xc5, 0xb7, 0x60, 0xfc, 0x1f, 0x01, 0x30, 0x66, 0xe1, 0xec, 0xf6, 0xfe, + 0xcb, 0x58, 0x23, 0x36, 0xe8, 0xe1, 0x62, 0x3e, 0x0b, 0xc6, 0x83, 0xc8, 0x60, 0x7f, 0xe0, 0xfe, + 0x9f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xdc, 0x84, 0x34, 0xaf, 0xdb, 0x05, 0x00, 0x00, +} diff --git a/vendor/github.com/golang/protobuf/jsonpb/jsonpb_test_proto/more_test_objects.proto b/vendor/github.com/golang/protobuf/jsonpb/jsonpb_test_proto/more_test_objects.proto new file mode 100644 index 00000000..d254fa5f --- /dev/null +++ b/vendor/github.com/golang/protobuf/jsonpb/jsonpb_test_proto/more_test_objects.proto @@ -0,0 +1,69 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2015 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// 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 +// OWNER 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. + +syntax = "proto3"; + +package jsonpb; + +message Simple3 { + double dub = 1; +} + +message SimpleSlice3 { + repeated string slices = 1; +} + +message SimpleMap3 { + map stringy = 1; +} + +message SimpleNull3 { + Simple3 simple = 1; +} + +enum Numeral { + UNKNOWN = 0; + ARABIC = 1; + ROMAN = 2; +} + +message Mappy { + map nummy = 1; + map strry = 2; + map objjy = 3; + map buggy = 4; + map booly = 5; + map enumy = 6; + map s32booly = 7; + map s64booly = 8; + map u32booly = 9; + map u64booly = 10; +} diff --git a/vendor/github.com/golang/protobuf/jsonpb/jsonpb_test_proto/test_objects.pb.go b/vendor/github.com/golang/protobuf/jsonpb/jsonpb_test_proto/test_objects.pb.go new file mode 100644 index 00000000..d413d740 --- /dev/null +++ b/vendor/github.com/golang/protobuf/jsonpb/jsonpb_test_proto/test_objects.pb.go @@ -0,0 +1,852 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: test_objects.proto + +package jsonpb + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" +import google_protobuf "github.com/golang/protobuf/ptypes/any" +import google_protobuf1 "github.com/golang/protobuf/ptypes/duration" +import google_protobuf2 "github.com/golang/protobuf/ptypes/struct" +import google_protobuf3 "github.com/golang/protobuf/ptypes/timestamp" +import google_protobuf4 "github.com/golang/protobuf/ptypes/wrappers" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +type Widget_Color int32 + +const ( + Widget_RED Widget_Color = 0 + Widget_GREEN Widget_Color = 1 + Widget_BLUE Widget_Color = 2 +) + +var Widget_Color_name = map[int32]string{ + 0: "RED", + 1: "GREEN", + 2: "BLUE", +} +var Widget_Color_value = map[string]int32{ + "RED": 0, + "GREEN": 1, + "BLUE": 2, +} + +func (x Widget_Color) Enum() *Widget_Color { + p := new(Widget_Color) + *p = x + return p +} +func (x Widget_Color) String() string { + return proto.EnumName(Widget_Color_name, int32(x)) +} +func (x *Widget_Color) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(Widget_Color_value, data, "Widget_Color") + if err != nil { + return err + } + *x = Widget_Color(value) + return nil +} +func (Widget_Color) EnumDescriptor() ([]byte, []int) { return fileDescriptor1, []int{3, 0} } + +// Test message for holding primitive types. +type Simple struct { + OBool *bool `protobuf:"varint,1,opt,name=o_bool,json=oBool" json:"o_bool,omitempty"` + OInt32 *int32 `protobuf:"varint,2,opt,name=o_int32,json=oInt32" json:"o_int32,omitempty"` + OInt64 *int64 `protobuf:"varint,3,opt,name=o_int64,json=oInt64" json:"o_int64,omitempty"` + OUint32 *uint32 `protobuf:"varint,4,opt,name=o_uint32,json=oUint32" json:"o_uint32,omitempty"` + OUint64 *uint64 `protobuf:"varint,5,opt,name=o_uint64,json=oUint64" json:"o_uint64,omitempty"` + OSint32 *int32 `protobuf:"zigzag32,6,opt,name=o_sint32,json=oSint32" json:"o_sint32,omitempty"` + OSint64 *int64 `protobuf:"zigzag64,7,opt,name=o_sint64,json=oSint64" json:"o_sint64,omitempty"` + OFloat *float32 `protobuf:"fixed32,8,opt,name=o_float,json=oFloat" json:"o_float,omitempty"` + ODouble *float64 `protobuf:"fixed64,9,opt,name=o_double,json=oDouble" json:"o_double,omitempty"` + OString *string `protobuf:"bytes,10,opt,name=o_string,json=oString" json:"o_string,omitempty"` + OBytes []byte `protobuf:"bytes,11,opt,name=o_bytes,json=oBytes" json:"o_bytes,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *Simple) Reset() { *m = Simple{} } +func (m *Simple) String() string { return proto.CompactTextString(m) } +func (*Simple) ProtoMessage() {} +func (*Simple) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{0} } + +func (m *Simple) GetOBool() bool { + if m != nil && m.OBool != nil { + return *m.OBool + } + return false +} + +func (m *Simple) GetOInt32() int32 { + if m != nil && m.OInt32 != nil { + return *m.OInt32 + } + return 0 +} + +func (m *Simple) GetOInt64() int64 { + if m != nil && m.OInt64 != nil { + return *m.OInt64 + } + return 0 +} + +func (m *Simple) GetOUint32() uint32 { + if m != nil && m.OUint32 != nil { + return *m.OUint32 + } + return 0 +} + +func (m *Simple) GetOUint64() uint64 { + if m != nil && m.OUint64 != nil { + return *m.OUint64 + } + return 0 +} + +func (m *Simple) GetOSint32() int32 { + if m != nil && m.OSint32 != nil { + return *m.OSint32 + } + return 0 +} + +func (m *Simple) GetOSint64() int64 { + if m != nil && m.OSint64 != nil { + return *m.OSint64 + } + return 0 +} + +func (m *Simple) GetOFloat() float32 { + if m != nil && m.OFloat != nil { + return *m.OFloat + } + return 0 +} + +func (m *Simple) GetODouble() float64 { + if m != nil && m.ODouble != nil { + return *m.ODouble + } + return 0 +} + +func (m *Simple) GetOString() string { + if m != nil && m.OString != nil { + return *m.OString + } + return "" +} + +func (m *Simple) GetOBytes() []byte { + if m != nil { + return m.OBytes + } + return nil +} + +// Test message for holding special non-finites primitives. +type NonFinites struct { + FNan *float32 `protobuf:"fixed32,1,opt,name=f_nan,json=fNan" json:"f_nan,omitempty"` + FPinf *float32 `protobuf:"fixed32,2,opt,name=f_pinf,json=fPinf" json:"f_pinf,omitempty"` + FNinf *float32 `protobuf:"fixed32,3,opt,name=f_ninf,json=fNinf" json:"f_ninf,omitempty"` + DNan *float64 `protobuf:"fixed64,4,opt,name=d_nan,json=dNan" json:"d_nan,omitempty"` + DPinf *float64 `protobuf:"fixed64,5,opt,name=d_pinf,json=dPinf" json:"d_pinf,omitempty"` + DNinf *float64 `protobuf:"fixed64,6,opt,name=d_ninf,json=dNinf" json:"d_ninf,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *NonFinites) Reset() { *m = NonFinites{} } +func (m *NonFinites) String() string { return proto.CompactTextString(m) } +func (*NonFinites) ProtoMessage() {} +func (*NonFinites) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{1} } + +func (m *NonFinites) GetFNan() float32 { + if m != nil && m.FNan != nil { + return *m.FNan + } + return 0 +} + +func (m *NonFinites) GetFPinf() float32 { + if m != nil && m.FPinf != nil { + return *m.FPinf + } + return 0 +} + +func (m *NonFinites) GetFNinf() float32 { + if m != nil && m.FNinf != nil { + return *m.FNinf + } + return 0 +} + +func (m *NonFinites) GetDNan() float64 { + if m != nil && m.DNan != nil { + return *m.DNan + } + return 0 +} + +func (m *NonFinites) GetDPinf() float64 { + if m != nil && m.DPinf != nil { + return *m.DPinf + } + return 0 +} + +func (m *NonFinites) GetDNinf() float64 { + if m != nil && m.DNinf != nil { + return *m.DNinf + } + return 0 +} + +// Test message for holding repeated primitives. +type Repeats struct { + RBool []bool `protobuf:"varint,1,rep,name=r_bool,json=rBool" json:"r_bool,omitempty"` + RInt32 []int32 `protobuf:"varint,2,rep,name=r_int32,json=rInt32" json:"r_int32,omitempty"` + RInt64 []int64 `protobuf:"varint,3,rep,name=r_int64,json=rInt64" json:"r_int64,omitempty"` + RUint32 []uint32 `protobuf:"varint,4,rep,name=r_uint32,json=rUint32" json:"r_uint32,omitempty"` + RUint64 []uint64 `protobuf:"varint,5,rep,name=r_uint64,json=rUint64" json:"r_uint64,omitempty"` + RSint32 []int32 `protobuf:"zigzag32,6,rep,name=r_sint32,json=rSint32" json:"r_sint32,omitempty"` + RSint64 []int64 `protobuf:"zigzag64,7,rep,name=r_sint64,json=rSint64" json:"r_sint64,omitempty"` + RFloat []float32 `protobuf:"fixed32,8,rep,name=r_float,json=rFloat" json:"r_float,omitempty"` + RDouble []float64 `protobuf:"fixed64,9,rep,name=r_double,json=rDouble" json:"r_double,omitempty"` + RString []string `protobuf:"bytes,10,rep,name=r_string,json=rString" json:"r_string,omitempty"` + RBytes [][]byte `protobuf:"bytes,11,rep,name=r_bytes,json=rBytes" json:"r_bytes,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *Repeats) Reset() { *m = Repeats{} } +func (m *Repeats) String() string { return proto.CompactTextString(m) } +func (*Repeats) ProtoMessage() {} +func (*Repeats) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{2} } + +func (m *Repeats) GetRBool() []bool { + if m != nil { + return m.RBool + } + return nil +} + +func (m *Repeats) GetRInt32() []int32 { + if m != nil { + return m.RInt32 + } + return nil +} + +func (m *Repeats) GetRInt64() []int64 { + if m != nil { + return m.RInt64 + } + return nil +} + +func (m *Repeats) GetRUint32() []uint32 { + if m != nil { + return m.RUint32 + } + return nil +} + +func (m *Repeats) GetRUint64() []uint64 { + if m != nil { + return m.RUint64 + } + return nil +} + +func (m *Repeats) GetRSint32() []int32 { + if m != nil { + return m.RSint32 + } + return nil +} + +func (m *Repeats) GetRSint64() []int64 { + if m != nil { + return m.RSint64 + } + return nil +} + +func (m *Repeats) GetRFloat() []float32 { + if m != nil { + return m.RFloat + } + return nil +} + +func (m *Repeats) GetRDouble() []float64 { + if m != nil { + return m.RDouble + } + return nil +} + +func (m *Repeats) GetRString() []string { + if m != nil { + return m.RString + } + return nil +} + +func (m *Repeats) GetRBytes() [][]byte { + if m != nil { + return m.RBytes + } + return nil +} + +// Test message for holding enums and nested messages. +type Widget struct { + Color *Widget_Color `protobuf:"varint,1,opt,name=color,enum=jsonpb.Widget_Color" json:"color,omitempty"` + RColor []Widget_Color `protobuf:"varint,2,rep,name=r_color,json=rColor,enum=jsonpb.Widget_Color" json:"r_color,omitempty"` + Simple *Simple `protobuf:"bytes,10,opt,name=simple" json:"simple,omitempty"` + RSimple []*Simple `protobuf:"bytes,11,rep,name=r_simple,json=rSimple" json:"r_simple,omitempty"` + Repeats *Repeats `protobuf:"bytes,20,opt,name=repeats" json:"repeats,omitempty"` + RRepeats []*Repeats `protobuf:"bytes,21,rep,name=r_repeats,json=rRepeats" json:"r_repeats,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *Widget) Reset() { *m = Widget{} } +func (m *Widget) String() string { return proto.CompactTextString(m) } +func (*Widget) ProtoMessage() {} +func (*Widget) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{3} } + +func (m *Widget) GetColor() Widget_Color { + if m != nil && m.Color != nil { + return *m.Color + } + return Widget_RED +} + +func (m *Widget) GetRColor() []Widget_Color { + if m != nil { + return m.RColor + } + return nil +} + +func (m *Widget) GetSimple() *Simple { + if m != nil { + return m.Simple + } + return nil +} + +func (m *Widget) GetRSimple() []*Simple { + if m != nil { + return m.RSimple + } + return nil +} + +func (m *Widget) GetRepeats() *Repeats { + if m != nil { + return m.Repeats + } + return nil +} + +func (m *Widget) GetRRepeats() []*Repeats { + if m != nil { + return m.RRepeats + } + return nil +} + +type Maps struct { + MInt64Str map[int64]string `protobuf:"bytes,1,rep,name=m_int64_str,json=mInt64Str" json:"m_int64_str,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + MBoolSimple map[bool]*Simple `protobuf:"bytes,2,rep,name=m_bool_simple,json=mBoolSimple" json:"m_bool_simple,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *Maps) Reset() { *m = Maps{} } +func (m *Maps) String() string { return proto.CompactTextString(m) } +func (*Maps) ProtoMessage() {} +func (*Maps) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{4} } + +func (m *Maps) GetMInt64Str() map[int64]string { + if m != nil { + return m.MInt64Str + } + return nil +} + +func (m *Maps) GetMBoolSimple() map[bool]*Simple { + if m != nil { + return m.MBoolSimple + } + return nil +} + +type MsgWithOneof struct { + // Types that are valid to be assigned to Union: + // *MsgWithOneof_Title + // *MsgWithOneof_Salary + // *MsgWithOneof_Country + // *MsgWithOneof_HomeAddress + Union isMsgWithOneof_Union `protobuf_oneof:"union"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *MsgWithOneof) Reset() { *m = MsgWithOneof{} } +func (m *MsgWithOneof) String() string { return proto.CompactTextString(m) } +func (*MsgWithOneof) ProtoMessage() {} +func (*MsgWithOneof) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{5} } + +type isMsgWithOneof_Union interface { + isMsgWithOneof_Union() +} + +type MsgWithOneof_Title struct { + Title string `protobuf:"bytes,1,opt,name=title,oneof"` +} +type MsgWithOneof_Salary struct { + Salary int64 `protobuf:"varint,2,opt,name=salary,oneof"` +} +type MsgWithOneof_Country struct { + Country string `protobuf:"bytes,3,opt,name=Country,oneof"` +} +type MsgWithOneof_HomeAddress struct { + HomeAddress string `protobuf:"bytes,4,opt,name=home_address,json=homeAddress,oneof"` +} + +func (*MsgWithOneof_Title) isMsgWithOneof_Union() {} +func (*MsgWithOneof_Salary) isMsgWithOneof_Union() {} +func (*MsgWithOneof_Country) isMsgWithOneof_Union() {} +func (*MsgWithOneof_HomeAddress) isMsgWithOneof_Union() {} + +func (m *MsgWithOneof) GetUnion() isMsgWithOneof_Union { + if m != nil { + return m.Union + } + return nil +} + +func (m *MsgWithOneof) GetTitle() string { + if x, ok := m.GetUnion().(*MsgWithOneof_Title); ok { + return x.Title + } + return "" +} + +func (m *MsgWithOneof) GetSalary() int64 { + if x, ok := m.GetUnion().(*MsgWithOneof_Salary); ok { + return x.Salary + } + return 0 +} + +func (m *MsgWithOneof) GetCountry() string { + if x, ok := m.GetUnion().(*MsgWithOneof_Country); ok { + return x.Country + } + return "" +} + +func (m *MsgWithOneof) GetHomeAddress() string { + if x, ok := m.GetUnion().(*MsgWithOneof_HomeAddress); ok { + return x.HomeAddress + } + return "" +} + +// XXX_OneofFuncs is for the internal use of the proto package. +func (*MsgWithOneof) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { + return _MsgWithOneof_OneofMarshaler, _MsgWithOneof_OneofUnmarshaler, _MsgWithOneof_OneofSizer, []interface{}{ + (*MsgWithOneof_Title)(nil), + (*MsgWithOneof_Salary)(nil), + (*MsgWithOneof_Country)(nil), + (*MsgWithOneof_HomeAddress)(nil), + } +} + +func _MsgWithOneof_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { + m := msg.(*MsgWithOneof) + // union + switch x := m.Union.(type) { + case *MsgWithOneof_Title: + b.EncodeVarint(1<<3 | proto.WireBytes) + b.EncodeStringBytes(x.Title) + case *MsgWithOneof_Salary: + b.EncodeVarint(2<<3 | proto.WireVarint) + b.EncodeVarint(uint64(x.Salary)) + case *MsgWithOneof_Country: + b.EncodeVarint(3<<3 | proto.WireBytes) + b.EncodeStringBytes(x.Country) + case *MsgWithOneof_HomeAddress: + b.EncodeVarint(4<<3 | proto.WireBytes) + b.EncodeStringBytes(x.HomeAddress) + case nil: + default: + return fmt.Errorf("MsgWithOneof.Union has unexpected type %T", x) + } + return nil +} + +func _MsgWithOneof_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { + m := msg.(*MsgWithOneof) + switch tag { + case 1: // union.title + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeStringBytes() + m.Union = &MsgWithOneof_Title{x} + return true, err + case 2: // union.salary + if wire != proto.WireVarint { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeVarint() + m.Union = &MsgWithOneof_Salary{int64(x)} + return true, err + case 3: // union.Country + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeStringBytes() + m.Union = &MsgWithOneof_Country{x} + return true, err + case 4: // union.home_address + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeStringBytes() + m.Union = &MsgWithOneof_HomeAddress{x} + return true, err + default: + return false, nil + } +} + +func _MsgWithOneof_OneofSizer(msg proto.Message) (n int) { + m := msg.(*MsgWithOneof) + // union + switch x := m.Union.(type) { + case *MsgWithOneof_Title: + n += proto.SizeVarint(1<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(len(x.Title))) + n += len(x.Title) + case *MsgWithOneof_Salary: + n += proto.SizeVarint(2<<3 | proto.WireVarint) + n += proto.SizeVarint(uint64(x.Salary)) + case *MsgWithOneof_Country: + n += proto.SizeVarint(3<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(len(x.Country))) + n += len(x.Country) + case *MsgWithOneof_HomeAddress: + n += proto.SizeVarint(4<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(len(x.HomeAddress))) + n += len(x.HomeAddress) + case nil: + default: + panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) + } + return n +} + +type Real struct { + Value *float64 `protobuf:"fixed64,1,opt,name=value" json:"value,omitempty"` + proto.XXX_InternalExtensions `json:"-"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *Real) Reset() { *m = Real{} } +func (m *Real) String() string { return proto.CompactTextString(m) } +func (*Real) ProtoMessage() {} +func (*Real) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{6} } + +var extRange_Real = []proto.ExtensionRange{ + {100, 536870911}, +} + +func (*Real) ExtensionRangeArray() []proto.ExtensionRange { + return extRange_Real +} + +func (m *Real) GetValue() float64 { + if m != nil && m.Value != nil { + return *m.Value + } + return 0 +} + +type Complex struct { + Imaginary *float64 `protobuf:"fixed64,1,opt,name=imaginary" json:"imaginary,omitempty"` + proto.XXX_InternalExtensions `json:"-"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *Complex) Reset() { *m = Complex{} } +func (m *Complex) String() string { return proto.CompactTextString(m) } +func (*Complex) ProtoMessage() {} +func (*Complex) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{7} } + +var extRange_Complex = []proto.ExtensionRange{ + {100, 536870911}, +} + +func (*Complex) ExtensionRangeArray() []proto.ExtensionRange { + return extRange_Complex +} + +func (m *Complex) GetImaginary() float64 { + if m != nil && m.Imaginary != nil { + return *m.Imaginary + } + return 0 +} + +var E_Complex_RealExtension = &proto.ExtensionDesc{ + ExtendedType: (*Real)(nil), + ExtensionType: (*Complex)(nil), + Field: 123, + Name: "jsonpb.Complex.real_extension", + Tag: "bytes,123,opt,name=real_extension,json=realExtension", + Filename: "test_objects.proto", +} + +type KnownTypes struct { + An *google_protobuf.Any `protobuf:"bytes,14,opt,name=an" json:"an,omitempty"` + Dur *google_protobuf1.Duration `protobuf:"bytes,1,opt,name=dur" json:"dur,omitempty"` + St *google_protobuf2.Struct `protobuf:"bytes,12,opt,name=st" json:"st,omitempty"` + Ts *google_protobuf3.Timestamp `protobuf:"bytes,2,opt,name=ts" json:"ts,omitempty"` + Lv *google_protobuf2.ListValue `protobuf:"bytes,15,opt,name=lv" json:"lv,omitempty"` + Val *google_protobuf2.Value `protobuf:"bytes,16,opt,name=val" json:"val,omitempty"` + Dbl *google_protobuf4.DoubleValue `protobuf:"bytes,3,opt,name=dbl" json:"dbl,omitempty"` + Flt *google_protobuf4.FloatValue `protobuf:"bytes,4,opt,name=flt" json:"flt,omitempty"` + I64 *google_protobuf4.Int64Value `protobuf:"bytes,5,opt,name=i64" json:"i64,omitempty"` + U64 *google_protobuf4.UInt64Value `protobuf:"bytes,6,opt,name=u64" json:"u64,omitempty"` + I32 *google_protobuf4.Int32Value `protobuf:"bytes,7,opt,name=i32" json:"i32,omitempty"` + U32 *google_protobuf4.UInt32Value `protobuf:"bytes,8,opt,name=u32" json:"u32,omitempty"` + Bool *google_protobuf4.BoolValue `protobuf:"bytes,9,opt,name=bool" json:"bool,omitempty"` + Str *google_protobuf4.StringValue `protobuf:"bytes,10,opt,name=str" json:"str,omitempty"` + Bytes *google_protobuf4.BytesValue `protobuf:"bytes,11,opt,name=bytes" json:"bytes,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *KnownTypes) Reset() { *m = KnownTypes{} } +func (m *KnownTypes) String() string { return proto.CompactTextString(m) } +func (*KnownTypes) ProtoMessage() {} +func (*KnownTypes) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{8} } + +func (m *KnownTypes) GetAn() *google_protobuf.Any { + if m != nil { + return m.An + } + return nil +} + +func (m *KnownTypes) GetDur() *google_protobuf1.Duration { + if m != nil { + return m.Dur + } + return nil +} + +func (m *KnownTypes) GetSt() *google_protobuf2.Struct { + if m != nil { + return m.St + } + return nil +} + +func (m *KnownTypes) GetTs() *google_protobuf3.Timestamp { + if m != nil { + return m.Ts + } + return nil +} + +func (m *KnownTypes) GetLv() *google_protobuf2.ListValue { + if m != nil { + return m.Lv + } + return nil +} + +func (m *KnownTypes) GetVal() *google_protobuf2.Value { + if m != nil { + return m.Val + } + return nil +} + +func (m *KnownTypes) GetDbl() *google_protobuf4.DoubleValue { + if m != nil { + return m.Dbl + } + return nil +} + +func (m *KnownTypes) GetFlt() *google_protobuf4.FloatValue { + if m != nil { + return m.Flt + } + return nil +} + +func (m *KnownTypes) GetI64() *google_protobuf4.Int64Value { + if m != nil { + return m.I64 + } + return nil +} + +func (m *KnownTypes) GetU64() *google_protobuf4.UInt64Value { + if m != nil { + return m.U64 + } + return nil +} + +func (m *KnownTypes) GetI32() *google_protobuf4.Int32Value { + if m != nil { + return m.I32 + } + return nil +} + +func (m *KnownTypes) GetU32() *google_protobuf4.UInt32Value { + if m != nil { + return m.U32 + } + return nil +} + +func (m *KnownTypes) GetBool() *google_protobuf4.BoolValue { + if m != nil { + return m.Bool + } + return nil +} + +func (m *KnownTypes) GetStr() *google_protobuf4.StringValue { + if m != nil { + return m.Str + } + return nil +} + +func (m *KnownTypes) GetBytes() *google_protobuf4.BytesValue { + if m != nil { + return m.Bytes + } + return nil +} + +var E_Name = &proto.ExtensionDesc{ + ExtendedType: (*Real)(nil), + ExtensionType: (*string)(nil), + Field: 124, + Name: "jsonpb.name", + Tag: "bytes,124,opt,name=name", + Filename: "test_objects.proto", +} + +func init() { + proto.RegisterType((*Simple)(nil), "jsonpb.Simple") + proto.RegisterType((*NonFinites)(nil), "jsonpb.NonFinites") + proto.RegisterType((*Repeats)(nil), "jsonpb.Repeats") + proto.RegisterType((*Widget)(nil), "jsonpb.Widget") + proto.RegisterType((*Maps)(nil), "jsonpb.Maps") + proto.RegisterType((*MsgWithOneof)(nil), "jsonpb.MsgWithOneof") + proto.RegisterType((*Real)(nil), "jsonpb.Real") + proto.RegisterType((*Complex)(nil), "jsonpb.Complex") + proto.RegisterType((*KnownTypes)(nil), "jsonpb.KnownTypes") + proto.RegisterEnum("jsonpb.Widget_Color", Widget_Color_name, Widget_Color_value) + proto.RegisterExtension(E_Complex_RealExtension) + proto.RegisterExtension(E_Name) +} + +func init() { proto.RegisterFile("test_objects.proto", fileDescriptor1) } + +var fileDescriptor1 = []byte{ + // 1160 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x95, 0x41, 0x73, 0xdb, 0x44, + 0x14, 0xc7, 0x23, 0xc9, 0x92, 0xed, 0x75, 0x92, 0x9a, 0x6d, 0xda, 0x2a, 0x26, 0x80, 0xc6, 0x94, + 0x22, 0x0a, 0x75, 0x07, 0xc7, 0xe3, 0x61, 0x0a, 0x97, 0xa4, 0x71, 0x29, 0x43, 0x13, 0x98, 0x4d, + 0x43, 0x8f, 0x1e, 0x39, 0x5a, 0xbb, 0x2a, 0xf2, 0xae, 0x67, 0x77, 0x95, 0xd4, 0x03, 0x87, 0x9c, + 0x39, 0x32, 0x7c, 0x05, 0xf8, 0x08, 0x1c, 0xf8, 0x74, 0xcc, 0xdb, 0x95, 0xac, 0xc4, 0x8e, 0x4f, + 0xf1, 0x7b, 0xef, 0xff, 0xfe, 0x59, 0xed, 0x6f, 0x77, 0x1f, 0xc2, 0x8a, 0x4a, 0x35, 0xe4, 0xa3, + 0x77, 0xf4, 0x5c, 0xc9, 0xce, 0x4c, 0x70, 0xc5, 0xb1, 0xf7, 0x4e, 0x72, 0x36, 0x1b, 0xb5, 0x76, + 0x27, 0x9c, 0x4f, 0x52, 0xfa, 0x54, 0x67, 0x47, 0xd9, 0xf8, 0x69, 0xc4, 0xe6, 0x46, 0xd2, 0xfa, + 0x78, 0xb9, 0x14, 0x67, 0x22, 0x52, 0x09, 0x67, 0x79, 0x7d, 0x6f, 0xb9, 0x2e, 0x95, 0xc8, 0xce, + 0x55, 0x5e, 0xfd, 0x64, 0xb9, 0xaa, 0x92, 0x29, 0x95, 0x2a, 0x9a, 0xce, 0xd6, 0xd9, 0x5f, 0x8a, + 0x68, 0x36, 0xa3, 0x22, 0x5f, 0x61, 0xfb, 0x6f, 0x1b, 0x79, 0xa7, 0xc9, 0x74, 0x96, 0x52, 0x7c, + 0x0f, 0x79, 0x7c, 0x38, 0xe2, 0x3c, 0xf5, 0xad, 0xc0, 0x0a, 0x6b, 0xc4, 0xe5, 0x87, 0x9c, 0xa7, + 0xf8, 0x01, 0xaa, 0xf2, 0x61, 0xc2, 0xd4, 0x7e, 0xd7, 0xb7, 0x03, 0x2b, 0x74, 0x89, 0xc7, 0x7f, + 0x80, 0x68, 0x51, 0xe8, 0xf7, 0x7c, 0x27, 0xb0, 0x42, 0xc7, 0x14, 0xfa, 0x3d, 0xbc, 0x8b, 0x6a, + 0x7c, 0x98, 0x99, 0x96, 0x4a, 0x60, 0x85, 0x5b, 0xa4, 0xca, 0xcf, 0x74, 0x58, 0x96, 0xfa, 0x3d, + 0xdf, 0x0d, 0xac, 0xb0, 0x92, 0x97, 0x8a, 0x2e, 0x69, 0xba, 0xbc, 0xc0, 0x0a, 0x3f, 0x20, 0x55, + 0x7e, 0x7a, 0xad, 0x4b, 0x9a, 0xae, 0x6a, 0x60, 0x85, 0x38, 0x2f, 0xf5, 0x7b, 0x66, 0x11, 0xe3, + 0x94, 0x47, 0xca, 0xaf, 0x05, 0x56, 0x68, 0x13, 0x8f, 0xbf, 0x80, 0xc8, 0xf4, 0xc4, 0x3c, 0x1b, + 0xa5, 0xd4, 0xaf, 0x07, 0x56, 0x68, 0x91, 0x2a, 0x3f, 0xd2, 0x61, 0x6e, 0xa7, 0x44, 0xc2, 0x26, + 0x3e, 0x0a, 0xac, 0xb0, 0x0e, 0x76, 0x3a, 0x34, 0x76, 0xa3, 0xb9, 0xa2, 0xd2, 0x6f, 0x04, 0x56, + 0xb8, 0x49, 0x3c, 0x7e, 0x08, 0x51, 0xfb, 0x4f, 0x0b, 0xa1, 0x13, 0xce, 0x5e, 0x24, 0x2c, 0x51, + 0x54, 0xe2, 0xbb, 0xc8, 0x1d, 0x0f, 0x59, 0xc4, 0xf4, 0x56, 0xd9, 0xa4, 0x32, 0x3e, 0x89, 0x18, + 0x6c, 0xe0, 0x78, 0x38, 0x4b, 0xd8, 0x58, 0x6f, 0x94, 0x4d, 0xdc, 0xf1, 0xcf, 0x09, 0x1b, 0x9b, + 0x34, 0x83, 0xb4, 0x93, 0xa7, 0x4f, 0x20, 0x7d, 0x17, 0xb9, 0xb1, 0xb6, 0xa8, 0xe8, 0xd5, 0x55, + 0xe2, 0xdc, 0x22, 0x36, 0x16, 0xae, 0xce, 0xba, 0x71, 0x61, 0x11, 0x1b, 0x0b, 0x2f, 0x4f, 0x83, + 0x45, 0xfb, 0x1f, 0x1b, 0x55, 0x09, 0x9d, 0xd1, 0x48, 0x49, 0x90, 0x88, 0x82, 0x9e, 0x03, 0xf4, + 0x44, 0x41, 0x4f, 0x2c, 0xe8, 0x39, 0x40, 0x4f, 0x2c, 0xe8, 0x89, 0x05, 0x3d, 0x07, 0xe8, 0x89, + 0x05, 0x3d, 0x51, 0xd2, 0x73, 0x80, 0x9e, 0x28, 0xe9, 0x89, 0x92, 0x9e, 0x03, 0xf4, 0x44, 0x49, + 0x4f, 0x94, 0xf4, 0x1c, 0xa0, 0x27, 0x4e, 0xaf, 0x75, 0x2d, 0xe8, 0x39, 0x40, 0x4f, 0x94, 0xf4, + 0xc4, 0x82, 0x9e, 0x03, 0xf4, 0xc4, 0x82, 0x9e, 0x28, 0xe9, 0x39, 0x40, 0x4f, 0x94, 0xf4, 0x44, + 0x49, 0xcf, 0x01, 0x7a, 0xa2, 0xa4, 0x27, 0x16, 0xf4, 0x1c, 0xa0, 0x27, 0x0c, 0xbd, 0x7f, 0x6d, + 0xe4, 0xbd, 0x49, 0xe2, 0x09, 0x55, 0xf8, 0x31, 0x72, 0xcf, 0x79, 0xca, 0x85, 0x26, 0xb7, 0xdd, + 0xdd, 0xe9, 0x98, 0x2b, 0xda, 0x31, 0xe5, 0xce, 0x73, 0xa8, 0x11, 0x23, 0xc1, 0x4f, 0xc0, 0xcf, + 0xa8, 0x61, 0xf3, 0xd6, 0xa9, 0x3d, 0xa1, 0xff, 0xe2, 0x47, 0xc8, 0x93, 0xfa, 0x2a, 0xe9, 0x53, + 0xd5, 0xe8, 0x6e, 0x17, 0x6a, 0x73, 0xc1, 0x48, 0x5e, 0xc5, 0x5f, 0x98, 0x0d, 0xd1, 0x4a, 0x58, + 0xe7, 0xaa, 0x12, 0x36, 0x28, 0x97, 0x56, 0x85, 0x01, 0xec, 0xef, 0x68, 0xcf, 0x3b, 0x85, 0x32, + 0xe7, 0x4e, 0x8a, 0x3a, 0xfe, 0x0a, 0xd5, 0xc5, 0xb0, 0x10, 0xdf, 0xd3, 0xb6, 0x2b, 0xe2, 0x9a, + 0xc8, 0x7f, 0xb5, 0x3f, 0x43, 0xae, 0x59, 0x74, 0x15, 0x39, 0x64, 0x70, 0xd4, 0xdc, 0xc0, 0x75, + 0xe4, 0x7e, 0x4f, 0x06, 0x83, 0x93, 0xa6, 0x85, 0x6b, 0xa8, 0x72, 0xf8, 0xea, 0x6c, 0xd0, 0xb4, + 0xdb, 0x7f, 0xd9, 0xa8, 0x72, 0x1c, 0xcd, 0x24, 0xfe, 0x16, 0x35, 0xa6, 0xe6, 0xb8, 0xc0, 0xde, + 0xeb, 0x33, 0xd6, 0xe8, 0x7e, 0x58, 0xf8, 0x83, 0xa4, 0x73, 0xac, 0xcf, 0xcf, 0xa9, 0x12, 0x03, + 0xa6, 0xc4, 0x9c, 0xd4, 0xa7, 0x45, 0x8c, 0x0f, 0xd0, 0xd6, 0x54, 0x9f, 0xcd, 0xe2, 0xab, 0x6d, + 0xdd, 0xfe, 0xd1, 0xcd, 0x76, 0x38, 0xaf, 0xe6, 0xb3, 0x8d, 0x41, 0x63, 0x5a, 0x66, 0x5a, 0xdf, + 0xa1, 0xed, 0x9b, 0xfe, 0xb8, 0x89, 0x9c, 0x5f, 0xe9, 0x5c, 0x63, 0x74, 0x08, 0xfc, 0xc4, 0x3b, + 0xc8, 0xbd, 0x88, 0xd2, 0x8c, 0xea, 0xeb, 0x57, 0x27, 0x26, 0x78, 0x66, 0x7f, 0x63, 0xb5, 0x4e, + 0x50, 0x73, 0xd9, 0xfe, 0x7a, 0x7f, 0xcd, 0xf4, 0x3f, 0xbc, 0xde, 0xbf, 0x0a, 0xa5, 0xf4, 0x6b, + 0xff, 0x61, 0xa1, 0xcd, 0x63, 0x39, 0x79, 0x93, 0xa8, 0xb7, 0x3f, 0x31, 0xca, 0xc7, 0xf8, 0x3e, + 0x72, 0x55, 0xa2, 0x52, 0xaa, 0xed, 0xea, 0x2f, 0x37, 0x88, 0x09, 0xb1, 0x8f, 0x3c, 0x19, 0xa5, + 0x91, 0x98, 0x6b, 0x4f, 0xe7, 0xe5, 0x06, 0xc9, 0x63, 0xdc, 0x42, 0xd5, 0xe7, 0x3c, 0x83, 0x95, + 0xe8, 0x67, 0x01, 0x7a, 0x8a, 0x04, 0xfe, 0x14, 0x6d, 0xbe, 0xe5, 0x53, 0x3a, 0x8c, 0xe2, 0x58, + 0x50, 0x29, 0xf5, 0x0b, 0x01, 0x82, 0x06, 0x64, 0x0f, 0x4c, 0xf2, 0xb0, 0x8a, 0xdc, 0x8c, 0x25, + 0x9c, 0xb5, 0x1f, 0xa1, 0x0a, 0xa1, 0x51, 0x5a, 0x7e, 0xbe, 0x65, 0xde, 0x08, 0x1d, 0x3c, 0xae, + 0xd5, 0xe2, 0xe6, 0xd5, 0xd5, 0xd5, 0x95, 0xdd, 0xbe, 0x84, 0xff, 0x08, 0x5f, 0xf2, 0x1e, 0xef, + 0xa1, 0x7a, 0x32, 0x8d, 0x26, 0x09, 0x83, 0x95, 0x19, 0x79, 0x99, 0x28, 0x5b, 0xba, 0x47, 0x68, + 0x5b, 0xd0, 0x28, 0x1d, 0xd2, 0xf7, 0x8a, 0x32, 0x99, 0x70, 0x86, 0x37, 0xcb, 0x23, 0x15, 0xa5, + 0xfe, 0x6f, 0x37, 0xcf, 0x64, 0x6e, 0x4f, 0xb6, 0xa0, 0x69, 0x50, 0xf4, 0xb4, 0xff, 0x73, 0x11, + 0xfa, 0x91, 0xf1, 0x4b, 0xf6, 0x7a, 0x3e, 0xa3, 0x12, 0x3f, 0x44, 0x76, 0xc4, 0xfc, 0x6d, 0xdd, + 0xba, 0xd3, 0x31, 0xf3, 0xa9, 0x53, 0xcc, 0xa7, 0xce, 0x01, 0x9b, 0x13, 0x3b, 0x62, 0xf8, 0x4b, + 0xe4, 0xc4, 0x99, 0xb9, 0xa5, 0x8d, 0xee, 0xee, 0x8a, 0xec, 0x28, 0x9f, 0x92, 0x04, 0x54, 0xf8, + 0x73, 0x64, 0x4b, 0xe5, 0x6f, 0x6a, 0xed, 0x83, 0x15, 0xed, 0xa9, 0x9e, 0x98, 0xc4, 0x96, 0x70, + 0xfb, 0x6d, 0x25, 0x73, 0xbe, 0xad, 0x15, 0xe1, 0xeb, 0x62, 0x78, 0x12, 0x5b, 0x49, 0xd0, 0xa6, + 0x17, 0xfe, 0x9d, 0x35, 0xda, 0x57, 0x89, 0x54, 0xbf, 0xc0, 0x0e, 0x13, 0x3b, 0xbd, 0xc0, 0x21, + 0x72, 0x2e, 0xa2, 0xd4, 0x6f, 0x6a, 0xf1, 0xfd, 0x15, 0xb1, 0x11, 0x82, 0x04, 0x77, 0x90, 0x13, + 0x8f, 0x52, 0xcd, 0xbc, 0xd1, 0xdd, 0x5b, 0xfd, 0x2e, 0xfd, 0xc8, 0xe5, 0xfa, 0x78, 0x94, 0xe2, + 0x27, 0xc8, 0x19, 0xa7, 0x4a, 0x1f, 0x01, 0xb8, 0x70, 0xcb, 0x7a, 0xfd, 0x5c, 0xe6, 0xf2, 0x71, + 0xaa, 0x40, 0x9e, 0xe4, 0xb3, 0xf5, 0x36, 0xb9, 0xbe, 0x42, 0xb9, 0x3c, 0xe9, 0xf7, 0x60, 0x35, + 0x59, 0xbf, 0xa7, 0xa7, 0xca, 0x6d, 0xab, 0x39, 0xbb, 0xae, 0xcf, 0xfa, 0x3d, 0x6d, 0xbf, 0xdf, + 0xd5, 0x43, 0x78, 0x8d, 0xfd, 0x7e, 0xb7, 0xb0, 0xdf, 0xef, 0x6a, 0xfb, 0xfd, 0xae, 0x9e, 0xcc, + 0xeb, 0xec, 0x17, 0xfa, 0x4c, 0xeb, 0x2b, 0x7a, 0x84, 0xd5, 0xd7, 0x6c, 0x3a, 0xdc, 0x61, 0x23, + 0xd7, 0x3a, 0xf0, 0x87, 0xd7, 0x08, 0xad, 0xf1, 0x37, 0x63, 0x21, 0xf7, 0x97, 0x4a, 0xe0, 0xaf, + 0x91, 0x5b, 0x0e, 0xf7, 0xdb, 0x3e, 0x40, 0x8f, 0x0b, 0xd3, 0x60, 0x94, 0xcf, 0x02, 0x54, 0x61, + 0xd1, 0x94, 0x2e, 0x1d, 0xfc, 0xdf, 0xf5, 0x0b, 0xa3, 0x2b, 0xff, 0x07, 0x00, 0x00, 0xff, 0xff, + 0xd5, 0x39, 0x32, 0x09, 0xf9, 0x09, 0x00, 0x00, +} diff --git a/vendor/github.com/golang/protobuf/jsonpb/jsonpb_test_proto/test_objects.proto b/vendor/github.com/golang/protobuf/jsonpb/jsonpb_test_proto/test_objects.proto new file mode 100644 index 00000000..0d2fc1fa --- /dev/null +++ b/vendor/github.com/golang/protobuf/jsonpb/jsonpb_test_proto/test_objects.proto @@ -0,0 +1,147 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2015 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// 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 +// OWNER 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. + +syntax = "proto2"; + +import "google/protobuf/any.proto"; +import "google/protobuf/duration.proto"; +import "google/protobuf/struct.proto"; +import "google/protobuf/timestamp.proto"; +import "google/protobuf/wrappers.proto"; + +package jsonpb; + +// Test message for holding primitive types. +message Simple { + optional bool o_bool = 1; + optional int32 o_int32 = 2; + optional int64 o_int64 = 3; + optional uint32 o_uint32 = 4; + optional uint64 o_uint64 = 5; + optional sint32 o_sint32 = 6; + optional sint64 o_sint64 = 7; + optional float o_float = 8; + optional double o_double = 9; + optional string o_string = 10; + optional bytes o_bytes = 11; +} + +// Test message for holding special non-finites primitives. +message NonFinites { + optional float f_nan = 1; + optional float f_pinf = 2; + optional float f_ninf = 3; + optional double d_nan = 4; + optional double d_pinf = 5; + optional double d_ninf = 6; +} + +// Test message for holding repeated primitives. +message Repeats { + repeated bool r_bool = 1; + repeated int32 r_int32 = 2; + repeated int64 r_int64 = 3; + repeated uint32 r_uint32 = 4; + repeated uint64 r_uint64 = 5; + repeated sint32 r_sint32 = 6; + repeated sint64 r_sint64 = 7; + repeated float r_float = 8; + repeated double r_double = 9; + repeated string r_string = 10; + repeated bytes r_bytes = 11; +} + +// Test message for holding enums and nested messages. +message Widget { + enum Color { + RED = 0; + GREEN = 1; + BLUE = 2; + }; + optional Color color = 1; + repeated Color r_color = 2; + + optional Simple simple = 10; + repeated Simple r_simple = 11; + + optional Repeats repeats = 20; + repeated Repeats r_repeats = 21; +} + +message Maps { + map m_int64_str = 1; + map m_bool_simple = 2; +} + +message MsgWithOneof { + oneof union { + string title = 1; + int64 salary = 2; + string Country = 3; + string home_address = 4; + } +} + +message Real { + optional double value = 1; + extensions 100 to max; +} + +extend Real { + optional string name = 124; +} + +message Complex { + extend Real { + optional Complex real_extension = 123; + } + optional double imaginary = 1; + extensions 100 to max; +} + +message KnownTypes { + optional google.protobuf.Any an = 14; + optional google.protobuf.Duration dur = 1; + optional google.protobuf.Struct st = 12; + optional google.protobuf.Timestamp ts = 2; + optional google.protobuf.ListValue lv = 15; + optional google.protobuf.Value val = 16; + + optional google.protobuf.DoubleValue dbl = 3; + optional google.protobuf.FloatValue flt = 4; + optional google.protobuf.Int64Value i64 = 5; + optional google.protobuf.UInt64Value u64 = 6; + optional google.protobuf.Int32Value i32 = 7; + optional google.protobuf.UInt32Value u32 = 8; + optional google.protobuf.BoolValue bool = 9; + optional google.protobuf.StringValue str = 10; + optional google.protobuf.BytesValue bytes = 11; +} diff --git a/vendor/github.com/golang/protobuf/proto/Makefile b/vendor/github.com/golang/protobuf/proto/Makefile new file mode 100644 index 00000000..e2e0651a --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/Makefile @@ -0,0 +1,43 @@ +# Go support for Protocol Buffers - Google's data interchange format +# +# Copyright 2010 The Go Authors. All rights reserved. +# https://github.com/golang/protobuf +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# 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 +# OWNER 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. + +install: + go install + +test: install generate-test-pbs + go test + + +generate-test-pbs: + make install + make -C testdata + protoc --go_out=Mtestdata/test.proto=github.com/golang/protobuf/proto/testdata,Mgoogle/protobuf/any.proto=github.com/golang/protobuf/ptypes/any:. proto3_proto/proto3.proto + make diff --git a/vendor/github.com/golang/protobuf/proto/all_test.go b/vendor/github.com/golang/protobuf/proto/all_test.go new file mode 100644 index 00000000..41451a40 --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/all_test.go @@ -0,0 +1,2278 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2010 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// 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 +// OWNER 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. + +package proto_test + +import ( + "bytes" + "encoding/json" + "errors" + "fmt" + "math" + "math/rand" + "reflect" + "runtime/debug" + "strings" + "testing" + "time" + + . "github.com/golang/protobuf/proto" + . "github.com/golang/protobuf/proto/testdata" +) + +var globalO *Buffer + +func old() *Buffer { + if globalO == nil { + globalO = NewBuffer(nil) + } + globalO.Reset() + return globalO +} + +func equalbytes(b1, b2 []byte, t *testing.T) { + if len(b1) != len(b2) { + t.Errorf("wrong lengths: 2*%d != %d", len(b1), len(b2)) + return + } + for i := 0; i < len(b1); i++ { + if b1[i] != b2[i] { + t.Errorf("bad byte[%d]:%x %x: %s %s", i, b1[i], b2[i], b1, b2) + } + } +} + +func initGoTestField() *GoTestField { + f := new(GoTestField) + f.Label = String("label") + f.Type = String("type") + return f +} + +// These are all structurally equivalent but the tag numbers differ. +// (It's remarkable that required, optional, and repeated all have +// 8 letters.) +func initGoTest_RequiredGroup() *GoTest_RequiredGroup { + return &GoTest_RequiredGroup{ + RequiredField: String("required"), + } +} + +func initGoTest_OptionalGroup() *GoTest_OptionalGroup { + return &GoTest_OptionalGroup{ + RequiredField: String("optional"), + } +} + +func initGoTest_RepeatedGroup() *GoTest_RepeatedGroup { + return &GoTest_RepeatedGroup{ + RequiredField: String("repeated"), + } +} + +func initGoTest(setdefaults bool) *GoTest { + pb := new(GoTest) + if setdefaults { + pb.F_BoolDefaulted = Bool(Default_GoTest_F_BoolDefaulted) + pb.F_Int32Defaulted = Int32(Default_GoTest_F_Int32Defaulted) + pb.F_Int64Defaulted = Int64(Default_GoTest_F_Int64Defaulted) + pb.F_Fixed32Defaulted = Uint32(Default_GoTest_F_Fixed32Defaulted) + pb.F_Fixed64Defaulted = Uint64(Default_GoTest_F_Fixed64Defaulted) + pb.F_Uint32Defaulted = Uint32(Default_GoTest_F_Uint32Defaulted) + pb.F_Uint64Defaulted = Uint64(Default_GoTest_F_Uint64Defaulted) + pb.F_FloatDefaulted = Float32(Default_GoTest_F_FloatDefaulted) + pb.F_DoubleDefaulted = Float64(Default_GoTest_F_DoubleDefaulted) + pb.F_StringDefaulted = String(Default_GoTest_F_StringDefaulted) + pb.F_BytesDefaulted = Default_GoTest_F_BytesDefaulted + pb.F_Sint32Defaulted = Int32(Default_GoTest_F_Sint32Defaulted) + pb.F_Sint64Defaulted = Int64(Default_GoTest_F_Sint64Defaulted) + } + + pb.Kind = GoTest_TIME.Enum() + pb.RequiredField = initGoTestField() + pb.F_BoolRequired = Bool(true) + pb.F_Int32Required = Int32(3) + pb.F_Int64Required = Int64(6) + pb.F_Fixed32Required = Uint32(32) + pb.F_Fixed64Required = Uint64(64) + pb.F_Uint32Required = Uint32(3232) + pb.F_Uint64Required = Uint64(6464) + pb.F_FloatRequired = Float32(3232) + pb.F_DoubleRequired = Float64(6464) + pb.F_StringRequired = String("string") + pb.F_BytesRequired = []byte("bytes") + pb.F_Sint32Required = Int32(-32) + pb.F_Sint64Required = Int64(-64) + pb.Requiredgroup = initGoTest_RequiredGroup() + + return pb +} + +func fail(msg string, b *bytes.Buffer, s string, t *testing.T) { + data := b.Bytes() + ld := len(data) + ls := len(s) / 2 + + fmt.Printf("fail %s ld=%d ls=%d\n", msg, ld, ls) + + // find the interesting spot - n + n := ls + if ld < ls { + n = ld + } + j := 0 + for i := 0; i < n; i++ { + bs := hex(s[j])*16 + hex(s[j+1]) + j += 2 + if data[i] == bs { + continue + } + n = i + break + } + l := n - 10 + if l < 0 { + l = 0 + } + h := n + 10 + + // find the interesting spot - n + fmt.Printf("is[%d]:", l) + for i := l; i < h; i++ { + if i >= ld { + fmt.Printf(" --") + continue + } + fmt.Printf(" %.2x", data[i]) + } + fmt.Printf("\n") + + fmt.Printf("sb[%d]:", l) + for i := l; i < h; i++ { + if i >= ls { + fmt.Printf(" --") + continue + } + bs := hex(s[j])*16 + hex(s[j+1]) + j += 2 + fmt.Printf(" %.2x", bs) + } + fmt.Printf("\n") + + t.Fail() + + // t.Errorf("%s: \ngood: %s\nbad: %x", msg, s, b.Bytes()) + // Print the output in a partially-decoded format; can + // be helpful when updating the test. It produces the output + // that is pasted, with minor edits, into the argument to verify(). + // data := b.Bytes() + // nesting := 0 + // for b.Len() > 0 { + // start := len(data) - b.Len() + // var u uint64 + // u, err := DecodeVarint(b) + // if err != nil { + // fmt.Printf("decode error on varint:", err) + // return + // } + // wire := u & 0x7 + // tag := u >> 3 + // switch wire { + // case WireVarint: + // v, err := DecodeVarint(b) + // if err != nil { + // fmt.Printf("decode error on varint:", err) + // return + // } + // fmt.Printf("\t\t\"%x\" // field %d, encoding %d, value %d\n", + // data[start:len(data)-b.Len()], tag, wire, v) + // case WireFixed32: + // v, err := DecodeFixed32(b) + // if err != nil { + // fmt.Printf("decode error on fixed32:", err) + // return + // } + // fmt.Printf("\t\t\"%x\" // field %d, encoding %d, value %d\n", + // data[start:len(data)-b.Len()], tag, wire, v) + // case WireFixed64: + // v, err := DecodeFixed64(b) + // if err != nil { + // fmt.Printf("decode error on fixed64:", err) + // return + // } + // fmt.Printf("\t\t\"%x\" // field %d, encoding %d, value %d\n", + // data[start:len(data)-b.Len()], tag, wire, v) + // case WireBytes: + // nb, err := DecodeVarint(b) + // if err != nil { + // fmt.Printf("decode error on bytes:", err) + // return + // } + // after_tag := len(data) - b.Len() + // str := make([]byte, nb) + // _, err = b.Read(str) + // if err != nil { + // fmt.Printf("decode error on bytes:", err) + // return + // } + // fmt.Printf("\t\t\"%x\" \"%x\" // field %d, encoding %d (FIELD)\n", + // data[start:after_tag], str, tag, wire) + // case WireStartGroup: + // nesting++ + // fmt.Printf("\t\t\"%x\"\t\t// start group field %d level %d\n", + // data[start:len(data)-b.Len()], tag, nesting) + // case WireEndGroup: + // fmt.Printf("\t\t\"%x\"\t\t// end group field %d level %d\n", + // data[start:len(data)-b.Len()], tag, nesting) + // nesting-- + // default: + // fmt.Printf("unrecognized wire type %d\n", wire) + // return + // } + // } +} + +func hex(c uint8) uint8 { + if '0' <= c && c <= '9' { + return c - '0' + } + if 'a' <= c && c <= 'f' { + return 10 + c - 'a' + } + if 'A' <= c && c <= 'F' { + return 10 + c - 'A' + } + return 0 +} + +func equal(b []byte, s string, t *testing.T) bool { + if 2*len(b) != len(s) { + // fail(fmt.Sprintf("wrong lengths: 2*%d != %d", len(b), len(s)), b, s, t) + fmt.Printf("wrong lengths: 2*%d != %d\n", len(b), len(s)) + return false + } + for i, j := 0, 0; i < len(b); i, j = i+1, j+2 { + x := hex(s[j])*16 + hex(s[j+1]) + if b[i] != x { + // fail(fmt.Sprintf("bad byte[%d]:%x %x", i, b[i], x), b, s, t) + fmt.Printf("bad byte[%d]:%x %x", i, b[i], x) + return false + } + } + return true +} + +func overify(t *testing.T, pb *GoTest, expected string) { + o := old() + err := o.Marshal(pb) + if err != nil { + fmt.Printf("overify marshal-1 err = %v", err) + o.DebugPrint("", o.Bytes()) + t.Fatalf("expected = %s", expected) + } + if !equal(o.Bytes(), expected, t) { + o.DebugPrint("overify neq 1", o.Bytes()) + t.Fatalf("expected = %s", expected) + } + + // Now test Unmarshal by recreating the original buffer. + pbd := new(GoTest) + err = o.Unmarshal(pbd) + if err != nil { + t.Fatalf("overify unmarshal err = %v", err) + o.DebugPrint("", o.Bytes()) + t.Fatalf("string = %s", expected) + } + o.Reset() + err = o.Marshal(pbd) + if err != nil { + t.Errorf("overify marshal-2 err = %v", err) + o.DebugPrint("", o.Bytes()) + t.Fatalf("string = %s", expected) + } + if !equal(o.Bytes(), expected, t) { + o.DebugPrint("overify neq 2", o.Bytes()) + t.Fatalf("string = %s", expected) + } +} + +// Simple tests for numeric encode/decode primitives (varint, etc.) +func TestNumericPrimitives(t *testing.T) { + for i := uint64(0); i < 1e6; i += 111 { + o := old() + if o.EncodeVarint(i) != nil { + t.Error("EncodeVarint") + break + } + x, e := o.DecodeVarint() + if e != nil { + t.Fatal("DecodeVarint") + } + if x != i { + t.Fatal("varint decode fail:", i, x) + } + + o = old() + if o.EncodeFixed32(i) != nil { + t.Fatal("encFixed32") + } + x, e = o.DecodeFixed32() + if e != nil { + t.Fatal("decFixed32") + } + if x != i { + t.Fatal("fixed32 decode fail:", i, x) + } + + o = old() + if o.EncodeFixed64(i*1234567) != nil { + t.Error("encFixed64") + break + } + x, e = o.DecodeFixed64() + if e != nil { + t.Error("decFixed64") + break + } + if x != i*1234567 { + t.Error("fixed64 decode fail:", i*1234567, x) + break + } + + o = old() + i32 := int32(i - 12345) + if o.EncodeZigzag32(uint64(i32)) != nil { + t.Fatal("EncodeZigzag32") + } + x, e = o.DecodeZigzag32() + if e != nil { + t.Fatal("DecodeZigzag32") + } + if x != uint64(uint32(i32)) { + t.Fatal("zigzag32 decode fail:", i32, x) + } + + o = old() + i64 := int64(i - 12345) + if o.EncodeZigzag64(uint64(i64)) != nil { + t.Fatal("EncodeZigzag64") + } + x, e = o.DecodeZigzag64() + if e != nil { + t.Fatal("DecodeZigzag64") + } + if x != uint64(i64) { + t.Fatal("zigzag64 decode fail:", i64, x) + } + } +} + +// fakeMarshaler is a simple struct implementing Marshaler and Message interfaces. +type fakeMarshaler struct { + b []byte + err error +} + +func (f *fakeMarshaler) Marshal() ([]byte, error) { return f.b, f.err } +func (f *fakeMarshaler) String() string { return fmt.Sprintf("Bytes: %v Error: %v", f.b, f.err) } +func (f *fakeMarshaler) ProtoMessage() {} +func (f *fakeMarshaler) Reset() {} + +type msgWithFakeMarshaler struct { + M *fakeMarshaler `protobuf:"bytes,1,opt,name=fake"` +} + +func (m *msgWithFakeMarshaler) String() string { return CompactTextString(m) } +func (m *msgWithFakeMarshaler) ProtoMessage() {} +func (m *msgWithFakeMarshaler) Reset() {} + +// Simple tests for proto messages that implement the Marshaler interface. +func TestMarshalerEncoding(t *testing.T) { + tests := []struct { + name string + m Message + want []byte + errType reflect.Type + }{ + { + name: "Marshaler that fails", + m: &fakeMarshaler{ + err: errors.New("some marshal err"), + b: []byte{5, 6, 7}, + }, + // Since the Marshal method returned bytes, they should be written to the + // buffer. (For efficiency, we assume that Marshal implementations are + // always correct w.r.t. RequiredNotSetError and output.) + want: []byte{5, 6, 7}, + errType: reflect.TypeOf(errors.New("some marshal err")), + }, + { + name: "Marshaler that fails with RequiredNotSetError", + m: &msgWithFakeMarshaler{ + M: &fakeMarshaler{ + err: &RequiredNotSetError{}, + b: []byte{5, 6, 7}, + }, + }, + // Since there's an error that can be continued after, + // the buffer should be written. + want: []byte{ + 10, 3, // for &msgWithFakeMarshaler + 5, 6, 7, // for &fakeMarshaler + }, + errType: reflect.TypeOf(&RequiredNotSetError{}), + }, + { + name: "Marshaler that succeeds", + m: &fakeMarshaler{ + b: []byte{0, 1, 2, 3, 4, 127, 255}, + }, + want: []byte{0, 1, 2, 3, 4, 127, 255}, + }, + } + for _, test := range tests { + b := NewBuffer(nil) + err := b.Marshal(test.m) + if reflect.TypeOf(err) != test.errType { + t.Errorf("%s: got err %T(%v) wanted %T", test.name, err, err, test.errType) + } + if !reflect.DeepEqual(test.want, b.Bytes()) { + t.Errorf("%s: got bytes %v wanted %v", test.name, b.Bytes(), test.want) + } + if size := Size(test.m); size != len(b.Bytes()) { + t.Errorf("%s: Size(_) = %v, but marshaled to %v bytes", test.name, size, len(b.Bytes())) + } + + m, mErr := Marshal(test.m) + if !bytes.Equal(b.Bytes(), m) { + t.Errorf("%s: Marshal returned %v, but (*Buffer).Marshal wrote %v", test.name, m, b.Bytes()) + } + if !reflect.DeepEqual(err, mErr) { + t.Errorf("%s: Marshal err = %q, but (*Buffer).Marshal returned %q", + test.name, fmt.Sprint(mErr), fmt.Sprint(err)) + } + } +} + +// Simple tests for bytes +func TestBytesPrimitives(t *testing.T) { + o := old() + bytes := []byte{'n', 'o', 'w', ' ', 'i', 's', ' ', 't', 'h', 'e', ' ', 't', 'i', 'm', 'e'} + if o.EncodeRawBytes(bytes) != nil { + t.Error("EncodeRawBytes") + } + decb, e := o.DecodeRawBytes(false) + if e != nil { + t.Error("DecodeRawBytes") + } + equalbytes(bytes, decb, t) +} + +// Simple tests for strings +func TestStringPrimitives(t *testing.T) { + o := old() + s := "now is the time" + if o.EncodeStringBytes(s) != nil { + t.Error("enc_string") + } + decs, e := o.DecodeStringBytes() + if e != nil { + t.Error("dec_string") + } + if s != decs { + t.Error("string encode/decode fail:", s, decs) + } +} + +// Do we catch the "required bit not set" case? +func TestRequiredBit(t *testing.T) { + o := old() + pb := new(GoTest) + err := o.Marshal(pb) + if err == nil { + t.Error("did not catch missing required fields") + } else if strings.Index(err.Error(), "Kind") < 0 { + t.Error("wrong error type:", err) + } +} + +// Check that all fields are nil. +// Clearly silly, and a residue from a more interesting test with an earlier, +// different initialization property, but it once caught a compiler bug so +// it lives. +func checkInitialized(pb *GoTest, t *testing.T) { + if pb.F_BoolDefaulted != nil { + t.Error("New or Reset did not set boolean:", *pb.F_BoolDefaulted) + } + if pb.F_Int32Defaulted != nil { + t.Error("New or Reset did not set int32:", *pb.F_Int32Defaulted) + } + if pb.F_Int64Defaulted != nil { + t.Error("New or Reset did not set int64:", *pb.F_Int64Defaulted) + } + if pb.F_Fixed32Defaulted != nil { + t.Error("New or Reset did not set fixed32:", *pb.F_Fixed32Defaulted) + } + if pb.F_Fixed64Defaulted != nil { + t.Error("New or Reset did not set fixed64:", *pb.F_Fixed64Defaulted) + } + if pb.F_Uint32Defaulted != nil { + t.Error("New or Reset did not set uint32:", *pb.F_Uint32Defaulted) + } + if pb.F_Uint64Defaulted != nil { + t.Error("New or Reset did not set uint64:", *pb.F_Uint64Defaulted) + } + if pb.F_FloatDefaulted != nil { + t.Error("New or Reset did not set float:", *pb.F_FloatDefaulted) + } + if pb.F_DoubleDefaulted != nil { + t.Error("New or Reset did not set double:", *pb.F_DoubleDefaulted) + } + if pb.F_StringDefaulted != nil { + t.Error("New or Reset did not set string:", *pb.F_StringDefaulted) + } + if pb.F_BytesDefaulted != nil { + t.Error("New or Reset did not set bytes:", string(pb.F_BytesDefaulted)) + } + if pb.F_Sint32Defaulted != nil { + t.Error("New or Reset did not set int32:", *pb.F_Sint32Defaulted) + } + if pb.F_Sint64Defaulted != nil { + t.Error("New or Reset did not set int64:", *pb.F_Sint64Defaulted) + } +} + +// Does Reset() reset? +func TestReset(t *testing.T) { + pb := initGoTest(true) + // muck with some values + pb.F_BoolDefaulted = Bool(false) + pb.F_Int32Defaulted = Int32(237) + pb.F_Int64Defaulted = Int64(12346) + pb.F_Fixed32Defaulted = Uint32(32000) + pb.F_Fixed64Defaulted = Uint64(666) + pb.F_Uint32Defaulted = Uint32(323232) + pb.F_Uint64Defaulted = nil + pb.F_FloatDefaulted = nil + pb.F_DoubleDefaulted = Float64(0) + pb.F_StringDefaulted = String("gotcha") + pb.F_BytesDefaulted = []byte("asdfasdf") + pb.F_Sint32Defaulted = Int32(123) + pb.F_Sint64Defaulted = Int64(789) + pb.Reset() + checkInitialized(pb, t) +} + +// All required fields set, no defaults provided. +func TestEncodeDecode1(t *testing.T) { + pb := initGoTest(false) + overify(t, pb, + "0807"+ // field 1, encoding 0, value 7 + "220d"+"0a056c6162656c120474797065"+ // field 4, encoding 2 (GoTestField) + "5001"+ // field 10, encoding 0, value 1 + "5803"+ // field 11, encoding 0, value 3 + "6006"+ // field 12, encoding 0, value 6 + "6d20000000"+ // field 13, encoding 5, value 0x20 + "714000000000000000"+ // field 14, encoding 1, value 0x40 + "78a019"+ // field 15, encoding 0, value 0xca0 = 3232 + "8001c032"+ // field 16, encoding 0, value 0x1940 = 6464 + "8d0100004a45"+ // field 17, encoding 5, value 3232.0 + "9101000000000040b940"+ // field 18, encoding 1, value 6464.0 + "9a0106"+"737472696e67"+ // field 19, encoding 2, string "string" + "b304"+ // field 70, encoding 3, start group + "ba0408"+"7265717569726564"+ // field 71, encoding 2, string "required" + "b404"+ // field 70, encoding 4, end group + "aa0605"+"6279746573"+ // field 101, encoding 2, string "bytes" + "b0063f"+ // field 102, encoding 0, 0x3f zigzag32 + "b8067f") // field 103, encoding 0, 0x7f zigzag64 +} + +// All required fields set, defaults provided. +func TestEncodeDecode2(t *testing.T) { + pb := initGoTest(true) + overify(t, pb, + "0807"+ // field 1, encoding 0, value 7 + "220d"+"0a056c6162656c120474797065"+ // field 4, encoding 2 (GoTestField) + "5001"+ // field 10, encoding 0, value 1 + "5803"+ // field 11, encoding 0, value 3 + "6006"+ // field 12, encoding 0, value 6 + "6d20000000"+ // field 13, encoding 5, value 32 + "714000000000000000"+ // field 14, encoding 1, value 64 + "78a019"+ // field 15, encoding 0, value 3232 + "8001c032"+ // field 16, encoding 0, value 6464 + "8d0100004a45"+ // field 17, encoding 5, value 3232.0 + "9101000000000040b940"+ // field 18, encoding 1, value 6464.0 + "9a0106"+"737472696e67"+ // field 19, encoding 2 string "string" + "c00201"+ // field 40, encoding 0, value 1 + "c80220"+ // field 41, encoding 0, value 32 + "d00240"+ // field 42, encoding 0, value 64 + "dd0240010000"+ // field 43, encoding 5, value 320 + "e1028002000000000000"+ // field 44, encoding 1, value 640 + "e8028019"+ // field 45, encoding 0, value 3200 + "f0028032"+ // field 46, encoding 0, value 6400 + "fd02e0659948"+ // field 47, encoding 5, value 314159.0 + "81030000000050971041"+ // field 48, encoding 1, value 271828.0 + "8a0310"+"68656c6c6f2c2022776f726c6421220a"+ // field 49, encoding 2 string "hello, \"world!\"\n" + "b304"+ // start group field 70 level 1 + "ba0408"+"7265717569726564"+ // field 71, encoding 2, string "required" + "b404"+ // end group field 70 level 1 + "aa0605"+"6279746573"+ // field 101, encoding 2 string "bytes" + "b0063f"+ // field 102, encoding 0, 0x3f zigzag32 + "b8067f"+ // field 103, encoding 0, 0x7f zigzag64 + "8a1907"+"4269676e6f7365"+ // field 401, encoding 2, string "Bignose" + "90193f"+ // field 402, encoding 0, value 63 + "98197f") // field 403, encoding 0, value 127 + +} + +// All default fields set to their default value by hand +func TestEncodeDecode3(t *testing.T) { + pb := initGoTest(false) + pb.F_BoolDefaulted = Bool(true) + pb.F_Int32Defaulted = Int32(32) + pb.F_Int64Defaulted = Int64(64) + pb.F_Fixed32Defaulted = Uint32(320) + pb.F_Fixed64Defaulted = Uint64(640) + pb.F_Uint32Defaulted = Uint32(3200) + pb.F_Uint64Defaulted = Uint64(6400) + pb.F_FloatDefaulted = Float32(314159) + pb.F_DoubleDefaulted = Float64(271828) + pb.F_StringDefaulted = String("hello, \"world!\"\n") + pb.F_BytesDefaulted = []byte("Bignose") + pb.F_Sint32Defaulted = Int32(-32) + pb.F_Sint64Defaulted = Int64(-64) + + overify(t, pb, + "0807"+ // field 1, encoding 0, value 7 + "220d"+"0a056c6162656c120474797065"+ // field 4, encoding 2 (GoTestField) + "5001"+ // field 10, encoding 0, value 1 + "5803"+ // field 11, encoding 0, value 3 + "6006"+ // field 12, encoding 0, value 6 + "6d20000000"+ // field 13, encoding 5, value 32 + "714000000000000000"+ // field 14, encoding 1, value 64 + "78a019"+ // field 15, encoding 0, value 3232 + "8001c032"+ // field 16, encoding 0, value 6464 + "8d0100004a45"+ // field 17, encoding 5, value 3232.0 + "9101000000000040b940"+ // field 18, encoding 1, value 6464.0 + "9a0106"+"737472696e67"+ // field 19, encoding 2 string "string" + "c00201"+ // field 40, encoding 0, value 1 + "c80220"+ // field 41, encoding 0, value 32 + "d00240"+ // field 42, encoding 0, value 64 + "dd0240010000"+ // field 43, encoding 5, value 320 + "e1028002000000000000"+ // field 44, encoding 1, value 640 + "e8028019"+ // field 45, encoding 0, value 3200 + "f0028032"+ // field 46, encoding 0, value 6400 + "fd02e0659948"+ // field 47, encoding 5, value 314159.0 + "81030000000050971041"+ // field 48, encoding 1, value 271828.0 + "8a0310"+"68656c6c6f2c2022776f726c6421220a"+ // field 49, encoding 2 string "hello, \"world!\"\n" + "b304"+ // start group field 70 level 1 + "ba0408"+"7265717569726564"+ // field 71, encoding 2, string "required" + "b404"+ // end group field 70 level 1 + "aa0605"+"6279746573"+ // field 101, encoding 2 string "bytes" + "b0063f"+ // field 102, encoding 0, 0x3f zigzag32 + "b8067f"+ // field 103, encoding 0, 0x7f zigzag64 + "8a1907"+"4269676e6f7365"+ // field 401, encoding 2, string "Bignose" + "90193f"+ // field 402, encoding 0, value 63 + "98197f") // field 403, encoding 0, value 127 + +} + +// All required fields set, defaults provided, all non-defaulted optional fields have values. +func TestEncodeDecode4(t *testing.T) { + pb := initGoTest(true) + pb.Table = String("hello") + pb.Param = Int32(7) + pb.OptionalField = initGoTestField() + pb.F_BoolOptional = Bool(true) + pb.F_Int32Optional = Int32(32) + pb.F_Int64Optional = Int64(64) + pb.F_Fixed32Optional = Uint32(3232) + pb.F_Fixed64Optional = Uint64(6464) + pb.F_Uint32Optional = Uint32(323232) + pb.F_Uint64Optional = Uint64(646464) + pb.F_FloatOptional = Float32(32.) + pb.F_DoubleOptional = Float64(64.) + pb.F_StringOptional = String("hello") + pb.F_BytesOptional = []byte("Bignose") + pb.F_Sint32Optional = Int32(-32) + pb.F_Sint64Optional = Int64(-64) + pb.Optionalgroup = initGoTest_OptionalGroup() + + overify(t, pb, + "0807"+ // field 1, encoding 0, value 7 + "1205"+"68656c6c6f"+ // field 2, encoding 2, string "hello" + "1807"+ // field 3, encoding 0, value 7 + "220d"+"0a056c6162656c120474797065"+ // field 4, encoding 2 (GoTestField) + "320d"+"0a056c6162656c120474797065"+ // field 6, encoding 2 (GoTestField) + "5001"+ // field 10, encoding 0, value 1 + "5803"+ // field 11, encoding 0, value 3 + "6006"+ // field 12, encoding 0, value 6 + "6d20000000"+ // field 13, encoding 5, value 32 + "714000000000000000"+ // field 14, encoding 1, value 64 + "78a019"+ // field 15, encoding 0, value 3232 + "8001c032"+ // field 16, encoding 0, value 6464 + "8d0100004a45"+ // field 17, encoding 5, value 3232.0 + "9101000000000040b940"+ // field 18, encoding 1, value 6464.0 + "9a0106"+"737472696e67"+ // field 19, encoding 2 string "string" + "f00101"+ // field 30, encoding 0, value 1 + "f80120"+ // field 31, encoding 0, value 32 + "800240"+ // field 32, encoding 0, value 64 + "8d02a00c0000"+ // field 33, encoding 5, value 3232 + "91024019000000000000"+ // field 34, encoding 1, value 6464 + "9802a0dd13"+ // field 35, encoding 0, value 323232 + "a002c0ba27"+ // field 36, encoding 0, value 646464 + "ad0200000042"+ // field 37, encoding 5, value 32.0 + "b1020000000000005040"+ // field 38, encoding 1, value 64.0 + "ba0205"+"68656c6c6f"+ // field 39, encoding 2, string "hello" + "c00201"+ // field 40, encoding 0, value 1 + "c80220"+ // field 41, encoding 0, value 32 + "d00240"+ // field 42, encoding 0, value 64 + "dd0240010000"+ // field 43, encoding 5, value 320 + "e1028002000000000000"+ // field 44, encoding 1, value 640 + "e8028019"+ // field 45, encoding 0, value 3200 + "f0028032"+ // field 46, encoding 0, value 6400 + "fd02e0659948"+ // field 47, encoding 5, value 314159.0 + "81030000000050971041"+ // field 48, encoding 1, value 271828.0 + "8a0310"+"68656c6c6f2c2022776f726c6421220a"+ // field 49, encoding 2 string "hello, \"world!\"\n" + "b304"+ // start group field 70 level 1 + "ba0408"+"7265717569726564"+ // field 71, encoding 2, string "required" + "b404"+ // end group field 70 level 1 + "d305"+ // start group field 90 level 1 + "da0508"+"6f7074696f6e616c"+ // field 91, encoding 2, string "optional" + "d405"+ // end group field 90 level 1 + "aa0605"+"6279746573"+ // field 101, encoding 2 string "bytes" + "b0063f"+ // field 102, encoding 0, 0x3f zigzag32 + "b8067f"+ // field 103, encoding 0, 0x7f zigzag64 + "ea1207"+"4269676e6f7365"+ // field 301, encoding 2, string "Bignose" + "f0123f"+ // field 302, encoding 0, value 63 + "f8127f"+ // field 303, encoding 0, value 127 + "8a1907"+"4269676e6f7365"+ // field 401, encoding 2, string "Bignose" + "90193f"+ // field 402, encoding 0, value 63 + "98197f") // field 403, encoding 0, value 127 + +} + +// All required fields set, defaults provided, all repeated fields given two values. +func TestEncodeDecode5(t *testing.T) { + pb := initGoTest(true) + pb.RepeatedField = []*GoTestField{initGoTestField(), initGoTestField()} + pb.F_BoolRepeated = []bool{false, true} + pb.F_Int32Repeated = []int32{32, 33} + pb.F_Int64Repeated = []int64{64, 65} + pb.F_Fixed32Repeated = []uint32{3232, 3333} + pb.F_Fixed64Repeated = []uint64{6464, 6565} + pb.F_Uint32Repeated = []uint32{323232, 333333} + pb.F_Uint64Repeated = []uint64{646464, 656565} + pb.F_FloatRepeated = []float32{32., 33.} + pb.F_DoubleRepeated = []float64{64., 65.} + pb.F_StringRepeated = []string{"hello", "sailor"} + pb.F_BytesRepeated = [][]byte{[]byte("big"), []byte("nose")} + pb.F_Sint32Repeated = []int32{32, -32} + pb.F_Sint64Repeated = []int64{64, -64} + pb.Repeatedgroup = []*GoTest_RepeatedGroup{initGoTest_RepeatedGroup(), initGoTest_RepeatedGroup()} + + overify(t, pb, + "0807"+ // field 1, encoding 0, value 7 + "220d"+"0a056c6162656c120474797065"+ // field 4, encoding 2 (GoTestField) + "2a0d"+"0a056c6162656c120474797065"+ // field 5, encoding 2 (GoTestField) + "2a0d"+"0a056c6162656c120474797065"+ // field 5, encoding 2 (GoTestField) + "5001"+ // field 10, encoding 0, value 1 + "5803"+ // field 11, encoding 0, value 3 + "6006"+ // field 12, encoding 0, value 6 + "6d20000000"+ // field 13, encoding 5, value 32 + "714000000000000000"+ // field 14, encoding 1, value 64 + "78a019"+ // field 15, encoding 0, value 3232 + "8001c032"+ // field 16, encoding 0, value 6464 + "8d0100004a45"+ // field 17, encoding 5, value 3232.0 + "9101000000000040b940"+ // field 18, encoding 1, value 6464.0 + "9a0106"+"737472696e67"+ // field 19, encoding 2 string "string" + "a00100"+ // field 20, encoding 0, value 0 + "a00101"+ // field 20, encoding 0, value 1 + "a80120"+ // field 21, encoding 0, value 32 + "a80121"+ // field 21, encoding 0, value 33 + "b00140"+ // field 22, encoding 0, value 64 + "b00141"+ // field 22, encoding 0, value 65 + "bd01a00c0000"+ // field 23, encoding 5, value 3232 + "bd01050d0000"+ // field 23, encoding 5, value 3333 + "c1014019000000000000"+ // field 24, encoding 1, value 6464 + "c101a519000000000000"+ // field 24, encoding 1, value 6565 + "c801a0dd13"+ // field 25, encoding 0, value 323232 + "c80195ac14"+ // field 25, encoding 0, value 333333 + "d001c0ba27"+ // field 26, encoding 0, value 646464 + "d001b58928"+ // field 26, encoding 0, value 656565 + "dd0100000042"+ // field 27, encoding 5, value 32.0 + "dd0100000442"+ // field 27, encoding 5, value 33.0 + "e1010000000000005040"+ // field 28, encoding 1, value 64.0 + "e1010000000000405040"+ // field 28, encoding 1, value 65.0 + "ea0105"+"68656c6c6f"+ // field 29, encoding 2, string "hello" + "ea0106"+"7361696c6f72"+ // field 29, encoding 2, string "sailor" + "c00201"+ // field 40, encoding 0, value 1 + "c80220"+ // field 41, encoding 0, value 32 + "d00240"+ // field 42, encoding 0, value 64 + "dd0240010000"+ // field 43, encoding 5, value 320 + "e1028002000000000000"+ // field 44, encoding 1, value 640 + "e8028019"+ // field 45, encoding 0, value 3200 + "f0028032"+ // field 46, encoding 0, value 6400 + "fd02e0659948"+ // field 47, encoding 5, value 314159.0 + "81030000000050971041"+ // field 48, encoding 1, value 271828.0 + "8a0310"+"68656c6c6f2c2022776f726c6421220a"+ // field 49, encoding 2 string "hello, \"world!\"\n" + "b304"+ // start group field 70 level 1 + "ba0408"+"7265717569726564"+ // field 71, encoding 2, string "required" + "b404"+ // end group field 70 level 1 + "8305"+ // start group field 80 level 1 + "8a0508"+"7265706561746564"+ // field 81, encoding 2, string "repeated" + "8405"+ // end group field 80 level 1 + "8305"+ // start group field 80 level 1 + "8a0508"+"7265706561746564"+ // field 81, encoding 2, string "repeated" + "8405"+ // end group field 80 level 1 + "aa0605"+"6279746573"+ // field 101, encoding 2 string "bytes" + "b0063f"+ // field 102, encoding 0, 0x3f zigzag32 + "b8067f"+ // field 103, encoding 0, 0x7f zigzag64 + "ca0c03"+"626967"+ // field 201, encoding 2, string "big" + "ca0c04"+"6e6f7365"+ // field 201, encoding 2, string "nose" + "d00c40"+ // field 202, encoding 0, value 32 + "d00c3f"+ // field 202, encoding 0, value -32 + "d80c8001"+ // field 203, encoding 0, value 64 + "d80c7f"+ // field 203, encoding 0, value -64 + "8a1907"+"4269676e6f7365"+ // field 401, encoding 2, string "Bignose" + "90193f"+ // field 402, encoding 0, value 63 + "98197f") // field 403, encoding 0, value 127 + +} + +// All required fields set, all packed repeated fields given two values. +func TestEncodeDecode6(t *testing.T) { + pb := initGoTest(false) + pb.F_BoolRepeatedPacked = []bool{false, true} + pb.F_Int32RepeatedPacked = []int32{32, 33} + pb.F_Int64RepeatedPacked = []int64{64, 65} + pb.F_Fixed32RepeatedPacked = []uint32{3232, 3333} + pb.F_Fixed64RepeatedPacked = []uint64{6464, 6565} + pb.F_Uint32RepeatedPacked = []uint32{323232, 333333} + pb.F_Uint64RepeatedPacked = []uint64{646464, 656565} + pb.F_FloatRepeatedPacked = []float32{32., 33.} + pb.F_DoubleRepeatedPacked = []float64{64., 65.} + pb.F_Sint32RepeatedPacked = []int32{32, -32} + pb.F_Sint64RepeatedPacked = []int64{64, -64} + + overify(t, pb, + "0807"+ // field 1, encoding 0, value 7 + "220d"+"0a056c6162656c120474797065"+ // field 4, encoding 2 (GoTestField) + "5001"+ // field 10, encoding 0, value 1 + "5803"+ // field 11, encoding 0, value 3 + "6006"+ // field 12, encoding 0, value 6 + "6d20000000"+ // field 13, encoding 5, value 32 + "714000000000000000"+ // field 14, encoding 1, value 64 + "78a019"+ // field 15, encoding 0, value 3232 + "8001c032"+ // field 16, encoding 0, value 6464 + "8d0100004a45"+ // field 17, encoding 5, value 3232.0 + "9101000000000040b940"+ // field 18, encoding 1, value 6464.0 + "9a0106"+"737472696e67"+ // field 19, encoding 2 string "string" + "9203020001"+ // field 50, encoding 2, 2 bytes, value 0, value 1 + "9a03022021"+ // field 51, encoding 2, 2 bytes, value 32, value 33 + "a203024041"+ // field 52, encoding 2, 2 bytes, value 64, value 65 + "aa0308"+ // field 53, encoding 2, 8 bytes + "a00c0000050d0000"+ // value 3232, value 3333 + "b20310"+ // field 54, encoding 2, 16 bytes + "4019000000000000a519000000000000"+ // value 6464, value 6565 + "ba0306"+ // field 55, encoding 2, 6 bytes + "a0dd1395ac14"+ // value 323232, value 333333 + "c20306"+ // field 56, encoding 2, 6 bytes + "c0ba27b58928"+ // value 646464, value 656565 + "ca0308"+ // field 57, encoding 2, 8 bytes + "0000004200000442"+ // value 32.0, value 33.0 + "d20310"+ // field 58, encoding 2, 16 bytes + "00000000000050400000000000405040"+ // value 64.0, value 65.0 + "b304"+ // start group field 70 level 1 + "ba0408"+"7265717569726564"+ // field 71, encoding 2, string "required" + "b404"+ // end group field 70 level 1 + "aa0605"+"6279746573"+ // field 101, encoding 2 string "bytes" + "b0063f"+ // field 102, encoding 0, 0x3f zigzag32 + "b8067f"+ // field 103, encoding 0, 0x7f zigzag64 + "b21f02"+ // field 502, encoding 2, 2 bytes + "403f"+ // value 32, value -32 + "ba1f03"+ // field 503, encoding 2, 3 bytes + "80017f") // value 64, value -64 +} + +// Test that we can encode empty bytes fields. +func TestEncodeDecodeBytes1(t *testing.T) { + pb := initGoTest(false) + + // Create our bytes + pb.F_BytesRequired = []byte{} + pb.F_BytesRepeated = [][]byte{{}} + pb.F_BytesOptional = []byte{} + + d, err := Marshal(pb) + if err != nil { + t.Error(err) + } + + pbd := new(GoTest) + if err := Unmarshal(d, pbd); err != nil { + t.Error(err) + } + + if pbd.F_BytesRequired == nil || len(pbd.F_BytesRequired) != 0 { + t.Error("required empty bytes field is incorrect") + } + if pbd.F_BytesRepeated == nil || len(pbd.F_BytesRepeated) == 1 && pbd.F_BytesRepeated[0] == nil { + t.Error("repeated empty bytes field is incorrect") + } + if pbd.F_BytesOptional == nil || len(pbd.F_BytesOptional) != 0 { + t.Error("optional empty bytes field is incorrect") + } +} + +// Test that we encode nil-valued fields of a repeated bytes field correctly. +// Since entries in a repeated field cannot be nil, nil must mean empty value. +func TestEncodeDecodeBytes2(t *testing.T) { + pb := initGoTest(false) + + // Create our bytes + pb.F_BytesRepeated = [][]byte{nil} + + d, err := Marshal(pb) + if err != nil { + t.Error(err) + } + + pbd := new(GoTest) + if err := Unmarshal(d, pbd); err != nil { + t.Error(err) + } + + if len(pbd.F_BytesRepeated) != 1 || pbd.F_BytesRepeated[0] == nil { + t.Error("Unexpected value for repeated bytes field") + } +} + +// All required fields set, defaults provided, all repeated fields given two values. +func TestSkippingUnrecognizedFields(t *testing.T) { + o := old() + pb := initGoTestField() + + // Marshal it normally. + o.Marshal(pb) + + // Now new a GoSkipTest record. + skip := &GoSkipTest{ + SkipInt32: Int32(32), + SkipFixed32: Uint32(3232), + SkipFixed64: Uint64(6464), + SkipString: String("skipper"), + Skipgroup: &GoSkipTest_SkipGroup{ + GroupInt32: Int32(75), + GroupString: String("wxyz"), + }, + } + + // Marshal it into same buffer. + o.Marshal(skip) + + pbd := new(GoTestField) + o.Unmarshal(pbd) + + // The __unrecognized field should be a marshaling of GoSkipTest + skipd := new(GoSkipTest) + + o.SetBuf(pbd.XXX_unrecognized) + o.Unmarshal(skipd) + + if *skipd.SkipInt32 != *skip.SkipInt32 { + t.Error("skip int32", skipd.SkipInt32) + } + if *skipd.SkipFixed32 != *skip.SkipFixed32 { + t.Error("skip fixed32", skipd.SkipFixed32) + } + if *skipd.SkipFixed64 != *skip.SkipFixed64 { + t.Error("skip fixed64", skipd.SkipFixed64) + } + if *skipd.SkipString != *skip.SkipString { + t.Error("skip string", *skipd.SkipString) + } + if *skipd.Skipgroup.GroupInt32 != *skip.Skipgroup.GroupInt32 { + t.Error("skip group int32", skipd.Skipgroup.GroupInt32) + } + if *skipd.Skipgroup.GroupString != *skip.Skipgroup.GroupString { + t.Error("skip group string", *skipd.Skipgroup.GroupString) + } +} + +// Check that unrecognized fields of a submessage are preserved. +func TestSubmessageUnrecognizedFields(t *testing.T) { + nm := &NewMessage{ + Nested: &NewMessage_Nested{ + Name: String("Nigel"), + FoodGroup: String("carbs"), + }, + } + b, err := Marshal(nm) + if err != nil { + t.Fatalf("Marshal of NewMessage: %v", err) + } + + // Unmarshal into an OldMessage. + om := new(OldMessage) + if err := Unmarshal(b, om); err != nil { + t.Fatalf("Unmarshal to OldMessage: %v", err) + } + exp := &OldMessage{ + Nested: &OldMessage_Nested{ + Name: String("Nigel"), + // normal protocol buffer users should not do this + XXX_unrecognized: []byte("\x12\x05carbs"), + }, + } + if !Equal(om, exp) { + t.Errorf("om = %v, want %v", om, exp) + } + + // Clone the OldMessage. + om = Clone(om).(*OldMessage) + if !Equal(om, exp) { + t.Errorf("Clone(om) = %v, want %v", om, exp) + } + + // Marshal the OldMessage, then unmarshal it into an empty NewMessage. + if b, err = Marshal(om); err != nil { + t.Fatalf("Marshal of OldMessage: %v", err) + } + t.Logf("Marshal(%v) -> %q", om, b) + nm2 := new(NewMessage) + if err := Unmarshal(b, nm2); err != nil { + t.Fatalf("Unmarshal to NewMessage: %v", err) + } + if !Equal(nm, nm2) { + t.Errorf("NewMessage round-trip: %v => %v", nm, nm2) + } +} + +// Check that an int32 field can be upgraded to an int64 field. +func TestNegativeInt32(t *testing.T) { + om := &OldMessage{ + Num: Int32(-1), + } + b, err := Marshal(om) + if err != nil { + t.Fatalf("Marshal of OldMessage: %v", err) + } + + // Check the size. It should be 11 bytes; + // 1 for the field/wire type, and 10 for the negative number. + if len(b) != 11 { + t.Errorf("%v marshaled as %q, wanted 11 bytes", om, b) + } + + // Unmarshal into a NewMessage. + nm := new(NewMessage) + if err := Unmarshal(b, nm); err != nil { + t.Fatalf("Unmarshal to NewMessage: %v", err) + } + want := &NewMessage{ + Num: Int64(-1), + } + if !Equal(nm, want) { + t.Errorf("nm = %v, want %v", nm, want) + } +} + +// Check that we can grow an array (repeated field) to have many elements. +// This test doesn't depend only on our encoding; for variety, it makes sure +// we create, encode, and decode the correct contents explicitly. It's therefore +// a bit messier. +// This test also uses (and hence tests) the Marshal/Unmarshal functions +// instead of the methods. +func TestBigRepeated(t *testing.T) { + pb := initGoTest(true) + + // Create the arrays + const N = 50 // Internally the library starts much smaller. + pb.Repeatedgroup = make([]*GoTest_RepeatedGroup, N) + pb.F_Sint64Repeated = make([]int64, N) + pb.F_Sint32Repeated = make([]int32, N) + pb.F_BytesRepeated = make([][]byte, N) + pb.F_StringRepeated = make([]string, N) + pb.F_DoubleRepeated = make([]float64, N) + pb.F_FloatRepeated = make([]float32, N) + pb.F_Uint64Repeated = make([]uint64, N) + pb.F_Uint32Repeated = make([]uint32, N) + pb.F_Fixed64Repeated = make([]uint64, N) + pb.F_Fixed32Repeated = make([]uint32, N) + pb.F_Int64Repeated = make([]int64, N) + pb.F_Int32Repeated = make([]int32, N) + pb.F_BoolRepeated = make([]bool, N) + pb.RepeatedField = make([]*GoTestField, N) + + // Fill in the arrays with checkable values. + igtf := initGoTestField() + igtrg := initGoTest_RepeatedGroup() + for i := 0; i < N; i++ { + pb.Repeatedgroup[i] = igtrg + pb.F_Sint64Repeated[i] = int64(i) + pb.F_Sint32Repeated[i] = int32(i) + s := fmt.Sprint(i) + pb.F_BytesRepeated[i] = []byte(s) + pb.F_StringRepeated[i] = s + pb.F_DoubleRepeated[i] = float64(i) + pb.F_FloatRepeated[i] = float32(i) + pb.F_Uint64Repeated[i] = uint64(i) + pb.F_Uint32Repeated[i] = uint32(i) + pb.F_Fixed64Repeated[i] = uint64(i) + pb.F_Fixed32Repeated[i] = uint32(i) + pb.F_Int64Repeated[i] = int64(i) + pb.F_Int32Repeated[i] = int32(i) + pb.F_BoolRepeated[i] = i%2 == 0 + pb.RepeatedField[i] = igtf + } + + // Marshal. + buf, _ := Marshal(pb) + + // Now test Unmarshal by recreating the original buffer. + pbd := new(GoTest) + Unmarshal(buf, pbd) + + // Check the checkable values + for i := uint64(0); i < N; i++ { + if pbd.Repeatedgroup[i] == nil { // TODO: more checking? + t.Error("pbd.Repeatedgroup bad") + } + var x uint64 + x = uint64(pbd.F_Sint64Repeated[i]) + if x != i { + t.Error("pbd.F_Sint64Repeated bad", x, i) + } + x = uint64(pbd.F_Sint32Repeated[i]) + if x != i { + t.Error("pbd.F_Sint32Repeated bad", x, i) + } + s := fmt.Sprint(i) + equalbytes(pbd.F_BytesRepeated[i], []byte(s), t) + if pbd.F_StringRepeated[i] != s { + t.Error("pbd.F_Sint32Repeated bad", pbd.F_StringRepeated[i], i) + } + x = uint64(pbd.F_DoubleRepeated[i]) + if x != i { + t.Error("pbd.F_DoubleRepeated bad", x, i) + } + x = uint64(pbd.F_FloatRepeated[i]) + if x != i { + t.Error("pbd.F_FloatRepeated bad", x, i) + } + x = pbd.F_Uint64Repeated[i] + if x != i { + t.Error("pbd.F_Uint64Repeated bad", x, i) + } + x = uint64(pbd.F_Uint32Repeated[i]) + if x != i { + t.Error("pbd.F_Uint32Repeated bad", x, i) + } + x = pbd.F_Fixed64Repeated[i] + if x != i { + t.Error("pbd.F_Fixed64Repeated bad", x, i) + } + x = uint64(pbd.F_Fixed32Repeated[i]) + if x != i { + t.Error("pbd.F_Fixed32Repeated bad", x, i) + } + x = uint64(pbd.F_Int64Repeated[i]) + if x != i { + t.Error("pbd.F_Int64Repeated bad", x, i) + } + x = uint64(pbd.F_Int32Repeated[i]) + if x != i { + t.Error("pbd.F_Int32Repeated bad", x, i) + } + if pbd.F_BoolRepeated[i] != (i%2 == 0) { + t.Error("pbd.F_BoolRepeated bad", x, i) + } + if pbd.RepeatedField[i] == nil { // TODO: more checking? + t.Error("pbd.RepeatedField bad") + } + } +} + +// Verify we give a useful message when decoding to the wrong structure type. +func TestTypeMismatch(t *testing.T) { + pb1 := initGoTest(true) + + // Marshal + o := old() + o.Marshal(pb1) + + // Now Unmarshal it to the wrong type. + pb2 := initGoTestField() + err := o.Unmarshal(pb2) + if err == nil { + t.Error("expected error, got no error") + } else if !strings.Contains(err.Error(), "bad wiretype") { + t.Error("expected bad wiretype error, got", err) + } +} + +func encodeDecode(t *testing.T, in, out Message, msg string) { + buf, err := Marshal(in) + if err != nil { + t.Fatalf("failed marshaling %v: %v", msg, err) + } + if err := Unmarshal(buf, out); err != nil { + t.Fatalf("failed unmarshaling %v: %v", msg, err) + } +} + +func TestPackedNonPackedDecoderSwitching(t *testing.T) { + np, p := new(NonPackedTest), new(PackedTest) + + // non-packed -> packed + np.A = []int32{0, 1, 1, 2, 3, 5} + encodeDecode(t, np, p, "non-packed -> packed") + if !reflect.DeepEqual(np.A, p.B) { + t.Errorf("failed non-packed -> packed; np.A=%+v, p.B=%+v", np.A, p.B) + } + + // packed -> non-packed + np.Reset() + p.B = []int32{3, 1, 4, 1, 5, 9} + encodeDecode(t, p, np, "packed -> non-packed") + if !reflect.DeepEqual(p.B, np.A) { + t.Errorf("failed packed -> non-packed; p.B=%+v, np.A=%+v", p.B, np.A) + } +} + +func TestProto1RepeatedGroup(t *testing.T) { + pb := &MessageList{ + Message: []*MessageList_Message{ + { + Name: String("blah"), + Count: Int32(7), + }, + // NOTE: pb.Message[1] is a nil + nil, + }, + } + + o := old() + err := o.Marshal(pb) + if err == nil || !strings.Contains(err.Error(), "repeated field Message has nil") { + t.Fatalf("unexpected or no error when marshaling: %v", err) + } +} + +// Test that enums work. Checks for a bug introduced by making enums +// named types instead of int32: newInt32FromUint64 would crash with +// a type mismatch in reflect.PointTo. +func TestEnum(t *testing.T) { + pb := new(GoEnum) + pb.Foo = FOO_FOO1.Enum() + o := old() + if err := o.Marshal(pb); err != nil { + t.Fatal("error encoding enum:", err) + } + pb1 := new(GoEnum) + if err := o.Unmarshal(pb1); err != nil { + t.Fatal("error decoding enum:", err) + } + if *pb1.Foo != FOO_FOO1 { + t.Error("expected 7 but got ", *pb1.Foo) + } +} + +// Enum types have String methods. Check that enum fields can be printed. +// We don't care what the value actually is, just as long as it doesn't crash. +func TestPrintingNilEnumFields(t *testing.T) { + pb := new(GoEnum) + _ = fmt.Sprintf("%+v", pb) +} + +// Verify that absent required fields cause Marshal/Unmarshal to return errors. +func TestRequiredFieldEnforcement(t *testing.T) { + pb := new(GoTestField) + _, err := Marshal(pb) + if err == nil { + t.Error("marshal: expected error, got nil") + } else if _, ok := err.(*RequiredNotSetError); !ok || !strings.Contains(err.Error(), "Label") { + t.Errorf("marshal: bad error type: %v", err) + } + + // A slightly sneaky, yet valid, proto. It encodes the same required field twice, + // so simply counting the required fields is insufficient. + // field 1, encoding 2, value "hi" + buf := []byte("\x0A\x02hi\x0A\x02hi") + err = Unmarshal(buf, pb) + if err == nil { + t.Error("unmarshal: expected error, got nil") + } else if _, ok := err.(*RequiredNotSetError); !ok || !strings.Contains(err.Error(), "{Unknown}") { + t.Errorf("unmarshal: bad error type: %v", err) + } +} + +// Verify that absent required fields in groups cause Marshal/Unmarshal to return errors. +func TestRequiredFieldEnforcementGroups(t *testing.T) { + pb := &GoTestRequiredGroupField{Group: &GoTestRequiredGroupField_Group{}} + if _, err := Marshal(pb); err == nil { + t.Error("marshal: expected error, got nil") + } else if _, ok := err.(*RequiredNotSetError); !ok || !strings.Contains(err.Error(), "Group.Field") { + t.Errorf("marshal: bad error type: %v", err) + } + + buf := []byte{11, 12} + if err := Unmarshal(buf, pb); err == nil { + t.Error("unmarshal: expected error, got nil") + } else if _, ok := err.(*RequiredNotSetError); !ok || !strings.Contains(err.Error(), "Group.{Unknown}") { + t.Errorf("unmarshal: bad error type: %v", err) + } +} + +func TestTypedNilMarshal(t *testing.T) { + // A typed nil should return ErrNil and not crash. + { + var m *GoEnum + if _, err := Marshal(m); err != ErrNil { + t.Errorf("Marshal(%#v): got %v, want ErrNil", m, err) + } + } + + { + m := &Communique{Union: &Communique_Msg{nil}} + if _, err := Marshal(m); err == nil || err == ErrNil { + t.Errorf("Marshal(%#v): got %v, want errOneofHasNil", m, err) + } + } +} + +// A type that implements the Marshaler interface, but is not nillable. +type nonNillableInt uint64 + +func (nni nonNillableInt) Marshal() ([]byte, error) { + return EncodeVarint(uint64(nni)), nil +} + +type NNIMessage struct { + nni nonNillableInt +} + +func (*NNIMessage) Reset() {} +func (*NNIMessage) String() string { return "" } +func (*NNIMessage) ProtoMessage() {} + +// A type that implements the Marshaler interface and is nillable. +type nillableMessage struct { + x uint64 +} + +func (nm *nillableMessage) Marshal() ([]byte, error) { + return EncodeVarint(nm.x), nil +} + +type NMMessage struct { + nm *nillableMessage +} + +func (*NMMessage) Reset() {} +func (*NMMessage) String() string { return "" } +func (*NMMessage) ProtoMessage() {} + +// Verify a type that uses the Marshaler interface, but has a nil pointer. +func TestNilMarshaler(t *testing.T) { + // Try a struct with a Marshaler field that is nil. + // It should be directly marshable. + nmm := new(NMMessage) + if _, err := Marshal(nmm); err != nil { + t.Error("unexpected error marshaling nmm: ", err) + } + + // Try a struct with a Marshaler field that is not nillable. + nnim := new(NNIMessage) + nnim.nni = 7 + var _ Marshaler = nnim.nni // verify it is truly a Marshaler + if _, err := Marshal(nnim); err != nil { + t.Error("unexpected error marshaling nnim: ", err) + } +} + +func TestAllSetDefaults(t *testing.T) { + // Exercise SetDefaults with all scalar field types. + m := &Defaults{ + // NaN != NaN, so override that here. + F_Nan: Float32(1.7), + } + expected := &Defaults{ + F_Bool: Bool(true), + F_Int32: Int32(32), + F_Int64: Int64(64), + F_Fixed32: Uint32(320), + F_Fixed64: Uint64(640), + F_Uint32: Uint32(3200), + F_Uint64: Uint64(6400), + F_Float: Float32(314159), + F_Double: Float64(271828), + F_String: String(`hello, "world!"` + "\n"), + F_Bytes: []byte("Bignose"), + F_Sint32: Int32(-32), + F_Sint64: Int64(-64), + F_Enum: Defaults_GREEN.Enum(), + F_Pinf: Float32(float32(math.Inf(1))), + F_Ninf: Float32(float32(math.Inf(-1))), + F_Nan: Float32(1.7), + StrZero: String(""), + } + SetDefaults(m) + if !Equal(m, expected) { + t.Errorf("SetDefaults failed\n got %v\nwant %v", m, expected) + } +} + +func TestSetDefaultsWithSetField(t *testing.T) { + // Check that a set value is not overridden. + m := &Defaults{ + F_Int32: Int32(12), + } + SetDefaults(m) + if v := m.GetF_Int32(); v != 12 { + t.Errorf("m.FInt32 = %v, want 12", v) + } +} + +func TestSetDefaultsWithSubMessage(t *testing.T) { + m := &OtherMessage{ + Key: Int64(123), + Inner: &InnerMessage{ + Host: String("gopher"), + }, + } + expected := &OtherMessage{ + Key: Int64(123), + Inner: &InnerMessage{ + Host: String("gopher"), + Port: Int32(4000), + }, + } + SetDefaults(m) + if !Equal(m, expected) { + t.Errorf("\n got %v\nwant %v", m, expected) + } +} + +func TestSetDefaultsWithRepeatedSubMessage(t *testing.T) { + m := &MyMessage{ + RepInner: []*InnerMessage{{}}, + } + expected := &MyMessage{ + RepInner: []*InnerMessage{{ + Port: Int32(4000), + }}, + } + SetDefaults(m) + if !Equal(m, expected) { + t.Errorf("\n got %v\nwant %v", m, expected) + } +} + +func TestSetDefaultWithRepeatedNonMessage(t *testing.T) { + m := &MyMessage{ + Pet: []string{"turtle", "wombat"}, + } + expected := Clone(m) + SetDefaults(m) + if !Equal(m, expected) { + t.Errorf("\n got %v\nwant %v", m, expected) + } +} + +func TestMaximumTagNumber(t *testing.T) { + m := &MaxTag{ + LastField: String("natural goat essence"), + } + buf, err := Marshal(m) + if err != nil { + t.Fatalf("proto.Marshal failed: %v", err) + } + m2 := new(MaxTag) + if err := Unmarshal(buf, m2); err != nil { + t.Fatalf("proto.Unmarshal failed: %v", err) + } + if got, want := m2.GetLastField(), *m.LastField; got != want { + t.Errorf("got %q, want %q", got, want) + } +} + +func TestJSON(t *testing.T) { + m := &MyMessage{ + Count: Int32(4), + Pet: []string{"bunny", "kitty"}, + Inner: &InnerMessage{ + Host: String("cauchy"), + }, + Bikeshed: MyMessage_GREEN.Enum(), + } + const expected = `{"count":4,"pet":["bunny","kitty"],"inner":{"host":"cauchy"},"bikeshed":1}` + + b, err := json.Marshal(m) + if err != nil { + t.Fatalf("json.Marshal failed: %v", err) + } + s := string(b) + if s != expected { + t.Errorf("got %s\nwant %s", s, expected) + } + + received := new(MyMessage) + if err := json.Unmarshal(b, received); err != nil { + t.Fatalf("json.Unmarshal failed: %v", err) + } + if !Equal(received, m) { + t.Fatalf("got %s, want %s", received, m) + } + + // Test unmarshalling of JSON with symbolic enum name. + const old = `{"count":4,"pet":["bunny","kitty"],"inner":{"host":"cauchy"},"bikeshed":"GREEN"}` + received.Reset() + if err := json.Unmarshal([]byte(old), received); err != nil { + t.Fatalf("json.Unmarshal failed: %v", err) + } + if !Equal(received, m) { + t.Fatalf("got %s, want %s", received, m) + } +} + +func TestBadWireType(t *testing.T) { + b := []byte{7<<3 | 6} // field 7, wire type 6 + pb := new(OtherMessage) + if err := Unmarshal(b, pb); err == nil { + t.Errorf("Unmarshal did not fail") + } else if !strings.Contains(err.Error(), "unknown wire type") { + t.Errorf("wrong error: %v", err) + } +} + +func TestBytesWithInvalidLength(t *testing.T) { + // If a byte sequence has an invalid (negative) length, Unmarshal should not panic. + b := []byte{2<<3 | WireBytes, 0xff, 0xff, 0xff, 0xff, 0xff, 0} + Unmarshal(b, new(MyMessage)) +} + +func TestLengthOverflow(t *testing.T) { + // Overflowing a length should not panic. + b := []byte{2<<3 | WireBytes, 1, 1, 3<<3 | WireBytes, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x01} + Unmarshal(b, new(MyMessage)) +} + +func TestVarintOverflow(t *testing.T) { + // Overflowing a 64-bit length should not be allowed. + b := []byte{1<<3 | WireVarint, 0x01, 3<<3 | WireBytes, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x01} + if err := Unmarshal(b, new(MyMessage)); err == nil { + t.Fatalf("Overflowed uint64 length without error") + } +} + +func TestUnmarshalFuzz(t *testing.T) { + const N = 1000 + seed := time.Now().UnixNano() + t.Logf("RNG seed is %d", seed) + rng := rand.New(rand.NewSource(seed)) + buf := make([]byte, 20) + for i := 0; i < N; i++ { + for j := range buf { + buf[j] = byte(rng.Intn(256)) + } + fuzzUnmarshal(t, buf) + } +} + +func TestMergeMessages(t *testing.T) { + pb := &MessageList{Message: []*MessageList_Message{{Name: String("x"), Count: Int32(1)}}} + data, err := Marshal(pb) + if err != nil { + t.Fatalf("Marshal: %v", err) + } + + pb1 := new(MessageList) + if err := Unmarshal(data, pb1); err != nil { + t.Fatalf("first Unmarshal: %v", err) + } + if err := Unmarshal(data, pb1); err != nil { + t.Fatalf("second Unmarshal: %v", err) + } + if len(pb1.Message) != 1 { + t.Errorf("two Unmarshals produced %d Messages, want 1", len(pb1.Message)) + } + + pb2 := new(MessageList) + if err := UnmarshalMerge(data, pb2); err != nil { + t.Fatalf("first UnmarshalMerge: %v", err) + } + if err := UnmarshalMerge(data, pb2); err != nil { + t.Fatalf("second UnmarshalMerge: %v", err) + } + if len(pb2.Message) != 2 { + t.Errorf("two UnmarshalMerges produced %d Messages, want 2", len(pb2.Message)) + } +} + +func TestExtensionMarshalOrder(t *testing.T) { + m := &MyMessage{Count: Int(123)} + if err := SetExtension(m, E_Ext_More, &Ext{Data: String("alpha")}); err != nil { + t.Fatalf("SetExtension: %v", err) + } + if err := SetExtension(m, E_Ext_Text, String("aleph")); err != nil { + t.Fatalf("SetExtension: %v", err) + } + if err := SetExtension(m, E_Ext_Number, Int32(1)); err != nil { + t.Fatalf("SetExtension: %v", err) + } + + // Serialize m several times, and check we get the same bytes each time. + var orig []byte + for i := 0; i < 100; i++ { + b, err := Marshal(m) + if err != nil { + t.Fatalf("Marshal: %v", err) + } + if i == 0 { + orig = b + continue + } + if !bytes.Equal(b, orig) { + t.Errorf("Bytes differ on attempt #%d", i) + } + } +} + +// Many extensions, because small maps might not iterate differently on each iteration. +var exts = []*ExtensionDesc{ + E_X201, + E_X202, + E_X203, + E_X204, + E_X205, + E_X206, + E_X207, + E_X208, + E_X209, + E_X210, + E_X211, + E_X212, + E_X213, + E_X214, + E_X215, + E_X216, + E_X217, + E_X218, + E_X219, + E_X220, + E_X221, + E_X222, + E_X223, + E_X224, + E_X225, + E_X226, + E_X227, + E_X228, + E_X229, + E_X230, + E_X231, + E_X232, + E_X233, + E_X234, + E_X235, + E_X236, + E_X237, + E_X238, + E_X239, + E_X240, + E_X241, + E_X242, + E_X243, + E_X244, + E_X245, + E_X246, + E_X247, + E_X248, + E_X249, + E_X250, +} + +func TestMessageSetMarshalOrder(t *testing.T) { + m := &MyMessageSet{} + for _, x := range exts { + if err := SetExtension(m, x, &Empty{}); err != nil { + t.Fatalf("SetExtension: %v", err) + } + } + + buf, err := Marshal(m) + if err != nil { + t.Fatalf("Marshal: %v", err) + } + + // Serialize m several times, and check we get the same bytes each time. + for i := 0; i < 10; i++ { + b1, err := Marshal(m) + if err != nil { + t.Fatalf("Marshal: %v", err) + } + if !bytes.Equal(b1, buf) { + t.Errorf("Bytes differ on re-Marshal #%d", i) + } + + m2 := &MyMessageSet{} + if err := Unmarshal(buf, m2); err != nil { + t.Errorf("Unmarshal: %v", err) + } + b2, err := Marshal(m2) + if err != nil { + t.Errorf("re-Marshal: %v", err) + } + if !bytes.Equal(b2, buf) { + t.Errorf("Bytes differ on round-trip #%d", i) + } + } +} + +func TestUnmarshalMergesMessages(t *testing.T) { + // If a nested message occurs twice in the input, + // the fields should be merged when decoding. + a := &OtherMessage{ + Key: Int64(123), + Inner: &InnerMessage{ + Host: String("polhode"), + Port: Int32(1234), + }, + } + aData, err := Marshal(a) + if err != nil { + t.Fatalf("Marshal(a): %v", err) + } + b := &OtherMessage{ + Weight: Float32(1.2), + Inner: &InnerMessage{ + Host: String("herpolhode"), + Connected: Bool(true), + }, + } + bData, err := Marshal(b) + if err != nil { + t.Fatalf("Marshal(b): %v", err) + } + want := &OtherMessage{ + Key: Int64(123), + Weight: Float32(1.2), + Inner: &InnerMessage{ + Host: String("herpolhode"), + Port: Int32(1234), + Connected: Bool(true), + }, + } + got := new(OtherMessage) + if err := Unmarshal(append(aData, bData...), got); err != nil { + t.Fatalf("Unmarshal: %v", err) + } + if !Equal(got, want) { + t.Errorf("\n got %v\nwant %v", got, want) + } +} + +func TestEncodingSizes(t *testing.T) { + tests := []struct { + m Message + n int + }{ + {&Defaults{F_Int32: Int32(math.MaxInt32)}, 6}, + {&Defaults{F_Int32: Int32(math.MinInt32)}, 11}, + {&Defaults{F_Uint32: Uint32(uint32(math.MaxInt32) + 1)}, 6}, + {&Defaults{F_Uint32: Uint32(math.MaxUint32)}, 6}, + } + for _, test := range tests { + b, err := Marshal(test.m) + if err != nil { + t.Errorf("Marshal(%v): %v", test.m, err) + continue + } + if len(b) != test.n { + t.Errorf("Marshal(%v) yielded %d bytes, want %d bytes", test.m, len(b), test.n) + } + } +} + +func TestRequiredNotSetError(t *testing.T) { + pb := initGoTest(false) + pb.RequiredField.Label = nil + pb.F_Int32Required = nil + pb.F_Int64Required = nil + + expected := "0807" + // field 1, encoding 0, value 7 + "2206" + "120474797065" + // field 4, encoding 2 (GoTestField) + "5001" + // field 10, encoding 0, value 1 + "6d20000000" + // field 13, encoding 5, value 0x20 + "714000000000000000" + // field 14, encoding 1, value 0x40 + "78a019" + // field 15, encoding 0, value 0xca0 = 3232 + "8001c032" + // field 16, encoding 0, value 0x1940 = 6464 + "8d0100004a45" + // field 17, encoding 5, value 3232.0 + "9101000000000040b940" + // field 18, encoding 1, value 6464.0 + "9a0106" + "737472696e67" + // field 19, encoding 2, string "string" + "b304" + // field 70, encoding 3, start group + "ba0408" + "7265717569726564" + // field 71, encoding 2, string "required" + "b404" + // field 70, encoding 4, end group + "aa0605" + "6279746573" + // field 101, encoding 2, string "bytes" + "b0063f" + // field 102, encoding 0, 0x3f zigzag32 + "b8067f" // field 103, encoding 0, 0x7f zigzag64 + + o := old() + bytes, err := Marshal(pb) + if _, ok := err.(*RequiredNotSetError); !ok { + fmt.Printf("marshal-1 err = %v, want *RequiredNotSetError", err) + o.DebugPrint("", bytes) + t.Fatalf("expected = %s", expected) + } + if strings.Index(err.Error(), "RequiredField.Label") < 0 { + t.Errorf("marshal-1 wrong err msg: %v", err) + } + if !equal(bytes, expected, t) { + o.DebugPrint("neq 1", bytes) + t.Fatalf("expected = %s", expected) + } + + // Now test Unmarshal by recreating the original buffer. + pbd := new(GoTest) + err = Unmarshal(bytes, pbd) + if _, ok := err.(*RequiredNotSetError); !ok { + t.Fatalf("unmarshal err = %v, want *RequiredNotSetError", err) + o.DebugPrint("", bytes) + t.Fatalf("string = %s", expected) + } + if strings.Index(err.Error(), "RequiredField.{Unknown}") < 0 { + t.Errorf("unmarshal wrong err msg: %v", err) + } + bytes, err = Marshal(pbd) + if _, ok := err.(*RequiredNotSetError); !ok { + t.Errorf("marshal-2 err = %v, want *RequiredNotSetError", err) + o.DebugPrint("", bytes) + t.Fatalf("string = %s", expected) + } + if strings.Index(err.Error(), "RequiredField.Label") < 0 { + t.Errorf("marshal-2 wrong err msg: %v", err) + } + if !equal(bytes, expected, t) { + o.DebugPrint("neq 2", bytes) + t.Fatalf("string = %s", expected) + } +} + +func fuzzUnmarshal(t *testing.T, data []byte) { + defer func() { + if e := recover(); e != nil { + t.Errorf("These bytes caused a panic: %+v", data) + t.Logf("Stack:\n%s", debug.Stack()) + t.FailNow() + } + }() + + pb := new(MyMessage) + Unmarshal(data, pb) +} + +func TestMapFieldMarshal(t *testing.T) { + m := &MessageWithMap{ + NameMapping: map[int32]string{ + 1: "Rob", + 4: "Ian", + 8: "Dave", + }, + } + b, err := Marshal(m) + if err != nil { + t.Fatalf("Marshal: %v", err) + } + + // b should be the concatenation of these three byte sequences in some order. + parts := []string{ + "\n\a\b\x01\x12\x03Rob", + "\n\a\b\x04\x12\x03Ian", + "\n\b\b\x08\x12\x04Dave", + } + ok := false + for i := range parts { + for j := range parts { + if j == i { + continue + } + for k := range parts { + if k == i || k == j { + continue + } + try := parts[i] + parts[j] + parts[k] + if bytes.Equal(b, []byte(try)) { + ok = true + break + } + } + } + } + if !ok { + t.Fatalf("Incorrect Marshal output.\n got %q\nwant %q (or a permutation of that)", b, parts[0]+parts[1]+parts[2]) + } + t.Logf("FYI b: %q", b) + + (new(Buffer)).DebugPrint("Dump of b", b) +} + +func TestMapFieldRoundTrips(t *testing.T) { + m := &MessageWithMap{ + NameMapping: map[int32]string{ + 1: "Rob", + 4: "Ian", + 8: "Dave", + }, + MsgMapping: map[int64]*FloatingPoint{ + 0x7001: &FloatingPoint{F: Float64(2.0)}, + }, + ByteMapping: map[bool][]byte{ + false: []byte("that's not right!"), + true: []byte("aye, 'tis true!"), + }, + } + b, err := Marshal(m) + if err != nil { + t.Fatalf("Marshal: %v", err) + } + t.Logf("FYI b: %q", b) + m2 := new(MessageWithMap) + if err := Unmarshal(b, m2); err != nil { + t.Fatalf("Unmarshal: %v", err) + } + for _, pair := range [][2]interface{}{ + {m.NameMapping, m2.NameMapping}, + {m.MsgMapping, m2.MsgMapping}, + {m.ByteMapping, m2.ByteMapping}, + } { + if !reflect.DeepEqual(pair[0], pair[1]) { + t.Errorf("Map did not survive a round trip.\ninitial: %v\n final: %v", pair[0], pair[1]) + } + } +} + +func TestMapFieldWithNil(t *testing.T) { + m1 := &MessageWithMap{ + MsgMapping: map[int64]*FloatingPoint{ + 1: nil, + }, + } + b, err := Marshal(m1) + if err != nil { + t.Fatalf("Marshal: %v", err) + } + m2 := new(MessageWithMap) + if err := Unmarshal(b, m2); err != nil { + t.Fatalf("Unmarshal: %v, got these bytes: %v", err, b) + } + if v, ok := m2.MsgMapping[1]; !ok { + t.Error("msg_mapping[1] not present") + } else if v != nil { + t.Errorf("msg_mapping[1] not nil: %v", v) + } +} + +func TestMapFieldWithNilBytes(t *testing.T) { + m1 := &MessageWithMap{ + ByteMapping: map[bool][]byte{ + false: []byte{}, + true: nil, + }, + } + n := Size(m1) + b, err := Marshal(m1) + if err != nil { + t.Fatalf("Marshal: %v", err) + } + if n != len(b) { + t.Errorf("Size(m1) = %d; want len(Marshal(m1)) = %d", n, len(b)) + } + m2 := new(MessageWithMap) + if err := Unmarshal(b, m2); err != nil { + t.Fatalf("Unmarshal: %v, got these bytes: %v", err, b) + } + if v, ok := m2.ByteMapping[false]; !ok { + t.Error("byte_mapping[false] not present") + } else if len(v) != 0 { + t.Errorf("byte_mapping[false] not empty: %#v", v) + } + if v, ok := m2.ByteMapping[true]; !ok { + t.Error("byte_mapping[true] not present") + } else if len(v) != 0 { + t.Errorf("byte_mapping[true] not empty: %#v", v) + } +} + +func TestDecodeMapFieldMissingKey(t *testing.T) { + b := []byte{ + 0x0A, 0x03, // message, tag 1 (name_mapping), of length 3 bytes + // no key + 0x12, 0x01, 0x6D, // string value of length 1 byte, value "m" + } + got := &MessageWithMap{} + err := Unmarshal(b, got) + if err != nil { + t.Fatalf("failed to marshal map with missing key: %v", err) + } + want := &MessageWithMap{NameMapping: map[int32]string{0: "m"}} + if !Equal(got, want) { + t.Errorf("Unmarshaled map with no key was not as expected. got: %v, want %v", got, want) + } +} + +func TestDecodeMapFieldMissingValue(t *testing.T) { + b := []byte{ + 0x0A, 0x02, // message, tag 1 (name_mapping), of length 2 bytes + 0x08, 0x01, // varint key, value 1 + // no value + } + got := &MessageWithMap{} + err := Unmarshal(b, got) + if err != nil { + t.Fatalf("failed to marshal map with missing value: %v", err) + } + want := &MessageWithMap{NameMapping: map[int32]string{1: ""}} + if !Equal(got, want) { + t.Errorf("Unmarshaled map with no value was not as expected. got: %v, want %v", got, want) + } +} + +func TestOneof(t *testing.T) { + m := &Communique{} + b, err := Marshal(m) + if err != nil { + t.Fatalf("Marshal of empty message with oneof: %v", err) + } + if len(b) != 0 { + t.Errorf("Marshal of empty message yielded too many bytes: %v", b) + } + + m = &Communique{ + Union: &Communique_Name{"Barry"}, + } + + // Round-trip. + b, err = Marshal(m) + if err != nil { + t.Fatalf("Marshal of message with oneof: %v", err) + } + if len(b) != 7 { // name tag/wire (1) + name len (1) + name (5) + t.Errorf("Incorrect marshal of message with oneof: %v", b) + } + m.Reset() + if err := Unmarshal(b, m); err != nil { + t.Fatalf("Unmarshal of message with oneof: %v", err) + } + if x, ok := m.Union.(*Communique_Name); !ok || x.Name != "Barry" { + t.Errorf("After round trip, Union = %+v", m.Union) + } + if name := m.GetName(); name != "Barry" { + t.Errorf("After round trip, GetName = %q, want %q", name, "Barry") + } + + // Let's try with a message in the oneof. + m.Union = &Communique_Msg{&Strings{StringField: String("deep deep string")}} + b, err = Marshal(m) + if err != nil { + t.Fatalf("Marshal of message with oneof set to message: %v", err) + } + if len(b) != 20 { // msg tag/wire (1) + msg len (1) + msg (1 + 1 + 16) + t.Errorf("Incorrect marshal of message with oneof set to message: %v", b) + } + m.Reset() + if err := Unmarshal(b, m); err != nil { + t.Fatalf("Unmarshal of message with oneof set to message: %v", err) + } + ss, ok := m.Union.(*Communique_Msg) + if !ok || ss.Msg.GetStringField() != "deep deep string" { + t.Errorf("After round trip with oneof set to message, Union = %+v", m.Union) + } +} + +func TestInefficientPackedBool(t *testing.T) { + // https://github.com/golang/protobuf/issues/76 + inp := []byte{ + 0x12, 0x02, // 0x12 = 2<<3|2; 2 bytes + // Usually a bool should take a single byte, + // but it is permitted to be any varint. + 0xb9, 0x30, + } + if err := Unmarshal(inp, new(MoreRepeated)); err != nil { + t.Error(err) + } +} + +// Benchmarks + +func testMsg() *GoTest { + pb := initGoTest(true) + const N = 1000 // Internally the library starts much smaller. + pb.F_Int32Repeated = make([]int32, N) + pb.F_DoubleRepeated = make([]float64, N) + for i := 0; i < N; i++ { + pb.F_Int32Repeated[i] = int32(i) + pb.F_DoubleRepeated[i] = float64(i) + } + return pb +} + +func bytesMsg() *GoTest { + pb := initGoTest(true) + buf := make([]byte, 4000) + for i := range buf { + buf[i] = byte(i) + } + pb.F_BytesDefaulted = buf + return pb +} + +func benchmarkMarshal(b *testing.B, pb Message, marshal func(Message) ([]byte, error)) { + d, _ := marshal(pb) + b.SetBytes(int64(len(d))) + b.ResetTimer() + for i := 0; i < b.N; i++ { + marshal(pb) + } +} + +func benchmarkBufferMarshal(b *testing.B, pb Message) { + p := NewBuffer(nil) + benchmarkMarshal(b, pb, func(pb0 Message) ([]byte, error) { + p.Reset() + err := p.Marshal(pb0) + return p.Bytes(), err + }) +} + +func benchmarkSize(b *testing.B, pb Message) { + benchmarkMarshal(b, pb, func(pb0 Message) ([]byte, error) { + Size(pb) + return nil, nil + }) +} + +func newOf(pb Message) Message { + in := reflect.ValueOf(pb) + if in.IsNil() { + return pb + } + return reflect.New(in.Type().Elem()).Interface().(Message) +} + +func benchmarkUnmarshal(b *testing.B, pb Message, unmarshal func([]byte, Message) error) { + d, _ := Marshal(pb) + b.SetBytes(int64(len(d))) + pbd := newOf(pb) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + unmarshal(d, pbd) + } +} + +func benchmarkBufferUnmarshal(b *testing.B, pb Message) { + p := NewBuffer(nil) + benchmarkUnmarshal(b, pb, func(d []byte, pb0 Message) error { + p.SetBuf(d) + return p.Unmarshal(pb0) + }) +} + +// Benchmark{Marshal,BufferMarshal,Size,Unmarshal,BufferUnmarshal}{,Bytes} + +func BenchmarkMarshal(b *testing.B) { + benchmarkMarshal(b, testMsg(), Marshal) +} + +func BenchmarkBufferMarshal(b *testing.B) { + benchmarkBufferMarshal(b, testMsg()) +} + +func BenchmarkSize(b *testing.B) { + benchmarkSize(b, testMsg()) +} + +func BenchmarkUnmarshal(b *testing.B) { + benchmarkUnmarshal(b, testMsg(), Unmarshal) +} + +func BenchmarkBufferUnmarshal(b *testing.B) { + benchmarkBufferUnmarshal(b, testMsg()) +} + +func BenchmarkMarshalBytes(b *testing.B) { + benchmarkMarshal(b, bytesMsg(), Marshal) +} + +func BenchmarkBufferMarshalBytes(b *testing.B) { + benchmarkBufferMarshal(b, bytesMsg()) +} + +func BenchmarkSizeBytes(b *testing.B) { + benchmarkSize(b, bytesMsg()) +} + +func BenchmarkUnmarshalBytes(b *testing.B) { + benchmarkUnmarshal(b, bytesMsg(), Unmarshal) +} + +func BenchmarkBufferUnmarshalBytes(b *testing.B) { + benchmarkBufferUnmarshal(b, bytesMsg()) +} + +func BenchmarkUnmarshalUnrecognizedFields(b *testing.B) { + b.StopTimer() + pb := initGoTestField() + skip := &GoSkipTest{ + SkipInt32: Int32(32), + SkipFixed32: Uint32(3232), + SkipFixed64: Uint64(6464), + SkipString: String("skipper"), + Skipgroup: &GoSkipTest_SkipGroup{ + GroupInt32: Int32(75), + GroupString: String("wxyz"), + }, + } + + pbd := new(GoTestField) + p := NewBuffer(nil) + p.Marshal(pb) + p.Marshal(skip) + p2 := NewBuffer(nil) + + b.StartTimer() + for i := 0; i < b.N; i++ { + p2.SetBuf(p.Bytes()) + p2.Unmarshal(pbd) + } +} diff --git a/vendor/github.com/golang/protobuf/proto/any_test.go b/vendor/github.com/golang/protobuf/proto/any_test.go new file mode 100644 index 00000000..1a3c22ed --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/any_test.go @@ -0,0 +1,300 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2016 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// 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 +// OWNER 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. + +package proto_test + +import ( + "strings" + "testing" + + "github.com/golang/protobuf/proto" + + pb "github.com/golang/protobuf/proto/proto3_proto" + testpb "github.com/golang/protobuf/proto/testdata" + anypb "github.com/golang/protobuf/ptypes/any" +) + +var ( + expandedMarshaler = proto.TextMarshaler{ExpandAny: true} + expandedCompactMarshaler = proto.TextMarshaler{Compact: true, ExpandAny: true} +) + +// anyEqual reports whether two messages which may be google.protobuf.Any or may +// contain google.protobuf.Any fields are equal. We can't use proto.Equal for +// comparison, because semantically equivalent messages may be marshaled to +// binary in different tag order. Instead, trust that TextMarshaler with +// ExpandAny option works and compare the text marshaling results. +func anyEqual(got, want proto.Message) bool { + // if messages are proto.Equal, no need to marshal. + if proto.Equal(got, want) { + return true + } + g := expandedMarshaler.Text(got) + w := expandedMarshaler.Text(want) + return g == w +} + +type golden struct { + m proto.Message + t, c string +} + +var goldenMessages = makeGolden() + +func makeGolden() []golden { + nested := &pb.Nested{Bunny: "Monty"} + nb, err := proto.Marshal(nested) + if err != nil { + panic(err) + } + m1 := &pb.Message{ + Name: "David", + ResultCount: 47, + Anything: &anypb.Any{TypeUrl: "type.googleapis.com/" + proto.MessageName(nested), Value: nb}, + } + m2 := &pb.Message{ + Name: "David", + ResultCount: 47, + Anything: &anypb.Any{TypeUrl: "http://[::1]/type.googleapis.com/" + proto.MessageName(nested), Value: nb}, + } + m3 := &pb.Message{ + Name: "David", + ResultCount: 47, + Anything: &anypb.Any{TypeUrl: `type.googleapis.com/"/` + proto.MessageName(nested), Value: nb}, + } + m4 := &pb.Message{ + Name: "David", + ResultCount: 47, + Anything: &anypb.Any{TypeUrl: "type.googleapis.com/a/path/" + proto.MessageName(nested), Value: nb}, + } + m5 := &anypb.Any{TypeUrl: "type.googleapis.com/" + proto.MessageName(nested), Value: nb} + + any1 := &testpb.MyMessage{Count: proto.Int32(47), Name: proto.String("David")} + proto.SetExtension(any1, testpb.E_Ext_More, &testpb.Ext{Data: proto.String("foo")}) + proto.SetExtension(any1, testpb.E_Ext_Text, proto.String("bar")) + any1b, err := proto.Marshal(any1) + if err != nil { + panic(err) + } + any2 := &testpb.MyMessage{Count: proto.Int32(42), Bikeshed: testpb.MyMessage_GREEN.Enum(), RepBytes: [][]byte{[]byte("roboto")}} + proto.SetExtension(any2, testpb.E_Ext_More, &testpb.Ext{Data: proto.String("baz")}) + any2b, err := proto.Marshal(any2) + if err != nil { + panic(err) + } + m6 := &pb.Message{ + Name: "David", + ResultCount: 47, + Anything: &anypb.Any{TypeUrl: "type.googleapis.com/" + proto.MessageName(any1), Value: any1b}, + ManyThings: []*anypb.Any{ + &anypb.Any{TypeUrl: "type.googleapis.com/" + proto.MessageName(any2), Value: any2b}, + &anypb.Any{TypeUrl: "type.googleapis.com/" + proto.MessageName(any1), Value: any1b}, + }, + } + + const ( + m1Golden = ` +name: "David" +result_count: 47 +anything: < + [type.googleapis.com/proto3_proto.Nested]: < + bunny: "Monty" + > +> +` + m2Golden = ` +name: "David" +result_count: 47 +anything: < + ["http://[::1]/type.googleapis.com/proto3_proto.Nested"]: < + bunny: "Monty" + > +> +` + m3Golden = ` +name: "David" +result_count: 47 +anything: < + ["type.googleapis.com/\"/proto3_proto.Nested"]: < + bunny: "Monty" + > +> +` + m4Golden = ` +name: "David" +result_count: 47 +anything: < + [type.googleapis.com/a/path/proto3_proto.Nested]: < + bunny: "Monty" + > +> +` + m5Golden = ` +[type.googleapis.com/proto3_proto.Nested]: < + bunny: "Monty" +> +` + m6Golden = ` +name: "David" +result_count: 47 +anything: < + [type.googleapis.com/testdata.MyMessage]: < + count: 47 + name: "David" + [testdata.Ext.more]: < + data: "foo" + > + [testdata.Ext.text]: "bar" + > +> +many_things: < + [type.googleapis.com/testdata.MyMessage]: < + count: 42 + bikeshed: GREEN + rep_bytes: "roboto" + [testdata.Ext.more]: < + data: "baz" + > + > +> +many_things: < + [type.googleapis.com/testdata.MyMessage]: < + count: 47 + name: "David" + [testdata.Ext.more]: < + data: "foo" + > + [testdata.Ext.text]: "bar" + > +> +` + ) + return []golden{ + {m1, strings.TrimSpace(m1Golden) + "\n", strings.TrimSpace(compact(m1Golden)) + " "}, + {m2, strings.TrimSpace(m2Golden) + "\n", strings.TrimSpace(compact(m2Golden)) + " "}, + {m3, strings.TrimSpace(m3Golden) + "\n", strings.TrimSpace(compact(m3Golden)) + " "}, + {m4, strings.TrimSpace(m4Golden) + "\n", strings.TrimSpace(compact(m4Golden)) + " "}, + {m5, strings.TrimSpace(m5Golden) + "\n", strings.TrimSpace(compact(m5Golden)) + " "}, + {m6, strings.TrimSpace(m6Golden) + "\n", strings.TrimSpace(compact(m6Golden)) + " "}, + } +} + +func TestMarshalGolden(t *testing.T) { + for _, tt := range goldenMessages { + if got, want := expandedMarshaler.Text(tt.m), tt.t; got != want { + t.Errorf("message %v: got:\n%s\nwant:\n%s", tt.m, got, want) + } + if got, want := expandedCompactMarshaler.Text(tt.m), tt.c; got != want { + t.Errorf("message %v: got:\n`%s`\nwant:\n`%s`", tt.m, got, want) + } + } +} + +func TestUnmarshalGolden(t *testing.T) { + for _, tt := range goldenMessages { + want := tt.m + got := proto.Clone(tt.m) + got.Reset() + if err := proto.UnmarshalText(tt.t, got); err != nil { + t.Errorf("failed to unmarshal\n%s\nerror: %v", tt.t, err) + } + if !anyEqual(got, want) { + t.Errorf("message:\n%s\ngot:\n%s\nwant:\n%s", tt.t, got, want) + } + got.Reset() + if err := proto.UnmarshalText(tt.c, got); err != nil { + t.Errorf("failed to unmarshal\n%s\nerror: %v", tt.c, err) + } + if !anyEqual(got, want) { + t.Errorf("message:\n%s\ngot:\n%s\nwant:\n%s", tt.c, got, want) + } + } +} + +func TestMarshalUnknownAny(t *testing.T) { + m := &pb.Message{ + Anything: &anypb.Any{ + TypeUrl: "foo", + Value: []byte("bar"), + }, + } + want := `anything: < + type_url: "foo" + value: "bar" +> +` + got := expandedMarshaler.Text(m) + if got != want { + t.Errorf("got\n`%s`\nwant\n`%s`", got, want) + } +} + +func TestAmbiguousAny(t *testing.T) { + pb := &anypb.Any{} + err := proto.UnmarshalText(` + type_url: "ttt/proto3_proto.Nested" + value: "\n\x05Monty" + `, pb) + t.Logf("result: %v (error: %v)", expandedMarshaler.Text(pb), err) + if err != nil { + t.Errorf("failed to parse ambiguous Any message: %v", err) + } +} + +func TestUnmarshalOverwriteAny(t *testing.T) { + pb := &anypb.Any{} + err := proto.UnmarshalText(` + [type.googleapis.com/a/path/proto3_proto.Nested]: < + bunny: "Monty" + > + [type.googleapis.com/a/path/proto3_proto.Nested]: < + bunny: "Rabbit of Caerbannog" + > + `, pb) + want := `line 7: Any message unpacked multiple times, or "type_url" already set` + if err.Error() != want { + t.Errorf("incorrect error.\nHave: %v\nWant: %v", err.Error(), want) + } +} + +func TestUnmarshalAnyMixAndMatch(t *testing.T) { + pb := &anypb.Any{} + err := proto.UnmarshalText(` + value: "\n\x05Monty" + [type.googleapis.com/a/path/proto3_proto.Nested]: < + bunny: "Rabbit of Caerbannog" + > + `, pb) + want := `line 5: Any message unpacked multiple times, or "value" already set` + if err.Error() != want { + t.Errorf("incorrect error.\nHave: %v\nWant: %v", err.Error(), want) + } +} diff --git a/vendor/github.com/golang/protobuf/proto/clone.go b/vendor/github.com/golang/protobuf/proto/clone.go new file mode 100644 index 00000000..e392575b --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/clone.go @@ -0,0 +1,229 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2011 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// 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 +// OWNER 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. + +// Protocol buffer deep copy and merge. +// TODO: RawMessage. + +package proto + +import ( + "log" + "reflect" + "strings" +) + +// Clone returns a deep copy of a protocol buffer. +func Clone(pb Message) Message { + in := reflect.ValueOf(pb) + if in.IsNil() { + return pb + } + + out := reflect.New(in.Type().Elem()) + // out is empty so a merge is a deep copy. + mergeStruct(out.Elem(), in.Elem()) + return out.Interface().(Message) +} + +// Merge merges src into dst. +// Required and optional fields that are set in src will be set to that value in dst. +// Elements of repeated fields will be appended. +// Merge panics if src and dst are not the same type, or if dst is nil. +func Merge(dst, src Message) { + in := reflect.ValueOf(src) + out := reflect.ValueOf(dst) + if out.IsNil() { + panic("proto: nil destination") + } + if in.Type() != out.Type() { + // Explicit test prior to mergeStruct so that mistyped nils will fail + panic("proto: type mismatch") + } + if in.IsNil() { + // Merging nil into non-nil is a quiet no-op + return + } + mergeStruct(out.Elem(), in.Elem()) +} + +func mergeStruct(out, in reflect.Value) { + sprop := GetProperties(in.Type()) + for i := 0; i < in.NumField(); i++ { + f := in.Type().Field(i) + if strings.HasPrefix(f.Name, "XXX_") { + continue + } + mergeAny(out.Field(i), in.Field(i), false, sprop.Prop[i]) + } + + if emIn, ok := extendable(in.Addr().Interface()); ok { + emOut, _ := extendable(out.Addr().Interface()) + mIn, muIn := emIn.extensionsRead() + if mIn != nil { + mOut := emOut.extensionsWrite() + muIn.Lock() + mergeExtension(mOut, mIn) + muIn.Unlock() + } + } + + uf := in.FieldByName("XXX_unrecognized") + if !uf.IsValid() { + return + } + uin := uf.Bytes() + if len(uin) > 0 { + out.FieldByName("XXX_unrecognized").SetBytes(append([]byte(nil), uin...)) + } +} + +// mergeAny performs a merge between two values of the same type. +// viaPtr indicates whether the values were indirected through a pointer (implying proto2). +// prop is set if this is a struct field (it may be nil). +func mergeAny(out, in reflect.Value, viaPtr bool, prop *Properties) { + if in.Type() == protoMessageType { + if !in.IsNil() { + if out.IsNil() { + out.Set(reflect.ValueOf(Clone(in.Interface().(Message)))) + } else { + Merge(out.Interface().(Message), in.Interface().(Message)) + } + } + return + } + switch in.Kind() { + case reflect.Bool, reflect.Float32, reflect.Float64, reflect.Int32, reflect.Int64, + reflect.String, reflect.Uint32, reflect.Uint64: + if !viaPtr && isProto3Zero(in) { + return + } + out.Set(in) + case reflect.Interface: + // Probably a oneof field; copy non-nil values. + if in.IsNil() { + return + } + // Allocate destination if it is not set, or set to a different type. + // Otherwise we will merge as normal. + if out.IsNil() || out.Elem().Type() != in.Elem().Type() { + out.Set(reflect.New(in.Elem().Elem().Type())) // interface -> *T -> T -> new(T) + } + mergeAny(out.Elem(), in.Elem(), false, nil) + case reflect.Map: + if in.Len() == 0 { + return + } + if out.IsNil() { + out.Set(reflect.MakeMap(in.Type())) + } + // For maps with value types of *T or []byte we need to deep copy each value. + elemKind := in.Type().Elem().Kind() + for _, key := range in.MapKeys() { + var val reflect.Value + switch elemKind { + case reflect.Ptr: + val = reflect.New(in.Type().Elem().Elem()) + mergeAny(val, in.MapIndex(key), false, nil) + case reflect.Slice: + val = in.MapIndex(key) + val = reflect.ValueOf(append([]byte{}, val.Bytes()...)) + default: + val = in.MapIndex(key) + } + out.SetMapIndex(key, val) + } + case reflect.Ptr: + if in.IsNil() { + return + } + if out.IsNil() { + out.Set(reflect.New(in.Elem().Type())) + } + mergeAny(out.Elem(), in.Elem(), true, nil) + case reflect.Slice: + if in.IsNil() { + return + } + if in.Type().Elem().Kind() == reflect.Uint8 { + // []byte is a scalar bytes field, not a repeated field. + + // Edge case: if this is in a proto3 message, a zero length + // bytes field is considered the zero value, and should not + // be merged. + if prop != nil && prop.proto3 && in.Len() == 0 { + return + } + + // Make a deep copy. + // Append to []byte{} instead of []byte(nil) so that we never end up + // with a nil result. + out.SetBytes(append([]byte{}, in.Bytes()...)) + return + } + n := in.Len() + if out.IsNil() { + out.Set(reflect.MakeSlice(in.Type(), 0, n)) + } + switch in.Type().Elem().Kind() { + case reflect.Bool, reflect.Float32, reflect.Float64, reflect.Int32, reflect.Int64, + reflect.String, reflect.Uint32, reflect.Uint64: + out.Set(reflect.AppendSlice(out, in)) + default: + for i := 0; i < n; i++ { + x := reflect.Indirect(reflect.New(in.Type().Elem())) + mergeAny(x, in.Index(i), false, nil) + out.Set(reflect.Append(out, x)) + } + } + case reflect.Struct: + mergeStruct(out, in) + default: + // unknown type, so not a protocol buffer + log.Printf("proto: don't know how to copy %v", in) + } +} + +func mergeExtension(out, in map[int32]Extension) { + for extNum, eIn := range in { + eOut := Extension{desc: eIn.desc} + if eIn.value != nil { + v := reflect.New(reflect.TypeOf(eIn.value)).Elem() + mergeAny(v, reflect.ValueOf(eIn.value), false, nil) + eOut.value = v.Interface() + } + if eIn.enc != nil { + eOut.enc = make([]byte, len(eIn.enc)) + copy(eOut.enc, eIn.enc) + } + + out[extNum] = eOut + } +} diff --git a/vendor/github.com/golang/protobuf/proto/clone_test.go b/vendor/github.com/golang/protobuf/proto/clone_test.go new file mode 100644 index 00000000..f607ff49 --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/clone_test.go @@ -0,0 +1,300 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2011 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// 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 +// OWNER 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. + +package proto_test + +import ( + "testing" + + "github.com/golang/protobuf/proto" + + proto3pb "github.com/golang/protobuf/proto/proto3_proto" + pb "github.com/golang/protobuf/proto/testdata" +) + +var cloneTestMessage = &pb.MyMessage{ + Count: proto.Int32(42), + Name: proto.String("Dave"), + Pet: []string{"bunny", "kitty", "horsey"}, + Inner: &pb.InnerMessage{ + Host: proto.String("niles"), + Port: proto.Int32(9099), + Connected: proto.Bool(true), + }, + Others: []*pb.OtherMessage{ + { + Value: []byte("some bytes"), + }, + }, + Somegroup: &pb.MyMessage_SomeGroup{ + GroupField: proto.Int32(6), + }, + RepBytes: [][]byte{[]byte("sham"), []byte("wow")}, +} + +func init() { + ext := &pb.Ext{ + Data: proto.String("extension"), + } + if err := proto.SetExtension(cloneTestMessage, pb.E_Ext_More, ext); err != nil { + panic("SetExtension: " + err.Error()) + } +} + +func TestClone(t *testing.T) { + m := proto.Clone(cloneTestMessage).(*pb.MyMessage) + if !proto.Equal(m, cloneTestMessage) { + t.Errorf("Clone(%v) = %v", cloneTestMessage, m) + } + + // Verify it was a deep copy. + *m.Inner.Port++ + if proto.Equal(m, cloneTestMessage) { + t.Error("Mutating clone changed the original") + } + // Byte fields and repeated fields should be copied. + if &m.Pet[0] == &cloneTestMessage.Pet[0] { + t.Error("Pet: repeated field not copied") + } + if &m.Others[0] == &cloneTestMessage.Others[0] { + t.Error("Others: repeated field not copied") + } + if &m.Others[0].Value[0] == &cloneTestMessage.Others[0].Value[0] { + t.Error("Others[0].Value: bytes field not copied") + } + if &m.RepBytes[0] == &cloneTestMessage.RepBytes[0] { + t.Error("RepBytes: repeated field not copied") + } + if &m.RepBytes[0][0] == &cloneTestMessage.RepBytes[0][0] { + t.Error("RepBytes[0]: bytes field not copied") + } +} + +func TestCloneNil(t *testing.T) { + var m *pb.MyMessage + if c := proto.Clone(m); !proto.Equal(m, c) { + t.Errorf("Clone(%v) = %v", m, c) + } +} + +var mergeTests = []struct { + src, dst, want proto.Message +}{ + { + src: &pb.MyMessage{ + Count: proto.Int32(42), + }, + dst: &pb.MyMessage{ + Name: proto.String("Dave"), + }, + want: &pb.MyMessage{ + Count: proto.Int32(42), + Name: proto.String("Dave"), + }, + }, + { + src: &pb.MyMessage{ + Inner: &pb.InnerMessage{ + Host: proto.String("hey"), + Connected: proto.Bool(true), + }, + Pet: []string{"horsey"}, + Others: []*pb.OtherMessage{ + { + Value: []byte("some bytes"), + }, + }, + }, + dst: &pb.MyMessage{ + Inner: &pb.InnerMessage{ + Host: proto.String("niles"), + Port: proto.Int32(9099), + }, + Pet: []string{"bunny", "kitty"}, + Others: []*pb.OtherMessage{ + { + Key: proto.Int64(31415926535), + }, + { + // Explicitly test a src=nil field + Inner: nil, + }, + }, + }, + want: &pb.MyMessage{ + Inner: &pb.InnerMessage{ + Host: proto.String("hey"), + Connected: proto.Bool(true), + Port: proto.Int32(9099), + }, + Pet: []string{"bunny", "kitty", "horsey"}, + Others: []*pb.OtherMessage{ + { + Key: proto.Int64(31415926535), + }, + {}, + { + Value: []byte("some bytes"), + }, + }, + }, + }, + { + src: &pb.MyMessage{ + RepBytes: [][]byte{[]byte("wow")}, + }, + dst: &pb.MyMessage{ + Somegroup: &pb.MyMessage_SomeGroup{ + GroupField: proto.Int32(6), + }, + RepBytes: [][]byte{[]byte("sham")}, + }, + want: &pb.MyMessage{ + Somegroup: &pb.MyMessage_SomeGroup{ + GroupField: proto.Int32(6), + }, + RepBytes: [][]byte{[]byte("sham"), []byte("wow")}, + }, + }, + // Check that a scalar bytes field replaces rather than appends. + { + src: &pb.OtherMessage{Value: []byte("foo")}, + dst: &pb.OtherMessage{Value: []byte("bar")}, + want: &pb.OtherMessage{Value: []byte("foo")}, + }, + { + src: &pb.MessageWithMap{ + NameMapping: map[int32]string{6: "Nigel"}, + MsgMapping: map[int64]*pb.FloatingPoint{ + 0x4001: &pb.FloatingPoint{F: proto.Float64(2.0)}, + 0x4002: &pb.FloatingPoint{ + F: proto.Float64(2.0), + }, + }, + ByteMapping: map[bool][]byte{true: []byte("wowsa")}, + }, + dst: &pb.MessageWithMap{ + NameMapping: map[int32]string{ + 6: "Bruce", // should be overwritten + 7: "Andrew", + }, + MsgMapping: map[int64]*pb.FloatingPoint{ + 0x4002: &pb.FloatingPoint{ + F: proto.Float64(3.0), + Exact: proto.Bool(true), + }, // the entire message should be overwritten + }, + }, + want: &pb.MessageWithMap{ + NameMapping: map[int32]string{ + 6: "Nigel", + 7: "Andrew", + }, + MsgMapping: map[int64]*pb.FloatingPoint{ + 0x4001: &pb.FloatingPoint{F: proto.Float64(2.0)}, + 0x4002: &pb.FloatingPoint{ + F: proto.Float64(2.0), + }, + }, + ByteMapping: map[bool][]byte{true: []byte("wowsa")}, + }, + }, + // proto3 shouldn't merge zero values, + // in the same way that proto2 shouldn't merge nils. + { + src: &proto3pb.Message{ + Name: "Aaron", + Data: []byte(""), // zero value, but not nil + }, + dst: &proto3pb.Message{ + HeightInCm: 176, + Data: []byte("texas!"), + }, + want: &proto3pb.Message{ + Name: "Aaron", + HeightInCm: 176, + Data: []byte("texas!"), + }, + }, + // Oneof fields should merge by assignment. + { + src: &pb.Communique{ + Union: &pb.Communique_Number{41}, + }, + dst: &pb.Communique{ + Union: &pb.Communique_Name{"Bobby Tables"}, + }, + want: &pb.Communique{ + Union: &pb.Communique_Number{41}, + }, + }, + // Oneof nil is the same as not set. + { + src: &pb.Communique{}, + dst: &pb.Communique{ + Union: &pb.Communique_Name{"Bobby Tables"}, + }, + want: &pb.Communique{ + Union: &pb.Communique_Name{"Bobby Tables"}, + }, + }, + { + src: &proto3pb.Message{ + Terrain: map[string]*proto3pb.Nested{ + "kay_a": &proto3pb.Nested{Cute: true}, // replace + "kay_b": &proto3pb.Nested{Bunny: "rabbit"}, // insert + }, + }, + dst: &proto3pb.Message{ + Terrain: map[string]*proto3pb.Nested{ + "kay_a": &proto3pb.Nested{Bunny: "lost"}, // replaced + "kay_c": &proto3pb.Nested{Bunny: "bunny"}, // keep + }, + }, + want: &proto3pb.Message{ + Terrain: map[string]*proto3pb.Nested{ + "kay_a": &proto3pb.Nested{Cute: true}, + "kay_b": &proto3pb.Nested{Bunny: "rabbit"}, + "kay_c": &proto3pb.Nested{Bunny: "bunny"}, + }, + }, + }, +} + +func TestMerge(t *testing.T) { + for _, m := range mergeTests { + got := proto.Clone(m.dst) + proto.Merge(got, m.src) + if !proto.Equal(got, m.want) { + t.Errorf("Merge(%v, %v)\n got %v\nwant %v\n", m.dst, m.src, got, m.want) + } + } +} diff --git a/vendor/github.com/golang/protobuf/proto/decode.go b/vendor/github.com/golang/protobuf/proto/decode.go new file mode 100644 index 00000000..aa207298 --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/decode.go @@ -0,0 +1,970 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2010 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// 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 +// OWNER 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. + +package proto + +/* + * Routines for decoding protocol buffer data to construct in-memory representations. + */ + +import ( + "errors" + "fmt" + "io" + "os" + "reflect" +) + +// errOverflow is returned when an integer is too large to be represented. +var errOverflow = errors.New("proto: integer overflow") + +// ErrInternalBadWireType is returned by generated code when an incorrect +// wire type is encountered. It does not get returned to user code. +var ErrInternalBadWireType = errors.New("proto: internal error: bad wiretype for oneof") + +// The fundamental decoders that interpret bytes on the wire. +// Those that take integer types all return uint64 and are +// therefore of type valueDecoder. + +// DecodeVarint reads a varint-encoded integer from the slice. +// It returns the integer and the number of bytes consumed, or +// zero if there is not enough. +// This is the format for the +// int32, int64, uint32, uint64, bool, and enum +// protocol buffer types. +func DecodeVarint(buf []byte) (x uint64, n int) { + for shift := uint(0); shift < 64; shift += 7 { + if n >= len(buf) { + return 0, 0 + } + b := uint64(buf[n]) + n++ + x |= (b & 0x7F) << shift + if (b & 0x80) == 0 { + return x, n + } + } + + // The number is too large to represent in a 64-bit value. + return 0, 0 +} + +func (p *Buffer) decodeVarintSlow() (x uint64, err error) { + i := p.index + l := len(p.buf) + + for shift := uint(0); shift < 64; shift += 7 { + if i >= l { + err = io.ErrUnexpectedEOF + return + } + b := p.buf[i] + i++ + x |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + p.index = i + return + } + } + + // The number is too large to represent in a 64-bit value. + err = errOverflow + return +} + +// DecodeVarint reads a varint-encoded integer from the Buffer. +// This is the format for the +// int32, int64, uint32, uint64, bool, and enum +// protocol buffer types. +func (p *Buffer) DecodeVarint() (x uint64, err error) { + i := p.index + buf := p.buf + + if i >= len(buf) { + return 0, io.ErrUnexpectedEOF + } else if buf[i] < 0x80 { + p.index++ + return uint64(buf[i]), nil + } else if len(buf)-i < 10 { + return p.decodeVarintSlow() + } + + var b uint64 + // we already checked the first byte + x = uint64(buf[i]) - 0x80 + i++ + + b = uint64(buf[i]) + i++ + x += b << 7 + if b&0x80 == 0 { + goto done + } + x -= 0x80 << 7 + + b = uint64(buf[i]) + i++ + x += b << 14 + if b&0x80 == 0 { + goto done + } + x -= 0x80 << 14 + + b = uint64(buf[i]) + i++ + x += b << 21 + if b&0x80 == 0 { + goto done + } + x -= 0x80 << 21 + + b = uint64(buf[i]) + i++ + x += b << 28 + if b&0x80 == 0 { + goto done + } + x -= 0x80 << 28 + + b = uint64(buf[i]) + i++ + x += b << 35 + if b&0x80 == 0 { + goto done + } + x -= 0x80 << 35 + + b = uint64(buf[i]) + i++ + x += b << 42 + if b&0x80 == 0 { + goto done + } + x -= 0x80 << 42 + + b = uint64(buf[i]) + i++ + x += b << 49 + if b&0x80 == 0 { + goto done + } + x -= 0x80 << 49 + + b = uint64(buf[i]) + i++ + x += b << 56 + if b&0x80 == 0 { + goto done + } + x -= 0x80 << 56 + + b = uint64(buf[i]) + i++ + x += b << 63 + if b&0x80 == 0 { + goto done + } + // x -= 0x80 << 63 // Always zero. + + return 0, errOverflow + +done: + p.index = i + return x, nil +} + +// DecodeFixed64 reads a 64-bit integer from the Buffer. +// This is the format for the +// fixed64, sfixed64, and double protocol buffer types. +func (p *Buffer) DecodeFixed64() (x uint64, err error) { + // x, err already 0 + i := p.index + 8 + if i < 0 || i > len(p.buf) { + err = io.ErrUnexpectedEOF + return + } + p.index = i + + x = uint64(p.buf[i-8]) + x |= uint64(p.buf[i-7]) << 8 + x |= uint64(p.buf[i-6]) << 16 + x |= uint64(p.buf[i-5]) << 24 + x |= uint64(p.buf[i-4]) << 32 + x |= uint64(p.buf[i-3]) << 40 + x |= uint64(p.buf[i-2]) << 48 + x |= uint64(p.buf[i-1]) << 56 + return +} + +// DecodeFixed32 reads a 32-bit integer from the Buffer. +// This is the format for the +// fixed32, sfixed32, and float protocol buffer types. +func (p *Buffer) DecodeFixed32() (x uint64, err error) { + // x, err already 0 + i := p.index + 4 + if i < 0 || i > len(p.buf) { + err = io.ErrUnexpectedEOF + return + } + p.index = i + + x = uint64(p.buf[i-4]) + x |= uint64(p.buf[i-3]) << 8 + x |= uint64(p.buf[i-2]) << 16 + x |= uint64(p.buf[i-1]) << 24 + return +} + +// DecodeZigzag64 reads a zigzag-encoded 64-bit integer +// from the Buffer. +// This is the format used for the sint64 protocol buffer type. +func (p *Buffer) DecodeZigzag64() (x uint64, err error) { + x, err = p.DecodeVarint() + if err != nil { + return + } + x = (x >> 1) ^ uint64((int64(x&1)<<63)>>63) + return +} + +// DecodeZigzag32 reads a zigzag-encoded 32-bit integer +// from the Buffer. +// This is the format used for the sint32 protocol buffer type. +func (p *Buffer) DecodeZigzag32() (x uint64, err error) { + x, err = p.DecodeVarint() + if err != nil { + return + } + x = uint64((uint32(x) >> 1) ^ uint32((int32(x&1)<<31)>>31)) + return +} + +// These are not ValueDecoders: they produce an array of bytes or a string. +// bytes, embedded messages + +// DecodeRawBytes reads a count-delimited byte buffer from the Buffer. +// This is the format used for the bytes protocol buffer +// type and for embedded messages. +func (p *Buffer) DecodeRawBytes(alloc bool) (buf []byte, err error) { + n, err := p.DecodeVarint() + if err != nil { + return nil, err + } + + nb := int(n) + if nb < 0 { + return nil, fmt.Errorf("proto: bad byte length %d", nb) + } + end := p.index + nb + if end < p.index || end > len(p.buf) { + return nil, io.ErrUnexpectedEOF + } + + if !alloc { + // todo: check if can get more uses of alloc=false + buf = p.buf[p.index:end] + p.index += nb + return + } + + buf = make([]byte, nb) + copy(buf, p.buf[p.index:]) + p.index += nb + return +} + +// DecodeStringBytes reads an encoded string from the Buffer. +// This is the format used for the proto2 string type. +func (p *Buffer) DecodeStringBytes() (s string, err error) { + buf, err := p.DecodeRawBytes(false) + if err != nil { + return + } + return string(buf), nil +} + +// Skip the next item in the buffer. Its wire type is decoded and presented as an argument. +// If the protocol buffer has extensions, and the field matches, add it as an extension. +// Otherwise, if the XXX_unrecognized field exists, append the skipped data there. +func (o *Buffer) skipAndSave(t reflect.Type, tag, wire int, base structPointer, unrecField field) error { + oi := o.index + + err := o.skip(t, tag, wire) + if err != nil { + return err + } + + if !unrecField.IsValid() { + return nil + } + + ptr := structPointer_Bytes(base, unrecField) + + // Add the skipped field to struct field + obuf := o.buf + + o.buf = *ptr + o.EncodeVarint(uint64(tag<<3 | wire)) + *ptr = append(o.buf, obuf[oi:o.index]...) + + o.buf = obuf + + return nil +} + +// Skip the next item in the buffer. Its wire type is decoded and presented as an argument. +func (o *Buffer) skip(t reflect.Type, tag, wire int) error { + + var u uint64 + var err error + + switch wire { + case WireVarint: + _, err = o.DecodeVarint() + case WireFixed64: + _, err = o.DecodeFixed64() + case WireBytes: + _, err = o.DecodeRawBytes(false) + case WireFixed32: + _, err = o.DecodeFixed32() + case WireStartGroup: + for { + u, err = o.DecodeVarint() + if err != nil { + break + } + fwire := int(u & 0x7) + if fwire == WireEndGroup { + break + } + ftag := int(u >> 3) + err = o.skip(t, ftag, fwire) + if err != nil { + break + } + } + default: + err = fmt.Errorf("proto: can't skip unknown wire type %d for %s", wire, t) + } + return err +} + +// Unmarshaler is the interface representing objects that can +// unmarshal themselves. The method should reset the receiver before +// decoding starts. The argument points to data that may be +// overwritten, so implementations should not keep references to the +// buffer. +type Unmarshaler interface { + Unmarshal([]byte) error +} + +// Unmarshal parses the protocol buffer representation in buf and places the +// decoded result in pb. If the struct underlying pb does not match +// the data in buf, the results can be unpredictable. +// +// Unmarshal resets pb before starting to unmarshal, so any +// existing data in pb is always removed. Use UnmarshalMerge +// to preserve and append to existing data. +func Unmarshal(buf []byte, pb Message) error { + pb.Reset() + return UnmarshalMerge(buf, pb) +} + +// UnmarshalMerge parses the protocol buffer representation in buf and +// writes the decoded result to pb. If the struct underlying pb does not match +// the data in buf, the results can be unpredictable. +// +// UnmarshalMerge merges into existing data in pb. +// Most code should use Unmarshal instead. +func UnmarshalMerge(buf []byte, pb Message) error { + // If the object can unmarshal itself, let it. + if u, ok := pb.(Unmarshaler); ok { + return u.Unmarshal(buf) + } + return NewBuffer(buf).Unmarshal(pb) +} + +// DecodeMessage reads a count-delimited message from the Buffer. +func (p *Buffer) DecodeMessage(pb Message) error { + enc, err := p.DecodeRawBytes(false) + if err != nil { + return err + } + return NewBuffer(enc).Unmarshal(pb) +} + +// DecodeGroup reads a tag-delimited group from the Buffer. +func (p *Buffer) DecodeGroup(pb Message) error { + typ, base, err := getbase(pb) + if err != nil { + return err + } + return p.unmarshalType(typ.Elem(), GetProperties(typ.Elem()), true, base) +} + +// Unmarshal parses the protocol buffer representation in the +// Buffer and places the decoded result in pb. If the struct +// underlying pb does not match the data in the buffer, the results can be +// unpredictable. +// +// Unlike proto.Unmarshal, this does not reset pb before starting to unmarshal. +func (p *Buffer) Unmarshal(pb Message) error { + // If the object can unmarshal itself, let it. + if u, ok := pb.(Unmarshaler); ok { + err := u.Unmarshal(p.buf[p.index:]) + p.index = len(p.buf) + return err + } + + typ, base, err := getbase(pb) + if err != nil { + return err + } + + err = p.unmarshalType(typ.Elem(), GetProperties(typ.Elem()), false, base) + + if collectStats { + stats.Decode++ + } + + return err +} + +// unmarshalType does the work of unmarshaling a structure. +func (o *Buffer) unmarshalType(st reflect.Type, prop *StructProperties, is_group bool, base structPointer) error { + var state errorState + required, reqFields := prop.reqCount, uint64(0) + + var err error + for err == nil && o.index < len(o.buf) { + oi := o.index + var u uint64 + u, err = o.DecodeVarint() + if err != nil { + break + } + wire := int(u & 0x7) + if wire == WireEndGroup { + if is_group { + if required > 0 { + // Not enough information to determine the exact field. + // (See below.) + return &RequiredNotSetError{"{Unknown}"} + } + return nil // input is satisfied + } + return fmt.Errorf("proto: %s: wiretype end group for non-group", st) + } + tag := int(u >> 3) + if tag <= 0 { + return fmt.Errorf("proto: %s: illegal tag %d (wire type %d)", st, tag, wire) + } + fieldnum, ok := prop.decoderTags.get(tag) + if !ok { + // Maybe it's an extension? + if prop.extendable { + if e, _ := extendable(structPointer_Interface(base, st)); isExtensionField(e, int32(tag)) { + if err = o.skip(st, tag, wire); err == nil { + extmap := e.extensionsWrite() + ext := extmap[int32(tag)] // may be missing + ext.enc = append(ext.enc, o.buf[oi:o.index]...) + extmap[int32(tag)] = ext + } + continue + } + } + // Maybe it's a oneof? + if prop.oneofUnmarshaler != nil { + m := structPointer_Interface(base, st).(Message) + // First return value indicates whether tag is a oneof field. + ok, err = prop.oneofUnmarshaler(m, tag, wire, o) + if err == ErrInternalBadWireType { + // Map the error to something more descriptive. + // Do the formatting here to save generated code space. + err = fmt.Errorf("bad wiretype for oneof field in %T", m) + } + if ok { + continue + } + } + err = o.skipAndSave(st, tag, wire, base, prop.unrecField) + continue + } + p := prop.Prop[fieldnum] + + if p.dec == nil { + fmt.Fprintf(os.Stderr, "proto: no protobuf decoder for %s.%s\n", st, st.Field(fieldnum).Name) + continue + } + dec := p.dec + if wire != WireStartGroup && wire != p.WireType { + if wire == WireBytes && p.packedDec != nil { + // a packable field + dec = p.packedDec + } else { + err = fmt.Errorf("proto: bad wiretype for field %s.%s: got wiretype %d, want %d", st, st.Field(fieldnum).Name, wire, p.WireType) + continue + } + } + decErr := dec(o, p, base) + if decErr != nil && !state.shouldContinue(decErr, p) { + err = decErr + } + if err == nil && p.Required { + // Successfully decoded a required field. + if tag <= 64 { + // use bitmap for fields 1-64 to catch field reuse. + var mask uint64 = 1 << uint64(tag-1) + if reqFields&mask == 0 { + // new required field + reqFields |= mask + required-- + } + } else { + // This is imprecise. It can be fooled by a required field + // with a tag > 64 that is encoded twice; that's very rare. + // A fully correct implementation would require allocating + // a data structure, which we would like to avoid. + required-- + } + } + } + if err == nil { + if is_group { + return io.ErrUnexpectedEOF + } + if state.err != nil { + return state.err + } + if required > 0 { + // Not enough information to determine the exact field. If we use extra + // CPU, we could determine the field only if the missing required field + // has a tag <= 64 and we check reqFields. + return &RequiredNotSetError{"{Unknown}"} + } + } + return err +} + +// Individual type decoders +// For each, +// u is the decoded value, +// v is a pointer to the field (pointer) in the struct + +// Sizes of the pools to allocate inside the Buffer. +// The goal is modest amortization and allocation +// on at least 16-byte boundaries. +const ( + boolPoolSize = 16 + uint32PoolSize = 8 + uint64PoolSize = 4 +) + +// Decode a bool. +func (o *Buffer) dec_bool(p *Properties, base structPointer) error { + u, err := p.valDec(o) + if err != nil { + return err + } + if len(o.bools) == 0 { + o.bools = make([]bool, boolPoolSize) + } + o.bools[0] = u != 0 + *structPointer_Bool(base, p.field) = &o.bools[0] + o.bools = o.bools[1:] + return nil +} + +func (o *Buffer) dec_proto3_bool(p *Properties, base structPointer) error { + u, err := p.valDec(o) + if err != nil { + return err + } + *structPointer_BoolVal(base, p.field) = u != 0 + return nil +} + +// Decode an int32. +func (o *Buffer) dec_int32(p *Properties, base structPointer) error { + u, err := p.valDec(o) + if err != nil { + return err + } + word32_Set(structPointer_Word32(base, p.field), o, uint32(u)) + return nil +} + +func (o *Buffer) dec_proto3_int32(p *Properties, base structPointer) error { + u, err := p.valDec(o) + if err != nil { + return err + } + word32Val_Set(structPointer_Word32Val(base, p.field), uint32(u)) + return nil +} + +// Decode an int64. +func (o *Buffer) dec_int64(p *Properties, base structPointer) error { + u, err := p.valDec(o) + if err != nil { + return err + } + word64_Set(structPointer_Word64(base, p.field), o, u) + return nil +} + +func (o *Buffer) dec_proto3_int64(p *Properties, base structPointer) error { + u, err := p.valDec(o) + if err != nil { + return err + } + word64Val_Set(structPointer_Word64Val(base, p.field), o, u) + return nil +} + +// Decode a string. +func (o *Buffer) dec_string(p *Properties, base structPointer) error { + s, err := o.DecodeStringBytes() + if err != nil { + return err + } + *structPointer_String(base, p.field) = &s + return nil +} + +func (o *Buffer) dec_proto3_string(p *Properties, base structPointer) error { + s, err := o.DecodeStringBytes() + if err != nil { + return err + } + *structPointer_StringVal(base, p.field) = s + return nil +} + +// Decode a slice of bytes ([]byte). +func (o *Buffer) dec_slice_byte(p *Properties, base structPointer) error { + b, err := o.DecodeRawBytes(true) + if err != nil { + return err + } + *structPointer_Bytes(base, p.field) = b + return nil +} + +// Decode a slice of bools ([]bool). +func (o *Buffer) dec_slice_bool(p *Properties, base structPointer) error { + u, err := p.valDec(o) + if err != nil { + return err + } + v := structPointer_BoolSlice(base, p.field) + *v = append(*v, u != 0) + return nil +} + +// Decode a slice of bools ([]bool) in packed format. +func (o *Buffer) dec_slice_packed_bool(p *Properties, base structPointer) error { + v := structPointer_BoolSlice(base, p.field) + + nn, err := o.DecodeVarint() + if err != nil { + return err + } + nb := int(nn) // number of bytes of encoded bools + fin := o.index + nb + if fin < o.index { + return errOverflow + } + + y := *v + for o.index < fin { + u, err := p.valDec(o) + if err != nil { + return err + } + y = append(y, u != 0) + } + + *v = y + return nil +} + +// Decode a slice of int32s ([]int32). +func (o *Buffer) dec_slice_int32(p *Properties, base structPointer) error { + u, err := p.valDec(o) + if err != nil { + return err + } + structPointer_Word32Slice(base, p.field).Append(uint32(u)) + return nil +} + +// Decode a slice of int32s ([]int32) in packed format. +func (o *Buffer) dec_slice_packed_int32(p *Properties, base structPointer) error { + v := structPointer_Word32Slice(base, p.field) + + nn, err := o.DecodeVarint() + if err != nil { + return err + } + nb := int(nn) // number of bytes of encoded int32s + + fin := o.index + nb + if fin < o.index { + return errOverflow + } + for o.index < fin { + u, err := p.valDec(o) + if err != nil { + return err + } + v.Append(uint32(u)) + } + return nil +} + +// Decode a slice of int64s ([]int64). +func (o *Buffer) dec_slice_int64(p *Properties, base structPointer) error { + u, err := p.valDec(o) + if err != nil { + return err + } + + structPointer_Word64Slice(base, p.field).Append(u) + return nil +} + +// Decode a slice of int64s ([]int64) in packed format. +func (o *Buffer) dec_slice_packed_int64(p *Properties, base structPointer) error { + v := structPointer_Word64Slice(base, p.field) + + nn, err := o.DecodeVarint() + if err != nil { + return err + } + nb := int(nn) // number of bytes of encoded int64s + + fin := o.index + nb + if fin < o.index { + return errOverflow + } + for o.index < fin { + u, err := p.valDec(o) + if err != nil { + return err + } + v.Append(u) + } + return nil +} + +// Decode a slice of strings ([]string). +func (o *Buffer) dec_slice_string(p *Properties, base structPointer) error { + s, err := o.DecodeStringBytes() + if err != nil { + return err + } + v := structPointer_StringSlice(base, p.field) + *v = append(*v, s) + return nil +} + +// Decode a slice of slice of bytes ([][]byte). +func (o *Buffer) dec_slice_slice_byte(p *Properties, base structPointer) error { + b, err := o.DecodeRawBytes(true) + if err != nil { + return err + } + v := structPointer_BytesSlice(base, p.field) + *v = append(*v, b) + return nil +} + +// Decode a map field. +func (o *Buffer) dec_new_map(p *Properties, base structPointer) error { + raw, err := o.DecodeRawBytes(false) + if err != nil { + return err + } + oi := o.index // index at the end of this map entry + o.index -= len(raw) // move buffer back to start of map entry + + mptr := structPointer_NewAt(base, p.field, p.mtype) // *map[K]V + if mptr.Elem().IsNil() { + mptr.Elem().Set(reflect.MakeMap(mptr.Type().Elem())) + } + v := mptr.Elem() // map[K]V + + // Prepare addressable doubly-indirect placeholders for the key and value types. + // See enc_new_map for why. + keyptr := reflect.New(reflect.PtrTo(p.mtype.Key())).Elem() // addressable *K + keybase := toStructPointer(keyptr.Addr()) // **K + + var valbase structPointer + var valptr reflect.Value + switch p.mtype.Elem().Kind() { + case reflect.Slice: + // []byte + var dummy []byte + valptr = reflect.ValueOf(&dummy) // *[]byte + valbase = toStructPointer(valptr) // *[]byte + case reflect.Ptr: + // message; valptr is **Msg; need to allocate the intermediate pointer + valptr = reflect.New(reflect.PtrTo(p.mtype.Elem())).Elem() // addressable *V + valptr.Set(reflect.New(valptr.Type().Elem())) + valbase = toStructPointer(valptr) + default: + // everything else + valptr = reflect.New(reflect.PtrTo(p.mtype.Elem())).Elem() // addressable *V + valbase = toStructPointer(valptr.Addr()) // **V + } + + // Decode. + // This parses a restricted wire format, namely the encoding of a message + // with two fields. See enc_new_map for the format. + for o.index < oi { + // tagcode for key and value properties are always a single byte + // because they have tags 1 and 2. + tagcode := o.buf[o.index] + o.index++ + switch tagcode { + case p.mkeyprop.tagcode[0]: + if err := p.mkeyprop.dec(o, p.mkeyprop, keybase); err != nil { + return err + } + case p.mvalprop.tagcode[0]: + if err := p.mvalprop.dec(o, p.mvalprop, valbase); err != nil { + return err + } + default: + // TODO: Should we silently skip this instead? + return fmt.Errorf("proto: bad map data tag %d", raw[0]) + } + } + keyelem, valelem := keyptr.Elem(), valptr.Elem() + if !keyelem.IsValid() { + keyelem = reflect.Zero(p.mtype.Key()) + } + if !valelem.IsValid() { + valelem = reflect.Zero(p.mtype.Elem()) + } + + v.SetMapIndex(keyelem, valelem) + return nil +} + +// Decode a group. +func (o *Buffer) dec_struct_group(p *Properties, base structPointer) error { + bas := structPointer_GetStructPointer(base, p.field) + if structPointer_IsNil(bas) { + // allocate new nested message + bas = toStructPointer(reflect.New(p.stype)) + structPointer_SetStructPointer(base, p.field, bas) + } + return o.unmarshalType(p.stype, p.sprop, true, bas) +} + +// Decode an embedded message. +func (o *Buffer) dec_struct_message(p *Properties, base structPointer) (err error) { + raw, e := o.DecodeRawBytes(false) + if e != nil { + return e + } + + bas := structPointer_GetStructPointer(base, p.field) + if structPointer_IsNil(bas) { + // allocate new nested message + bas = toStructPointer(reflect.New(p.stype)) + structPointer_SetStructPointer(base, p.field, bas) + } + + // If the object can unmarshal itself, let it. + if p.isUnmarshaler { + iv := structPointer_Interface(bas, p.stype) + return iv.(Unmarshaler).Unmarshal(raw) + } + + obuf := o.buf + oi := o.index + o.buf = raw + o.index = 0 + + err = o.unmarshalType(p.stype, p.sprop, false, bas) + o.buf = obuf + o.index = oi + + return err +} + +// Decode a slice of embedded messages. +func (o *Buffer) dec_slice_struct_message(p *Properties, base structPointer) error { + return o.dec_slice_struct(p, false, base) +} + +// Decode a slice of embedded groups. +func (o *Buffer) dec_slice_struct_group(p *Properties, base structPointer) error { + return o.dec_slice_struct(p, true, base) +} + +// Decode a slice of structs ([]*struct). +func (o *Buffer) dec_slice_struct(p *Properties, is_group bool, base structPointer) error { + v := reflect.New(p.stype) + bas := toStructPointer(v) + structPointer_StructPointerSlice(base, p.field).Append(bas) + + if is_group { + err := o.unmarshalType(p.stype, p.sprop, is_group, bas) + return err + } + + raw, err := o.DecodeRawBytes(false) + if err != nil { + return err + } + + // If the object can unmarshal itself, let it. + if p.isUnmarshaler { + iv := v.Interface() + return iv.(Unmarshaler).Unmarshal(raw) + } + + obuf := o.buf + oi := o.index + o.buf = raw + o.index = 0 + + err = o.unmarshalType(p.stype, p.sprop, is_group, bas) + + o.buf = obuf + o.index = oi + + return err +} diff --git a/vendor/github.com/golang/protobuf/proto/decode_test.go b/vendor/github.com/golang/protobuf/proto/decode_test.go new file mode 100644 index 00000000..2c4c31d1 --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/decode_test.go @@ -0,0 +1,258 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2010 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// 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 +// OWNER 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. + +// +build go1.7 + +package proto_test + +import ( + "fmt" + "testing" + + "github.com/golang/protobuf/proto" + tpb "github.com/golang/protobuf/proto/proto3_proto" +) + +var ( + bytesBlackhole []byte + msgBlackhole = new(tpb.Message) +) + +// BenchmarkVarint32ArraySmall shows the performance on an array of small int32 fields (1 and +// 2 bytes long). +func BenchmarkVarint32ArraySmall(b *testing.B) { + for i := uint(1); i <= 10; i++ { + dist := genInt32Dist([7]int{0, 3, 1}, 1<2GB. + ErrTooLarge = errors.New("proto: message encodes to over 2 GB") +) + +// The fundamental encoders that put bytes on the wire. +// Those that take integer types all accept uint64 and are +// therefore of type valueEncoder. + +const maxVarintBytes = 10 // maximum length of a varint + +// maxMarshalSize is the largest allowed size of an encoded protobuf, +// since C++ and Java use signed int32s for the size. +const maxMarshalSize = 1<<31 - 1 + +// EncodeVarint returns the varint encoding of x. +// This is the format for the +// int32, int64, uint32, uint64, bool, and enum +// protocol buffer types. +// Not used by the package itself, but helpful to clients +// wishing to use the same encoding. +func EncodeVarint(x uint64) []byte { + var buf [maxVarintBytes]byte + var n int + for n = 0; x > 127; n++ { + buf[n] = 0x80 | uint8(x&0x7F) + x >>= 7 + } + buf[n] = uint8(x) + n++ + return buf[0:n] +} + +// EncodeVarint writes a varint-encoded integer to the Buffer. +// This is the format for the +// int32, int64, uint32, uint64, bool, and enum +// protocol buffer types. +func (p *Buffer) EncodeVarint(x uint64) error { + for x >= 1<<7 { + p.buf = append(p.buf, uint8(x&0x7f|0x80)) + x >>= 7 + } + p.buf = append(p.buf, uint8(x)) + return nil +} + +// SizeVarint returns the varint encoding size of an integer. +func SizeVarint(x uint64) int { + return sizeVarint(x) +} + +func sizeVarint(x uint64) (n int) { + for { + n++ + x >>= 7 + if x == 0 { + break + } + } + return n +} + +// EncodeFixed64 writes a 64-bit integer to the Buffer. +// This is the format for the +// fixed64, sfixed64, and double protocol buffer types. +func (p *Buffer) EncodeFixed64(x uint64) error { + p.buf = append(p.buf, + uint8(x), + uint8(x>>8), + uint8(x>>16), + uint8(x>>24), + uint8(x>>32), + uint8(x>>40), + uint8(x>>48), + uint8(x>>56)) + return nil +} + +func sizeFixed64(x uint64) int { + return 8 +} + +// EncodeFixed32 writes a 32-bit integer to the Buffer. +// This is the format for the +// fixed32, sfixed32, and float protocol buffer types. +func (p *Buffer) EncodeFixed32(x uint64) error { + p.buf = append(p.buf, + uint8(x), + uint8(x>>8), + uint8(x>>16), + uint8(x>>24)) + return nil +} + +func sizeFixed32(x uint64) int { + return 4 +} + +// EncodeZigzag64 writes a zigzag-encoded 64-bit integer +// to the Buffer. +// This is the format used for the sint64 protocol buffer type. +func (p *Buffer) EncodeZigzag64(x uint64) error { + // use signed number to get arithmetic right shift. + return p.EncodeVarint((x << 1) ^ uint64((int64(x) >> 63))) +} + +func sizeZigzag64(x uint64) int { + return sizeVarint((x << 1) ^ uint64((int64(x) >> 63))) +} + +// EncodeZigzag32 writes a zigzag-encoded 32-bit integer +// to the Buffer. +// This is the format used for the sint32 protocol buffer type. +func (p *Buffer) EncodeZigzag32(x uint64) error { + // use signed number to get arithmetic right shift. + return p.EncodeVarint(uint64((uint32(x) << 1) ^ uint32((int32(x) >> 31)))) +} + +func sizeZigzag32(x uint64) int { + return sizeVarint(uint64((uint32(x) << 1) ^ uint32((int32(x) >> 31)))) +} + +// EncodeRawBytes writes a count-delimited byte buffer to the Buffer. +// This is the format used for the bytes protocol buffer +// type and for embedded messages. +func (p *Buffer) EncodeRawBytes(b []byte) error { + p.EncodeVarint(uint64(len(b))) + p.buf = append(p.buf, b...) + return nil +} + +func sizeRawBytes(b []byte) int { + return sizeVarint(uint64(len(b))) + + len(b) +} + +// EncodeStringBytes writes an encoded string to the Buffer. +// This is the format used for the proto2 string type. +func (p *Buffer) EncodeStringBytes(s string) error { + p.EncodeVarint(uint64(len(s))) + p.buf = append(p.buf, s...) + return nil +} + +func sizeStringBytes(s string) int { + return sizeVarint(uint64(len(s))) + + len(s) +} + +// Marshaler is the interface representing objects that can marshal themselves. +type Marshaler interface { + Marshal() ([]byte, error) +} + +// Marshal takes the protocol buffer +// and encodes it into the wire format, returning the data. +func Marshal(pb Message) ([]byte, error) { + // Can the object marshal itself? + if m, ok := pb.(Marshaler); ok { + return m.Marshal() + } + p := NewBuffer(nil) + err := p.Marshal(pb) + if p.buf == nil && err == nil { + // Return a non-nil slice on success. + return []byte{}, nil + } + return p.buf, err +} + +// EncodeMessage writes the protocol buffer to the Buffer, +// prefixed by a varint-encoded length. +func (p *Buffer) EncodeMessage(pb Message) error { + t, base, err := getbase(pb) + if structPointer_IsNil(base) { + return ErrNil + } + if err == nil { + var state errorState + err = p.enc_len_struct(GetProperties(t.Elem()), base, &state) + } + return err +} + +// Marshal takes the protocol buffer +// and encodes it into the wire format, writing the result to the +// Buffer. +func (p *Buffer) Marshal(pb Message) error { + // Can the object marshal itself? + if m, ok := pb.(Marshaler); ok { + data, err := m.Marshal() + p.buf = append(p.buf, data...) + return err + } + + t, base, err := getbase(pb) + if structPointer_IsNil(base) { + return ErrNil + } + if err == nil { + err = p.enc_struct(GetProperties(t.Elem()), base) + } + + if collectStats { + (stats).Encode++ // Parens are to work around a goimports bug. + } + + if len(p.buf) > maxMarshalSize { + return ErrTooLarge + } + return err +} + +// Size returns the encoded size of a protocol buffer. +func Size(pb Message) (n int) { + // Can the object marshal itself? If so, Size is slow. + // TODO: add Size to Marshaler, or add a Sizer interface. + if m, ok := pb.(Marshaler); ok { + b, _ := m.Marshal() + return len(b) + } + + t, base, err := getbase(pb) + if structPointer_IsNil(base) { + return 0 + } + if err == nil { + n = size_struct(GetProperties(t.Elem()), base) + } + + if collectStats { + (stats).Size++ // Parens are to work around a goimports bug. + } + + return +} + +// Individual type encoders. + +// Encode a bool. +func (o *Buffer) enc_bool(p *Properties, base structPointer) error { + v := *structPointer_Bool(base, p.field) + if v == nil { + return ErrNil + } + x := 0 + if *v { + x = 1 + } + o.buf = append(o.buf, p.tagcode...) + p.valEnc(o, uint64(x)) + return nil +} + +func (o *Buffer) enc_proto3_bool(p *Properties, base structPointer) error { + v := *structPointer_BoolVal(base, p.field) + if !v { + return ErrNil + } + o.buf = append(o.buf, p.tagcode...) + p.valEnc(o, 1) + return nil +} + +func size_bool(p *Properties, base structPointer) int { + v := *structPointer_Bool(base, p.field) + if v == nil { + return 0 + } + return len(p.tagcode) + 1 // each bool takes exactly one byte +} + +func size_proto3_bool(p *Properties, base structPointer) int { + v := *structPointer_BoolVal(base, p.field) + if !v && !p.oneof { + return 0 + } + return len(p.tagcode) + 1 // each bool takes exactly one byte +} + +// Encode an int32. +func (o *Buffer) enc_int32(p *Properties, base structPointer) error { + v := structPointer_Word32(base, p.field) + if word32_IsNil(v) { + return ErrNil + } + x := int32(word32_Get(v)) // permit sign extension to use full 64-bit range + o.buf = append(o.buf, p.tagcode...) + p.valEnc(o, uint64(x)) + return nil +} + +func (o *Buffer) enc_proto3_int32(p *Properties, base structPointer) error { + v := structPointer_Word32Val(base, p.field) + x := int32(word32Val_Get(v)) // permit sign extension to use full 64-bit range + if x == 0 { + return ErrNil + } + o.buf = append(o.buf, p.tagcode...) + p.valEnc(o, uint64(x)) + return nil +} + +func size_int32(p *Properties, base structPointer) (n int) { + v := structPointer_Word32(base, p.field) + if word32_IsNil(v) { + return 0 + } + x := int32(word32_Get(v)) // permit sign extension to use full 64-bit range + n += len(p.tagcode) + n += p.valSize(uint64(x)) + return +} + +func size_proto3_int32(p *Properties, base structPointer) (n int) { + v := structPointer_Word32Val(base, p.field) + x := int32(word32Val_Get(v)) // permit sign extension to use full 64-bit range + if x == 0 && !p.oneof { + return 0 + } + n += len(p.tagcode) + n += p.valSize(uint64(x)) + return +} + +// Encode a uint32. +// Exactly the same as int32, except for no sign extension. +func (o *Buffer) enc_uint32(p *Properties, base structPointer) error { + v := structPointer_Word32(base, p.field) + if word32_IsNil(v) { + return ErrNil + } + x := word32_Get(v) + o.buf = append(o.buf, p.tagcode...) + p.valEnc(o, uint64(x)) + return nil +} + +func (o *Buffer) enc_proto3_uint32(p *Properties, base structPointer) error { + v := structPointer_Word32Val(base, p.field) + x := word32Val_Get(v) + if x == 0 { + return ErrNil + } + o.buf = append(o.buf, p.tagcode...) + p.valEnc(o, uint64(x)) + return nil +} + +func size_uint32(p *Properties, base structPointer) (n int) { + v := structPointer_Word32(base, p.field) + if word32_IsNil(v) { + return 0 + } + x := word32_Get(v) + n += len(p.tagcode) + n += p.valSize(uint64(x)) + return +} + +func size_proto3_uint32(p *Properties, base structPointer) (n int) { + v := structPointer_Word32Val(base, p.field) + x := word32Val_Get(v) + if x == 0 && !p.oneof { + return 0 + } + n += len(p.tagcode) + n += p.valSize(uint64(x)) + return +} + +// Encode an int64. +func (o *Buffer) enc_int64(p *Properties, base structPointer) error { + v := structPointer_Word64(base, p.field) + if word64_IsNil(v) { + return ErrNil + } + x := word64_Get(v) + o.buf = append(o.buf, p.tagcode...) + p.valEnc(o, x) + return nil +} + +func (o *Buffer) enc_proto3_int64(p *Properties, base structPointer) error { + v := structPointer_Word64Val(base, p.field) + x := word64Val_Get(v) + if x == 0 { + return ErrNil + } + o.buf = append(o.buf, p.tagcode...) + p.valEnc(o, x) + return nil +} + +func size_int64(p *Properties, base structPointer) (n int) { + v := structPointer_Word64(base, p.field) + if word64_IsNil(v) { + return 0 + } + x := word64_Get(v) + n += len(p.tagcode) + n += p.valSize(x) + return +} + +func size_proto3_int64(p *Properties, base structPointer) (n int) { + v := structPointer_Word64Val(base, p.field) + x := word64Val_Get(v) + if x == 0 && !p.oneof { + return 0 + } + n += len(p.tagcode) + n += p.valSize(x) + return +} + +// Encode a string. +func (o *Buffer) enc_string(p *Properties, base structPointer) error { + v := *structPointer_String(base, p.field) + if v == nil { + return ErrNil + } + x := *v + o.buf = append(o.buf, p.tagcode...) + o.EncodeStringBytes(x) + return nil +} + +func (o *Buffer) enc_proto3_string(p *Properties, base structPointer) error { + v := *structPointer_StringVal(base, p.field) + if v == "" { + return ErrNil + } + o.buf = append(o.buf, p.tagcode...) + o.EncodeStringBytes(v) + return nil +} + +func size_string(p *Properties, base structPointer) (n int) { + v := *structPointer_String(base, p.field) + if v == nil { + return 0 + } + x := *v + n += len(p.tagcode) + n += sizeStringBytes(x) + return +} + +func size_proto3_string(p *Properties, base structPointer) (n int) { + v := *structPointer_StringVal(base, p.field) + if v == "" && !p.oneof { + return 0 + } + n += len(p.tagcode) + n += sizeStringBytes(v) + return +} + +// All protocol buffer fields are nillable, but be careful. +func isNil(v reflect.Value) bool { + switch v.Kind() { + case reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice: + return v.IsNil() + } + return false +} + +// Encode a message struct. +func (o *Buffer) enc_struct_message(p *Properties, base structPointer) error { + var state errorState + structp := structPointer_GetStructPointer(base, p.field) + if structPointer_IsNil(structp) { + return ErrNil + } + + // Can the object marshal itself? + if p.isMarshaler { + m := structPointer_Interface(structp, p.stype).(Marshaler) + data, err := m.Marshal() + if err != nil && !state.shouldContinue(err, nil) { + return err + } + o.buf = append(o.buf, p.tagcode...) + o.EncodeRawBytes(data) + return state.err + } + + o.buf = append(o.buf, p.tagcode...) + return o.enc_len_struct(p.sprop, structp, &state) +} + +func size_struct_message(p *Properties, base structPointer) int { + structp := structPointer_GetStructPointer(base, p.field) + if structPointer_IsNil(structp) { + return 0 + } + + // Can the object marshal itself? + if p.isMarshaler { + m := structPointer_Interface(structp, p.stype).(Marshaler) + data, _ := m.Marshal() + n0 := len(p.tagcode) + n1 := sizeRawBytes(data) + return n0 + n1 + } + + n0 := len(p.tagcode) + n1 := size_struct(p.sprop, structp) + n2 := sizeVarint(uint64(n1)) // size of encoded length + return n0 + n1 + n2 +} + +// Encode a group struct. +func (o *Buffer) enc_struct_group(p *Properties, base structPointer) error { + var state errorState + b := structPointer_GetStructPointer(base, p.field) + if structPointer_IsNil(b) { + return ErrNil + } + + o.EncodeVarint(uint64((p.Tag << 3) | WireStartGroup)) + err := o.enc_struct(p.sprop, b) + if err != nil && !state.shouldContinue(err, nil) { + return err + } + o.EncodeVarint(uint64((p.Tag << 3) | WireEndGroup)) + return state.err +} + +func size_struct_group(p *Properties, base structPointer) (n int) { + b := structPointer_GetStructPointer(base, p.field) + if structPointer_IsNil(b) { + return 0 + } + + n += sizeVarint(uint64((p.Tag << 3) | WireStartGroup)) + n += size_struct(p.sprop, b) + n += sizeVarint(uint64((p.Tag << 3) | WireEndGroup)) + return +} + +// Encode a slice of bools ([]bool). +func (o *Buffer) enc_slice_bool(p *Properties, base structPointer) error { + s := *structPointer_BoolSlice(base, p.field) + l := len(s) + if l == 0 { + return ErrNil + } + for _, x := range s { + o.buf = append(o.buf, p.tagcode...) + v := uint64(0) + if x { + v = 1 + } + p.valEnc(o, v) + } + return nil +} + +func size_slice_bool(p *Properties, base structPointer) int { + s := *structPointer_BoolSlice(base, p.field) + l := len(s) + if l == 0 { + return 0 + } + return l * (len(p.tagcode) + 1) // each bool takes exactly one byte +} + +// Encode a slice of bools ([]bool) in packed format. +func (o *Buffer) enc_slice_packed_bool(p *Properties, base structPointer) error { + s := *structPointer_BoolSlice(base, p.field) + l := len(s) + if l == 0 { + return ErrNil + } + o.buf = append(o.buf, p.tagcode...) + o.EncodeVarint(uint64(l)) // each bool takes exactly one byte + for _, x := range s { + v := uint64(0) + if x { + v = 1 + } + p.valEnc(o, v) + } + return nil +} + +func size_slice_packed_bool(p *Properties, base structPointer) (n int) { + s := *structPointer_BoolSlice(base, p.field) + l := len(s) + if l == 0 { + return 0 + } + n += len(p.tagcode) + n += sizeVarint(uint64(l)) + n += l // each bool takes exactly one byte + return +} + +// Encode a slice of bytes ([]byte). +func (o *Buffer) enc_slice_byte(p *Properties, base structPointer) error { + s := *structPointer_Bytes(base, p.field) + if s == nil { + return ErrNil + } + o.buf = append(o.buf, p.tagcode...) + o.EncodeRawBytes(s) + return nil +} + +func (o *Buffer) enc_proto3_slice_byte(p *Properties, base structPointer) error { + s := *structPointer_Bytes(base, p.field) + if len(s) == 0 { + return ErrNil + } + o.buf = append(o.buf, p.tagcode...) + o.EncodeRawBytes(s) + return nil +} + +func size_slice_byte(p *Properties, base structPointer) (n int) { + s := *structPointer_Bytes(base, p.field) + if s == nil && !p.oneof { + return 0 + } + n += len(p.tagcode) + n += sizeRawBytes(s) + return +} + +func size_proto3_slice_byte(p *Properties, base structPointer) (n int) { + s := *structPointer_Bytes(base, p.field) + if len(s) == 0 && !p.oneof { + return 0 + } + n += len(p.tagcode) + n += sizeRawBytes(s) + return +} + +// Encode a slice of int32s ([]int32). +func (o *Buffer) enc_slice_int32(p *Properties, base structPointer) error { + s := structPointer_Word32Slice(base, p.field) + l := s.Len() + if l == 0 { + return ErrNil + } + for i := 0; i < l; i++ { + o.buf = append(o.buf, p.tagcode...) + x := int32(s.Index(i)) // permit sign extension to use full 64-bit range + p.valEnc(o, uint64(x)) + } + return nil +} + +func size_slice_int32(p *Properties, base structPointer) (n int) { + s := structPointer_Word32Slice(base, p.field) + l := s.Len() + if l == 0 { + return 0 + } + for i := 0; i < l; i++ { + n += len(p.tagcode) + x := int32(s.Index(i)) // permit sign extension to use full 64-bit range + n += p.valSize(uint64(x)) + } + return +} + +// Encode a slice of int32s ([]int32) in packed format. +func (o *Buffer) enc_slice_packed_int32(p *Properties, base structPointer) error { + s := structPointer_Word32Slice(base, p.field) + l := s.Len() + if l == 0 { + return ErrNil + } + // TODO: Reuse a Buffer. + buf := NewBuffer(nil) + for i := 0; i < l; i++ { + x := int32(s.Index(i)) // permit sign extension to use full 64-bit range + p.valEnc(buf, uint64(x)) + } + + o.buf = append(o.buf, p.tagcode...) + o.EncodeVarint(uint64(len(buf.buf))) + o.buf = append(o.buf, buf.buf...) + return nil +} + +func size_slice_packed_int32(p *Properties, base structPointer) (n int) { + s := structPointer_Word32Slice(base, p.field) + l := s.Len() + if l == 0 { + return 0 + } + var bufSize int + for i := 0; i < l; i++ { + x := int32(s.Index(i)) // permit sign extension to use full 64-bit range + bufSize += p.valSize(uint64(x)) + } + + n += len(p.tagcode) + n += sizeVarint(uint64(bufSize)) + n += bufSize + return +} + +// Encode a slice of uint32s ([]uint32). +// Exactly the same as int32, except for no sign extension. +func (o *Buffer) enc_slice_uint32(p *Properties, base structPointer) error { + s := structPointer_Word32Slice(base, p.field) + l := s.Len() + if l == 0 { + return ErrNil + } + for i := 0; i < l; i++ { + o.buf = append(o.buf, p.tagcode...) + x := s.Index(i) + p.valEnc(o, uint64(x)) + } + return nil +} + +func size_slice_uint32(p *Properties, base structPointer) (n int) { + s := structPointer_Word32Slice(base, p.field) + l := s.Len() + if l == 0 { + return 0 + } + for i := 0; i < l; i++ { + n += len(p.tagcode) + x := s.Index(i) + n += p.valSize(uint64(x)) + } + return +} + +// Encode a slice of uint32s ([]uint32) in packed format. +// Exactly the same as int32, except for no sign extension. +func (o *Buffer) enc_slice_packed_uint32(p *Properties, base structPointer) error { + s := structPointer_Word32Slice(base, p.field) + l := s.Len() + if l == 0 { + return ErrNil + } + // TODO: Reuse a Buffer. + buf := NewBuffer(nil) + for i := 0; i < l; i++ { + p.valEnc(buf, uint64(s.Index(i))) + } + + o.buf = append(o.buf, p.tagcode...) + o.EncodeVarint(uint64(len(buf.buf))) + o.buf = append(o.buf, buf.buf...) + return nil +} + +func size_slice_packed_uint32(p *Properties, base structPointer) (n int) { + s := structPointer_Word32Slice(base, p.field) + l := s.Len() + if l == 0 { + return 0 + } + var bufSize int + for i := 0; i < l; i++ { + bufSize += p.valSize(uint64(s.Index(i))) + } + + n += len(p.tagcode) + n += sizeVarint(uint64(bufSize)) + n += bufSize + return +} + +// Encode a slice of int64s ([]int64). +func (o *Buffer) enc_slice_int64(p *Properties, base structPointer) error { + s := structPointer_Word64Slice(base, p.field) + l := s.Len() + if l == 0 { + return ErrNil + } + for i := 0; i < l; i++ { + o.buf = append(o.buf, p.tagcode...) + p.valEnc(o, s.Index(i)) + } + return nil +} + +func size_slice_int64(p *Properties, base structPointer) (n int) { + s := structPointer_Word64Slice(base, p.field) + l := s.Len() + if l == 0 { + return 0 + } + for i := 0; i < l; i++ { + n += len(p.tagcode) + n += p.valSize(s.Index(i)) + } + return +} + +// Encode a slice of int64s ([]int64) in packed format. +func (o *Buffer) enc_slice_packed_int64(p *Properties, base structPointer) error { + s := structPointer_Word64Slice(base, p.field) + l := s.Len() + if l == 0 { + return ErrNil + } + // TODO: Reuse a Buffer. + buf := NewBuffer(nil) + for i := 0; i < l; i++ { + p.valEnc(buf, s.Index(i)) + } + + o.buf = append(o.buf, p.tagcode...) + o.EncodeVarint(uint64(len(buf.buf))) + o.buf = append(o.buf, buf.buf...) + return nil +} + +func size_slice_packed_int64(p *Properties, base structPointer) (n int) { + s := structPointer_Word64Slice(base, p.field) + l := s.Len() + if l == 0 { + return 0 + } + var bufSize int + for i := 0; i < l; i++ { + bufSize += p.valSize(s.Index(i)) + } + + n += len(p.tagcode) + n += sizeVarint(uint64(bufSize)) + n += bufSize + return +} + +// Encode a slice of slice of bytes ([][]byte). +func (o *Buffer) enc_slice_slice_byte(p *Properties, base structPointer) error { + ss := *structPointer_BytesSlice(base, p.field) + l := len(ss) + if l == 0 { + return ErrNil + } + for i := 0; i < l; i++ { + o.buf = append(o.buf, p.tagcode...) + o.EncodeRawBytes(ss[i]) + } + return nil +} + +func size_slice_slice_byte(p *Properties, base structPointer) (n int) { + ss := *structPointer_BytesSlice(base, p.field) + l := len(ss) + if l == 0 { + return 0 + } + n += l * len(p.tagcode) + for i := 0; i < l; i++ { + n += sizeRawBytes(ss[i]) + } + return +} + +// Encode a slice of strings ([]string). +func (o *Buffer) enc_slice_string(p *Properties, base structPointer) error { + ss := *structPointer_StringSlice(base, p.field) + l := len(ss) + for i := 0; i < l; i++ { + o.buf = append(o.buf, p.tagcode...) + o.EncodeStringBytes(ss[i]) + } + return nil +} + +func size_slice_string(p *Properties, base structPointer) (n int) { + ss := *structPointer_StringSlice(base, p.field) + l := len(ss) + n += l * len(p.tagcode) + for i := 0; i < l; i++ { + n += sizeStringBytes(ss[i]) + } + return +} + +// Encode a slice of message structs ([]*struct). +func (o *Buffer) enc_slice_struct_message(p *Properties, base structPointer) error { + var state errorState + s := structPointer_StructPointerSlice(base, p.field) + l := s.Len() + + for i := 0; i < l; i++ { + structp := s.Index(i) + if structPointer_IsNil(structp) { + return errRepeatedHasNil + } + + // Can the object marshal itself? + if p.isMarshaler { + m := structPointer_Interface(structp, p.stype).(Marshaler) + data, err := m.Marshal() + if err != nil && !state.shouldContinue(err, nil) { + return err + } + o.buf = append(o.buf, p.tagcode...) + o.EncodeRawBytes(data) + continue + } + + o.buf = append(o.buf, p.tagcode...) + err := o.enc_len_struct(p.sprop, structp, &state) + if err != nil && !state.shouldContinue(err, nil) { + if err == ErrNil { + return errRepeatedHasNil + } + return err + } + } + return state.err +} + +func size_slice_struct_message(p *Properties, base structPointer) (n int) { + s := structPointer_StructPointerSlice(base, p.field) + l := s.Len() + n += l * len(p.tagcode) + for i := 0; i < l; i++ { + structp := s.Index(i) + if structPointer_IsNil(structp) { + return // return the size up to this point + } + + // Can the object marshal itself? + if p.isMarshaler { + m := structPointer_Interface(structp, p.stype).(Marshaler) + data, _ := m.Marshal() + n += sizeRawBytes(data) + continue + } + + n0 := size_struct(p.sprop, structp) + n1 := sizeVarint(uint64(n0)) // size of encoded length + n += n0 + n1 + } + return +} + +// Encode a slice of group structs ([]*struct). +func (o *Buffer) enc_slice_struct_group(p *Properties, base structPointer) error { + var state errorState + s := structPointer_StructPointerSlice(base, p.field) + l := s.Len() + + for i := 0; i < l; i++ { + b := s.Index(i) + if structPointer_IsNil(b) { + return errRepeatedHasNil + } + + o.EncodeVarint(uint64((p.Tag << 3) | WireStartGroup)) + + err := o.enc_struct(p.sprop, b) + + if err != nil && !state.shouldContinue(err, nil) { + if err == ErrNil { + return errRepeatedHasNil + } + return err + } + + o.EncodeVarint(uint64((p.Tag << 3) | WireEndGroup)) + } + return state.err +} + +func size_slice_struct_group(p *Properties, base structPointer) (n int) { + s := structPointer_StructPointerSlice(base, p.field) + l := s.Len() + + n += l * sizeVarint(uint64((p.Tag<<3)|WireStartGroup)) + n += l * sizeVarint(uint64((p.Tag<<3)|WireEndGroup)) + for i := 0; i < l; i++ { + b := s.Index(i) + if structPointer_IsNil(b) { + return // return size up to this point + } + + n += size_struct(p.sprop, b) + } + return +} + +// Encode an extension map. +func (o *Buffer) enc_map(p *Properties, base structPointer) error { + exts := structPointer_ExtMap(base, p.field) + if err := encodeExtensionsMap(*exts); err != nil { + return err + } + + return o.enc_map_body(*exts) +} + +func (o *Buffer) enc_exts(p *Properties, base structPointer) error { + exts := structPointer_Extensions(base, p.field) + + v, mu := exts.extensionsRead() + if v == nil { + return nil + } + + mu.Lock() + defer mu.Unlock() + if err := encodeExtensionsMap(v); err != nil { + return err + } + + return o.enc_map_body(v) +} + +func (o *Buffer) enc_map_body(v map[int32]Extension) error { + // Fast-path for common cases: zero or one extensions. + if len(v) <= 1 { + for _, e := range v { + o.buf = append(o.buf, e.enc...) + } + return nil + } + + // Sort keys to provide a deterministic encoding. + keys := make([]int, 0, len(v)) + for k := range v { + keys = append(keys, int(k)) + } + sort.Ints(keys) + + for _, k := range keys { + o.buf = append(o.buf, v[int32(k)].enc...) + } + return nil +} + +func size_map(p *Properties, base structPointer) int { + v := structPointer_ExtMap(base, p.field) + return extensionsMapSize(*v) +} + +func size_exts(p *Properties, base structPointer) int { + v := structPointer_Extensions(base, p.field) + return extensionsSize(v) +} + +// Encode a map field. +func (o *Buffer) enc_new_map(p *Properties, base structPointer) error { + var state errorState // XXX: or do we need to plumb this through? + + /* + A map defined as + map map_field = N; + is encoded in the same way as + message MapFieldEntry { + key_type key = 1; + value_type value = 2; + } + repeated MapFieldEntry map_field = N; + */ + + v := structPointer_NewAt(base, p.field, p.mtype).Elem() // map[K]V + if v.Len() == 0 { + return nil + } + + keycopy, valcopy, keybase, valbase := mapEncodeScratch(p.mtype) + + enc := func() error { + if err := p.mkeyprop.enc(o, p.mkeyprop, keybase); err != nil { + return err + } + if err := p.mvalprop.enc(o, p.mvalprop, valbase); err != nil && err != ErrNil { + return err + } + return nil + } + + // Don't sort map keys. It is not required by the spec, and C++ doesn't do it. + for _, key := range v.MapKeys() { + val := v.MapIndex(key) + + keycopy.Set(key) + valcopy.Set(val) + + o.buf = append(o.buf, p.tagcode...) + if err := o.enc_len_thing(enc, &state); err != nil { + return err + } + } + return nil +} + +func size_new_map(p *Properties, base structPointer) int { + v := structPointer_NewAt(base, p.field, p.mtype).Elem() // map[K]V + + keycopy, valcopy, keybase, valbase := mapEncodeScratch(p.mtype) + + n := 0 + for _, key := range v.MapKeys() { + val := v.MapIndex(key) + keycopy.Set(key) + valcopy.Set(val) + + // Tag codes for key and val are the responsibility of the sub-sizer. + keysize := p.mkeyprop.size(p.mkeyprop, keybase) + valsize := p.mvalprop.size(p.mvalprop, valbase) + entry := keysize + valsize + // Add on tag code and length of map entry itself. + n += len(p.tagcode) + sizeVarint(uint64(entry)) + entry + } + return n +} + +// mapEncodeScratch returns a new reflect.Value matching the map's value type, +// and a structPointer suitable for passing to an encoder or sizer. +func mapEncodeScratch(mapType reflect.Type) (keycopy, valcopy reflect.Value, keybase, valbase structPointer) { + // Prepare addressable doubly-indirect placeholders for the key and value types. + // This is needed because the element-type encoders expect **T, but the map iteration produces T. + + keycopy = reflect.New(mapType.Key()).Elem() // addressable K + keyptr := reflect.New(reflect.PtrTo(keycopy.Type())).Elem() // addressable *K + keyptr.Set(keycopy.Addr()) // + keybase = toStructPointer(keyptr.Addr()) // **K + + // Value types are more varied and require special handling. + switch mapType.Elem().Kind() { + case reflect.Slice: + // []byte + var dummy []byte + valcopy = reflect.ValueOf(&dummy).Elem() // addressable []byte + valbase = toStructPointer(valcopy.Addr()) + case reflect.Ptr: + // message; the generated field type is map[K]*Msg (so V is *Msg), + // so we only need one level of indirection. + valcopy = reflect.New(mapType.Elem()).Elem() // addressable V + valbase = toStructPointer(valcopy.Addr()) + default: + // everything else + valcopy = reflect.New(mapType.Elem()).Elem() // addressable V + valptr := reflect.New(reflect.PtrTo(valcopy.Type())).Elem() // addressable *V + valptr.Set(valcopy.Addr()) // + valbase = toStructPointer(valptr.Addr()) // **V + } + return +} + +// Encode a struct. +func (o *Buffer) enc_struct(prop *StructProperties, base structPointer) error { + var state errorState + // Encode fields in tag order so that decoders may use optimizations + // that depend on the ordering. + // https://developers.google.com/protocol-buffers/docs/encoding#order + for _, i := range prop.order { + p := prop.Prop[i] + if p.enc != nil { + err := p.enc(o, p, base) + if err != nil { + if err == ErrNil { + if p.Required && state.err == nil { + state.err = &RequiredNotSetError{p.Name} + } + } else if err == errRepeatedHasNil { + // Give more context to nil values in repeated fields. + return errors.New("repeated field " + p.OrigName + " has nil element") + } else if !state.shouldContinue(err, p) { + return err + } + } + if len(o.buf) > maxMarshalSize { + return ErrTooLarge + } + } + } + + // Do oneof fields. + if prop.oneofMarshaler != nil { + m := structPointer_Interface(base, prop.stype).(Message) + if err := prop.oneofMarshaler(m, o); err == ErrNil { + return errOneofHasNil + } else if err != nil { + return err + } + } + + // Add unrecognized fields at the end. + if prop.unrecField.IsValid() { + v := *structPointer_Bytes(base, prop.unrecField) + if len(o.buf)+len(v) > maxMarshalSize { + return ErrTooLarge + } + if len(v) > 0 { + o.buf = append(o.buf, v...) + } + } + + return state.err +} + +func size_struct(prop *StructProperties, base structPointer) (n int) { + for _, i := range prop.order { + p := prop.Prop[i] + if p.size != nil { + n += p.size(p, base) + } + } + + // Add unrecognized fields at the end. + if prop.unrecField.IsValid() { + v := *structPointer_Bytes(base, prop.unrecField) + n += len(v) + } + + // Factor in any oneof fields. + if prop.oneofSizer != nil { + m := structPointer_Interface(base, prop.stype).(Message) + n += prop.oneofSizer(m) + } + + return +} + +var zeroes [20]byte // longer than any conceivable sizeVarint + +// Encode a struct, preceded by its encoded length (as a varint). +func (o *Buffer) enc_len_struct(prop *StructProperties, base structPointer, state *errorState) error { + return o.enc_len_thing(func() error { return o.enc_struct(prop, base) }, state) +} + +// Encode something, preceded by its encoded length (as a varint). +func (o *Buffer) enc_len_thing(enc func() error, state *errorState) error { + iLen := len(o.buf) + o.buf = append(o.buf, 0, 0, 0, 0) // reserve four bytes for length + iMsg := len(o.buf) + err := enc() + if err != nil && !state.shouldContinue(err, nil) { + return err + } + lMsg := len(o.buf) - iMsg + lLen := sizeVarint(uint64(lMsg)) + switch x := lLen - (iMsg - iLen); { + case x > 0: // actual length is x bytes larger than the space we reserved + // Move msg x bytes right. + o.buf = append(o.buf, zeroes[:x]...) + copy(o.buf[iMsg+x:], o.buf[iMsg:iMsg+lMsg]) + case x < 0: // actual length is x bytes smaller than the space we reserved + // Move msg x bytes left. + copy(o.buf[iMsg+x:], o.buf[iMsg:iMsg+lMsg]) + o.buf = o.buf[:len(o.buf)+x] // x is negative + } + // Encode the length in the reserved space. + o.buf = o.buf[:iLen] + o.EncodeVarint(uint64(lMsg)) + o.buf = o.buf[:len(o.buf)+lMsg] + return state.err +} + +// errorState maintains the first error that occurs and updates that error +// with additional context. +type errorState struct { + err error +} + +// shouldContinue reports whether encoding should continue upon encountering the +// given error. If the error is RequiredNotSetError, shouldContinue returns true +// and, if this is the first appearance of that error, remembers it for future +// reporting. +// +// If prop is not nil, it may update any error with additional context about the +// field with the error. +func (s *errorState) shouldContinue(err error, prop *Properties) bool { + // Ignore unset required fields. + reqNotSet, ok := err.(*RequiredNotSetError) + if !ok { + return false + } + if s.err == nil { + if prop != nil { + err = &RequiredNotSetError{prop.Name + "." + reqNotSet.field} + } + s.err = err + } + return true +} diff --git a/vendor/github.com/golang/protobuf/proto/encode_test.go b/vendor/github.com/golang/protobuf/proto/encode_test.go new file mode 100644 index 00000000..a7209475 --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/encode_test.go @@ -0,0 +1,85 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2010 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// 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 +// OWNER 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. + +// +build go1.7 + +package proto_test + +import ( + "strconv" + "testing" + + "github.com/golang/protobuf/proto" + tpb "github.com/golang/protobuf/proto/proto3_proto" + "github.com/golang/protobuf/ptypes" +) + +var ( + blackhole []byte +) + +// BenchmarkAny creates increasingly large arbitrary Any messages. The type is always the +// same. +func BenchmarkAny(b *testing.B) { + data := make([]byte, 1<<20) + quantum := 1 << 10 + for i := uint(0); i <= 10; i++ { + b.Run(strconv.Itoa(quantum<= len(o.buf) { + break + } + } + return value.Interface(), nil +} + +// GetExtensions returns a slice of the extensions present in pb that are also listed in es. +// The returned slice has the same length as es; missing extensions will appear as nil elements. +func GetExtensions(pb Message, es []*ExtensionDesc) (extensions []interface{}, err error) { + epb, ok := extendable(pb) + if !ok { + return nil, errors.New("proto: not an extendable proto") + } + extensions = make([]interface{}, len(es)) + for i, e := range es { + extensions[i], err = GetExtension(epb, e) + if err == ErrMissingExtension { + err = nil + } + if err != nil { + return + } + } + return +} + +// ExtensionDescs returns a new slice containing pb's extension descriptors, in undefined order. +// For non-registered extensions, ExtensionDescs returns an incomplete descriptor containing +// just the Field field, which defines the extension's field number. +func ExtensionDescs(pb Message) ([]*ExtensionDesc, error) { + epb, ok := extendable(pb) + if !ok { + return nil, fmt.Errorf("proto: %T is not an extendable proto.Message", pb) + } + registeredExtensions := RegisteredExtensions(pb) + + emap, mu := epb.extensionsRead() + if emap == nil { + return nil, nil + } + mu.Lock() + defer mu.Unlock() + extensions := make([]*ExtensionDesc, 0, len(emap)) + for extid, e := range emap { + desc := e.desc + if desc == nil { + desc = registeredExtensions[extid] + if desc == nil { + desc = &ExtensionDesc{Field: extid} + } + } + + extensions = append(extensions, desc) + } + return extensions, nil +} + +// SetExtension sets the specified extension of pb to the specified value. +func SetExtension(pb Message, extension *ExtensionDesc, value interface{}) error { + epb, ok := extendable(pb) + if !ok { + return errors.New("proto: not an extendable proto") + } + if err := checkExtensionTypes(epb, extension); err != nil { + return err + } + typ := reflect.TypeOf(extension.ExtensionType) + if typ != reflect.TypeOf(value) { + return errors.New("proto: bad extension value type") + } + // nil extension values need to be caught early, because the + // encoder can't distinguish an ErrNil due to a nil extension + // from an ErrNil due to a missing field. Extensions are + // always optional, so the encoder would just swallow the error + // and drop all the extensions from the encoded message. + if reflect.ValueOf(value).IsNil() { + return fmt.Errorf("proto: SetExtension called with nil value of type %T", value) + } + + extmap := epb.extensionsWrite() + extmap[extension.Field] = Extension{desc: extension, value: value} + return nil +} + +// ClearAllExtensions clears all extensions from pb. +func ClearAllExtensions(pb Message) { + epb, ok := extendable(pb) + if !ok { + return + } + m := epb.extensionsWrite() + for k := range m { + delete(m, k) + } +} + +// A global registry of extensions. +// The generated code will register the generated descriptors by calling RegisterExtension. + +var extensionMaps = make(map[reflect.Type]map[int32]*ExtensionDesc) + +// RegisterExtension is called from the generated code. +func RegisterExtension(desc *ExtensionDesc) { + st := reflect.TypeOf(desc.ExtendedType).Elem() + m := extensionMaps[st] + if m == nil { + m = make(map[int32]*ExtensionDesc) + extensionMaps[st] = m + } + if _, ok := m[desc.Field]; ok { + panic("proto: duplicate extension registered: " + st.String() + " " + strconv.Itoa(int(desc.Field))) + } + m[desc.Field] = desc +} + +// RegisteredExtensions returns a map of the registered extensions of a +// protocol buffer struct, indexed by the extension number. +// The argument pb should be a nil pointer to the struct type. +func RegisteredExtensions(pb Message) map[int32]*ExtensionDesc { + return extensionMaps[reflect.TypeOf(pb).Elem()] +} diff --git a/vendor/github.com/golang/protobuf/proto/extensions_test.go b/vendor/github.com/golang/protobuf/proto/extensions_test.go new file mode 100644 index 00000000..b6d9114c --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/extensions_test.go @@ -0,0 +1,536 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2014 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// 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 +// OWNER 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. + +package proto_test + +import ( + "bytes" + "fmt" + "reflect" + "sort" + "testing" + + "github.com/golang/protobuf/proto" + pb "github.com/golang/protobuf/proto/testdata" + "golang.org/x/sync/errgroup" +) + +func TestGetExtensionsWithMissingExtensions(t *testing.T) { + msg := &pb.MyMessage{} + ext1 := &pb.Ext{} + if err := proto.SetExtension(msg, pb.E_Ext_More, ext1); err != nil { + t.Fatalf("Could not set ext1: %s", err) + } + exts, err := proto.GetExtensions(msg, []*proto.ExtensionDesc{ + pb.E_Ext_More, + pb.E_Ext_Text, + }) + if err != nil { + t.Fatalf("GetExtensions() failed: %s", err) + } + if exts[0] != ext1 { + t.Errorf("ext1 not in returned extensions: %T %v", exts[0], exts[0]) + } + if exts[1] != nil { + t.Errorf("ext2 in returned extensions: %T %v", exts[1], exts[1]) + } +} + +func TestExtensionDescsWithMissingExtensions(t *testing.T) { + msg := &pb.MyMessage{Count: proto.Int32(0)} + extdesc1 := pb.E_Ext_More + if descs, err := proto.ExtensionDescs(msg); len(descs) != 0 || err != nil { + t.Errorf("proto.ExtensionDescs: got %d descs, error %v; want 0, nil", len(descs), err) + } + + ext1 := &pb.Ext{} + if err := proto.SetExtension(msg, extdesc1, ext1); err != nil { + t.Fatalf("Could not set ext1: %s", err) + } + extdesc2 := &proto.ExtensionDesc{ + ExtendedType: (*pb.MyMessage)(nil), + ExtensionType: (*bool)(nil), + Field: 123456789, + Name: "a.b", + Tag: "varint,123456789,opt", + } + ext2 := proto.Bool(false) + if err := proto.SetExtension(msg, extdesc2, ext2); err != nil { + t.Fatalf("Could not set ext2: %s", err) + } + + b, err := proto.Marshal(msg) + if err != nil { + t.Fatalf("Could not marshal msg: %v", err) + } + if err := proto.Unmarshal(b, msg); err != nil { + t.Fatalf("Could not unmarshal into msg: %v", err) + } + + descs, err := proto.ExtensionDescs(msg) + if err != nil { + t.Fatalf("proto.ExtensionDescs: got error %v", err) + } + sortExtDescs(descs) + wantDescs := []*proto.ExtensionDesc{extdesc1, &proto.ExtensionDesc{Field: extdesc2.Field}} + if !reflect.DeepEqual(descs, wantDescs) { + t.Errorf("proto.ExtensionDescs(msg) sorted extension ids: got %+v, want %+v", descs, wantDescs) + } +} + +type ExtensionDescSlice []*proto.ExtensionDesc + +func (s ExtensionDescSlice) Len() int { return len(s) } +func (s ExtensionDescSlice) Less(i, j int) bool { return s[i].Field < s[j].Field } +func (s ExtensionDescSlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] } + +func sortExtDescs(s []*proto.ExtensionDesc) { + sort.Sort(ExtensionDescSlice(s)) +} + +func TestGetExtensionStability(t *testing.T) { + check := func(m *pb.MyMessage) bool { + ext1, err := proto.GetExtension(m, pb.E_Ext_More) + if err != nil { + t.Fatalf("GetExtension() failed: %s", err) + } + ext2, err := proto.GetExtension(m, pb.E_Ext_More) + if err != nil { + t.Fatalf("GetExtension() failed: %s", err) + } + return ext1 == ext2 + } + msg := &pb.MyMessage{Count: proto.Int32(4)} + ext0 := &pb.Ext{} + if err := proto.SetExtension(msg, pb.E_Ext_More, ext0); err != nil { + t.Fatalf("Could not set ext1: %s", ext0) + } + if !check(msg) { + t.Errorf("GetExtension() not stable before marshaling") + } + bb, err := proto.Marshal(msg) + if err != nil { + t.Fatalf("Marshal() failed: %s", err) + } + msg1 := &pb.MyMessage{} + err = proto.Unmarshal(bb, msg1) + if err != nil { + t.Fatalf("Unmarshal() failed: %s", err) + } + if !check(msg1) { + t.Errorf("GetExtension() not stable after unmarshaling") + } +} + +func TestGetExtensionDefaults(t *testing.T) { + var setFloat64 float64 = 1 + var setFloat32 float32 = 2 + var setInt32 int32 = 3 + var setInt64 int64 = 4 + var setUint32 uint32 = 5 + var setUint64 uint64 = 6 + var setBool = true + var setBool2 = false + var setString = "Goodnight string" + var setBytes = []byte("Goodnight bytes") + var setEnum = pb.DefaultsMessage_TWO + + type testcase struct { + ext *proto.ExtensionDesc // Extension we are testing. + want interface{} // Expected value of extension, or nil (meaning that GetExtension will fail). + def interface{} // Expected value of extension after ClearExtension(). + } + tests := []testcase{ + {pb.E_NoDefaultDouble, setFloat64, nil}, + {pb.E_NoDefaultFloat, setFloat32, nil}, + {pb.E_NoDefaultInt32, setInt32, nil}, + {pb.E_NoDefaultInt64, setInt64, nil}, + {pb.E_NoDefaultUint32, setUint32, nil}, + {pb.E_NoDefaultUint64, setUint64, nil}, + {pb.E_NoDefaultSint32, setInt32, nil}, + {pb.E_NoDefaultSint64, setInt64, nil}, + {pb.E_NoDefaultFixed32, setUint32, nil}, + {pb.E_NoDefaultFixed64, setUint64, nil}, + {pb.E_NoDefaultSfixed32, setInt32, nil}, + {pb.E_NoDefaultSfixed64, setInt64, nil}, + {pb.E_NoDefaultBool, setBool, nil}, + {pb.E_NoDefaultBool, setBool2, nil}, + {pb.E_NoDefaultString, setString, nil}, + {pb.E_NoDefaultBytes, setBytes, nil}, + {pb.E_NoDefaultEnum, setEnum, nil}, + {pb.E_DefaultDouble, setFloat64, float64(3.1415)}, + {pb.E_DefaultFloat, setFloat32, float32(3.14)}, + {pb.E_DefaultInt32, setInt32, int32(42)}, + {pb.E_DefaultInt64, setInt64, int64(43)}, + {pb.E_DefaultUint32, setUint32, uint32(44)}, + {pb.E_DefaultUint64, setUint64, uint64(45)}, + {pb.E_DefaultSint32, setInt32, int32(46)}, + {pb.E_DefaultSint64, setInt64, int64(47)}, + {pb.E_DefaultFixed32, setUint32, uint32(48)}, + {pb.E_DefaultFixed64, setUint64, uint64(49)}, + {pb.E_DefaultSfixed32, setInt32, int32(50)}, + {pb.E_DefaultSfixed64, setInt64, int64(51)}, + {pb.E_DefaultBool, setBool, true}, + {pb.E_DefaultBool, setBool2, true}, + {pb.E_DefaultString, setString, "Hello, string"}, + {pb.E_DefaultBytes, setBytes, []byte("Hello, bytes")}, + {pb.E_DefaultEnum, setEnum, pb.DefaultsMessage_ONE}, + } + + checkVal := func(test testcase, msg *pb.DefaultsMessage, valWant interface{}) error { + val, err := proto.GetExtension(msg, test.ext) + if err != nil { + if valWant != nil { + return fmt.Errorf("GetExtension(): %s", err) + } + if want := proto.ErrMissingExtension; err != want { + return fmt.Errorf("Unexpected error: got %v, want %v", err, want) + } + return nil + } + + // All proto2 extension values are either a pointer to a value or a slice of values. + ty := reflect.TypeOf(val) + tyWant := reflect.TypeOf(test.ext.ExtensionType) + if got, want := ty, tyWant; got != want { + return fmt.Errorf("unexpected reflect.TypeOf(): got %v want %v", got, want) + } + tye := ty.Elem() + tyeWant := tyWant.Elem() + if got, want := tye, tyeWant; got != want { + return fmt.Errorf("unexpected reflect.TypeOf().Elem(): got %v want %v", got, want) + } + + // Check the name of the type of the value. + // If it is an enum it will be type int32 with the name of the enum. + if got, want := tye.Name(), tye.Name(); got != want { + return fmt.Errorf("unexpected reflect.TypeOf().Elem().Name(): got %v want %v", got, want) + } + + // Check that value is what we expect. + // If we have a pointer in val, get the value it points to. + valExp := val + if ty.Kind() == reflect.Ptr { + valExp = reflect.ValueOf(val).Elem().Interface() + } + if got, want := valExp, valWant; !reflect.DeepEqual(got, want) { + return fmt.Errorf("unexpected reflect.DeepEqual(): got %v want %v", got, want) + } + + return nil + } + + setTo := func(test testcase) interface{} { + setTo := reflect.ValueOf(test.want) + if typ := reflect.TypeOf(test.ext.ExtensionType); typ.Kind() == reflect.Ptr { + setTo = reflect.New(typ).Elem() + setTo.Set(reflect.New(setTo.Type().Elem())) + setTo.Elem().Set(reflect.ValueOf(test.want)) + } + return setTo.Interface() + } + + for _, test := range tests { + msg := &pb.DefaultsMessage{} + name := test.ext.Name + + // Check the initial value. + if err := checkVal(test, msg, test.def); err != nil { + t.Errorf("%s: %v", name, err) + } + + // Set the per-type value and check value. + name = fmt.Sprintf("%s (set to %T %v)", name, test.want, test.want) + if err := proto.SetExtension(msg, test.ext, setTo(test)); err != nil { + t.Errorf("%s: SetExtension(): %v", name, err) + continue + } + if err := checkVal(test, msg, test.want); err != nil { + t.Errorf("%s: %v", name, err) + continue + } + + // Set and check the value. + name += " (cleared)" + proto.ClearExtension(msg, test.ext) + if err := checkVal(test, msg, test.def); err != nil { + t.Errorf("%s: %v", name, err) + } + } +} + +func TestExtensionsRoundTrip(t *testing.T) { + msg := &pb.MyMessage{} + ext1 := &pb.Ext{ + Data: proto.String("hi"), + } + ext2 := &pb.Ext{ + Data: proto.String("there"), + } + exists := proto.HasExtension(msg, pb.E_Ext_More) + if exists { + t.Error("Extension More present unexpectedly") + } + if err := proto.SetExtension(msg, pb.E_Ext_More, ext1); err != nil { + t.Error(err) + } + if err := proto.SetExtension(msg, pb.E_Ext_More, ext2); err != nil { + t.Error(err) + } + e, err := proto.GetExtension(msg, pb.E_Ext_More) + if err != nil { + t.Error(err) + } + x, ok := e.(*pb.Ext) + if !ok { + t.Errorf("e has type %T, expected testdata.Ext", e) + } else if *x.Data != "there" { + t.Errorf("SetExtension failed to overwrite, got %+v, not 'there'", x) + } + proto.ClearExtension(msg, pb.E_Ext_More) + if _, err = proto.GetExtension(msg, pb.E_Ext_More); err != proto.ErrMissingExtension { + t.Errorf("got %v, expected ErrMissingExtension", e) + } + if _, err := proto.GetExtension(msg, pb.E_X215); err == nil { + t.Error("expected bad extension error, got nil") + } + if err := proto.SetExtension(msg, pb.E_X215, 12); err == nil { + t.Error("expected extension err") + } + if err := proto.SetExtension(msg, pb.E_Ext_More, 12); err == nil { + t.Error("expected some sort of type mismatch error, got nil") + } +} + +func TestNilExtension(t *testing.T) { + msg := &pb.MyMessage{ + Count: proto.Int32(1), + } + if err := proto.SetExtension(msg, pb.E_Ext_Text, proto.String("hello")); err != nil { + t.Fatal(err) + } + if err := proto.SetExtension(msg, pb.E_Ext_More, (*pb.Ext)(nil)); err == nil { + t.Error("expected SetExtension to fail due to a nil extension") + } else if want := "proto: SetExtension called with nil value of type *testdata.Ext"; err.Error() != want { + t.Errorf("expected error %v, got %v", want, err) + } + // Note: if the behavior of Marshal is ever changed to ignore nil extensions, update + // this test to verify that E_Ext_Text is properly propagated through marshal->unmarshal. +} + +func TestMarshalUnmarshalRepeatedExtension(t *testing.T) { + // Add a repeated extension to the result. + tests := []struct { + name string + ext []*pb.ComplexExtension + }{ + { + "two fields", + []*pb.ComplexExtension{ + {First: proto.Int32(7)}, + {Second: proto.Int32(11)}, + }, + }, + { + "repeated field", + []*pb.ComplexExtension{ + {Third: []int32{1000}}, + {Third: []int32{2000}}, + }, + }, + { + "two fields and repeated field", + []*pb.ComplexExtension{ + {Third: []int32{1000}}, + {First: proto.Int32(9)}, + {Second: proto.Int32(21)}, + {Third: []int32{2000}}, + }, + }, + } + for _, test := range tests { + // Marshal message with a repeated extension. + msg1 := new(pb.OtherMessage) + err := proto.SetExtension(msg1, pb.E_RComplex, test.ext) + if err != nil { + t.Fatalf("[%s] Error setting extension: %v", test.name, err) + } + b, err := proto.Marshal(msg1) + if err != nil { + t.Fatalf("[%s] Error marshaling message: %v", test.name, err) + } + + // Unmarshal and read the merged proto. + msg2 := new(pb.OtherMessage) + err = proto.Unmarshal(b, msg2) + if err != nil { + t.Fatalf("[%s] Error unmarshaling message: %v", test.name, err) + } + e, err := proto.GetExtension(msg2, pb.E_RComplex) + if err != nil { + t.Fatalf("[%s] Error getting extension: %v", test.name, err) + } + ext := e.([]*pb.ComplexExtension) + if ext == nil { + t.Fatalf("[%s] Invalid extension", test.name) + } + if !reflect.DeepEqual(ext, test.ext) { + t.Errorf("[%s] Wrong value for ComplexExtension: got: %v want: %v\n", test.name, ext, test.ext) + } + } +} + +func TestUnmarshalRepeatingNonRepeatedExtension(t *testing.T) { + // We may see multiple instances of the same extension in the wire + // format. For example, the proto compiler may encode custom options in + // this way. Here, we verify that we merge the extensions together. + tests := []struct { + name string + ext []*pb.ComplexExtension + }{ + { + "two fields", + []*pb.ComplexExtension{ + {First: proto.Int32(7)}, + {Second: proto.Int32(11)}, + }, + }, + { + "repeated field", + []*pb.ComplexExtension{ + {Third: []int32{1000}}, + {Third: []int32{2000}}, + }, + }, + { + "two fields and repeated field", + []*pb.ComplexExtension{ + {Third: []int32{1000}}, + {First: proto.Int32(9)}, + {Second: proto.Int32(21)}, + {Third: []int32{2000}}, + }, + }, + } + for _, test := range tests { + var buf bytes.Buffer + var want pb.ComplexExtension + + // Generate a serialized representation of a repeated extension + // by catenating bytes together. + for i, e := range test.ext { + // Merge to create the wanted proto. + proto.Merge(&want, e) + + // serialize the message + msg := new(pb.OtherMessage) + err := proto.SetExtension(msg, pb.E_Complex, e) + if err != nil { + t.Fatalf("[%s] Error setting extension %d: %v", test.name, i, err) + } + b, err := proto.Marshal(msg) + if err != nil { + t.Fatalf("[%s] Error marshaling message %d: %v", test.name, i, err) + } + buf.Write(b) + } + + // Unmarshal and read the merged proto. + msg2 := new(pb.OtherMessage) + err := proto.Unmarshal(buf.Bytes(), msg2) + if err != nil { + t.Fatalf("[%s] Error unmarshaling message: %v", test.name, err) + } + e, err := proto.GetExtension(msg2, pb.E_Complex) + if err != nil { + t.Fatalf("[%s] Error getting extension: %v", test.name, err) + } + ext := e.(*pb.ComplexExtension) + if ext == nil { + t.Fatalf("[%s] Invalid extension", test.name) + } + if !reflect.DeepEqual(*ext, want) { + t.Errorf("[%s] Wrong value for ComplexExtension: got: %s want: %s\n", test.name, ext, want) + } + } +} + +func TestClearAllExtensions(t *testing.T) { + // unregistered extension + desc := &proto.ExtensionDesc{ + ExtendedType: (*pb.MyMessage)(nil), + ExtensionType: (*bool)(nil), + Field: 101010100, + Name: "emptyextension", + Tag: "varint,0,opt", + } + m := &pb.MyMessage{} + if proto.HasExtension(m, desc) { + t.Errorf("proto.HasExtension(%s): got true, want false", proto.MarshalTextString(m)) + } + if err := proto.SetExtension(m, desc, proto.Bool(true)); err != nil { + t.Errorf("proto.SetExtension(m, desc, true): got error %q, want nil", err) + } + if !proto.HasExtension(m, desc) { + t.Errorf("proto.HasExtension(%s): got false, want true", proto.MarshalTextString(m)) + } + proto.ClearAllExtensions(m) + if proto.HasExtension(m, desc) { + t.Errorf("proto.HasExtension(%s): got true, want false", proto.MarshalTextString(m)) + } +} + +func TestMarshalRace(t *testing.T) { + // unregistered extension + desc := &proto.ExtensionDesc{ + ExtendedType: (*pb.MyMessage)(nil), + ExtensionType: (*bool)(nil), + Field: 101010100, + Name: "emptyextension", + Tag: "varint,0,opt", + } + + m := &pb.MyMessage{Count: proto.Int32(4)} + if err := proto.SetExtension(m, desc, proto.Bool(true)); err != nil { + t.Errorf("proto.SetExtension(m, desc, true): got error %q, want nil", err) + } + + var g errgroup.Group + for n := 3; n > 0; n-- { + g.Go(func() error { + _, err := proto.Marshal(m) + return err + }) + } + if err := g.Wait(); err != nil { + t.Fatal(err) + } +} diff --git a/vendor/github.com/golang/protobuf/proto/lib.go b/vendor/github.com/golang/protobuf/proto/lib.go new file mode 100644 index 00000000..1c225504 --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/lib.go @@ -0,0 +1,897 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2010 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// 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 +// OWNER 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. + +/* +Package proto converts data structures to and from the wire format of +protocol buffers. It works in concert with the Go source code generated +for .proto files by the protocol compiler. + +A summary of the properties of the protocol buffer interface +for a protocol buffer variable v: + + - Names are turned from camel_case to CamelCase for export. + - There are no methods on v to set fields; just treat + them as structure fields. + - There are getters that return a field's value if set, + and return the field's default value if unset. + The getters work even if the receiver is a nil message. + - The zero value for a struct is its correct initialization state. + All desired fields must be set before marshaling. + - A Reset() method will restore a protobuf struct to its zero state. + - Non-repeated fields are pointers to the values; nil means unset. + That is, optional or required field int32 f becomes F *int32. + - Repeated fields are slices. + - Helper functions are available to aid the setting of fields. + msg.Foo = proto.String("hello") // set field + - Constants are defined to hold the default values of all fields that + have them. They have the form Default_StructName_FieldName. + Because the getter methods handle defaulted values, + direct use of these constants should be rare. + - Enums are given type names and maps from names to values. + Enum values are prefixed by the enclosing message's name, or by the + enum's type name if it is a top-level enum. Enum types have a String + method, and a Enum method to assist in message construction. + - Nested messages, groups and enums have type names prefixed with the name of + the surrounding message type. + - Extensions are given descriptor names that start with E_, + followed by an underscore-delimited list of the nested messages + that contain it (if any) followed by the CamelCased name of the + extension field itself. HasExtension, ClearExtension, GetExtension + and SetExtension are functions for manipulating extensions. + - Oneof field sets are given a single field in their message, + with distinguished wrapper types for each possible field value. + - Marshal and Unmarshal are functions to encode and decode the wire format. + +When the .proto file specifies `syntax="proto3"`, there are some differences: + + - Non-repeated fields of non-message type are values instead of pointers. + - Enum types do not get an Enum method. + +The simplest way to describe this is to see an example. +Given file test.proto, containing + + package example; + + enum FOO { X = 17; } + + message Test { + required string label = 1; + optional int32 type = 2 [default=77]; + repeated int64 reps = 3; + optional group OptionalGroup = 4 { + required string RequiredField = 5; + } + oneof union { + int32 number = 6; + string name = 7; + } + } + +The resulting file, test.pb.go, is: + + package example + + import proto "github.com/golang/protobuf/proto" + import math "math" + + type FOO int32 + const ( + FOO_X FOO = 17 + ) + var FOO_name = map[int32]string{ + 17: "X", + } + var FOO_value = map[string]int32{ + "X": 17, + } + + func (x FOO) Enum() *FOO { + p := new(FOO) + *p = x + return p + } + func (x FOO) String() string { + return proto.EnumName(FOO_name, int32(x)) + } + func (x *FOO) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(FOO_value, data) + if err != nil { + return err + } + *x = FOO(value) + return nil + } + + type Test struct { + Label *string `protobuf:"bytes,1,req,name=label" json:"label,omitempty"` + Type *int32 `protobuf:"varint,2,opt,name=type,def=77" json:"type,omitempty"` + Reps []int64 `protobuf:"varint,3,rep,name=reps" json:"reps,omitempty"` + Optionalgroup *Test_OptionalGroup `protobuf:"group,4,opt,name=OptionalGroup" json:"optionalgroup,omitempty"` + // Types that are valid to be assigned to Union: + // *Test_Number + // *Test_Name + Union isTest_Union `protobuf_oneof:"union"` + XXX_unrecognized []byte `json:"-"` + } + func (m *Test) Reset() { *m = Test{} } + func (m *Test) String() string { return proto.CompactTextString(m) } + func (*Test) ProtoMessage() {} + + type isTest_Union interface { + isTest_Union() + } + + type Test_Number struct { + Number int32 `protobuf:"varint,6,opt,name=number"` + } + type Test_Name struct { + Name string `protobuf:"bytes,7,opt,name=name"` + } + + func (*Test_Number) isTest_Union() {} + func (*Test_Name) isTest_Union() {} + + func (m *Test) GetUnion() isTest_Union { + if m != nil { + return m.Union + } + return nil + } + const Default_Test_Type int32 = 77 + + func (m *Test) GetLabel() string { + if m != nil && m.Label != nil { + return *m.Label + } + return "" + } + + func (m *Test) GetType() int32 { + if m != nil && m.Type != nil { + return *m.Type + } + return Default_Test_Type + } + + func (m *Test) GetOptionalgroup() *Test_OptionalGroup { + if m != nil { + return m.Optionalgroup + } + return nil + } + + type Test_OptionalGroup struct { + RequiredField *string `protobuf:"bytes,5,req" json:"RequiredField,omitempty"` + } + func (m *Test_OptionalGroup) Reset() { *m = Test_OptionalGroup{} } + func (m *Test_OptionalGroup) String() string { return proto.CompactTextString(m) } + + func (m *Test_OptionalGroup) GetRequiredField() string { + if m != nil && m.RequiredField != nil { + return *m.RequiredField + } + return "" + } + + func (m *Test) GetNumber() int32 { + if x, ok := m.GetUnion().(*Test_Number); ok { + return x.Number + } + return 0 + } + + func (m *Test) GetName() string { + if x, ok := m.GetUnion().(*Test_Name); ok { + return x.Name + } + return "" + } + + func init() { + proto.RegisterEnum("example.FOO", FOO_name, FOO_value) + } + +To create and play with a Test object: + + package main + + import ( + "log" + + "github.com/golang/protobuf/proto" + pb "./example.pb" + ) + + func main() { + test := &pb.Test{ + Label: proto.String("hello"), + Type: proto.Int32(17), + Reps: []int64{1, 2, 3}, + Optionalgroup: &pb.Test_OptionalGroup{ + RequiredField: proto.String("good bye"), + }, + Union: &pb.Test_Name{"fred"}, + } + data, err := proto.Marshal(test) + if err != nil { + log.Fatal("marshaling error: ", err) + } + newTest := &pb.Test{} + err = proto.Unmarshal(data, newTest) + if err != nil { + log.Fatal("unmarshaling error: ", err) + } + // Now test and newTest contain the same data. + if test.GetLabel() != newTest.GetLabel() { + log.Fatalf("data mismatch %q != %q", test.GetLabel(), newTest.GetLabel()) + } + // Use a type switch to determine which oneof was set. + switch u := test.Union.(type) { + case *pb.Test_Number: // u.Number contains the number. + case *pb.Test_Name: // u.Name contains the string. + } + // etc. + } +*/ +package proto + +import ( + "encoding/json" + "fmt" + "log" + "reflect" + "sort" + "strconv" + "sync" +) + +// Message is implemented by generated protocol buffer messages. +type Message interface { + Reset() + String() string + ProtoMessage() +} + +// Stats records allocation details about the protocol buffer encoders +// and decoders. Useful for tuning the library itself. +type Stats struct { + Emalloc uint64 // mallocs in encode + Dmalloc uint64 // mallocs in decode + Encode uint64 // number of encodes + Decode uint64 // number of decodes + Chit uint64 // number of cache hits + Cmiss uint64 // number of cache misses + Size uint64 // number of sizes +} + +// Set to true to enable stats collection. +const collectStats = false + +var stats Stats + +// GetStats returns a copy of the global Stats structure. +func GetStats() Stats { return stats } + +// A Buffer is a buffer manager for marshaling and unmarshaling +// protocol buffers. It may be reused between invocations to +// reduce memory usage. It is not necessary to use a Buffer; +// the global functions Marshal and Unmarshal create a +// temporary Buffer and are fine for most applications. +type Buffer struct { + buf []byte // encode/decode byte stream + index int // read point + + // pools of basic types to amortize allocation. + bools []bool + uint32s []uint32 + uint64s []uint64 + + // extra pools, only used with pointer_reflect.go + int32s []int32 + int64s []int64 + float32s []float32 + float64s []float64 +} + +// NewBuffer allocates a new Buffer and initializes its internal data to +// the contents of the argument slice. +func NewBuffer(e []byte) *Buffer { + return &Buffer{buf: e} +} + +// Reset resets the Buffer, ready for marshaling a new protocol buffer. +func (p *Buffer) Reset() { + p.buf = p.buf[0:0] // for reading/writing + p.index = 0 // for reading +} + +// SetBuf replaces the internal buffer with the slice, +// ready for unmarshaling the contents of the slice. +func (p *Buffer) SetBuf(s []byte) { + p.buf = s + p.index = 0 +} + +// Bytes returns the contents of the Buffer. +func (p *Buffer) Bytes() []byte { return p.buf } + +/* + * Helper routines for simplifying the creation of optional fields of basic type. + */ + +// Bool is a helper routine that allocates a new bool value +// to store v and returns a pointer to it. +func Bool(v bool) *bool { + return &v +} + +// Int32 is a helper routine that allocates a new int32 value +// to store v and returns a pointer to it. +func Int32(v int32) *int32 { + return &v +} + +// Int is a helper routine that allocates a new int32 value +// to store v and returns a pointer to it, but unlike Int32 +// its argument value is an int. +func Int(v int) *int32 { + p := new(int32) + *p = int32(v) + return p +} + +// Int64 is a helper routine that allocates a new int64 value +// to store v and returns a pointer to it. +func Int64(v int64) *int64 { + return &v +} + +// Float32 is a helper routine that allocates a new float32 value +// to store v and returns a pointer to it. +func Float32(v float32) *float32 { + return &v +} + +// Float64 is a helper routine that allocates a new float64 value +// to store v and returns a pointer to it. +func Float64(v float64) *float64 { + return &v +} + +// Uint32 is a helper routine that allocates a new uint32 value +// to store v and returns a pointer to it. +func Uint32(v uint32) *uint32 { + return &v +} + +// Uint64 is a helper routine that allocates a new uint64 value +// to store v and returns a pointer to it. +func Uint64(v uint64) *uint64 { + return &v +} + +// String is a helper routine that allocates a new string value +// to store v and returns a pointer to it. +func String(v string) *string { + return &v +} + +// EnumName is a helper function to simplify printing protocol buffer enums +// by name. Given an enum map and a value, it returns a useful string. +func EnumName(m map[int32]string, v int32) string { + s, ok := m[v] + if ok { + return s + } + return strconv.Itoa(int(v)) +} + +// UnmarshalJSONEnum is a helper function to simplify recovering enum int values +// from their JSON-encoded representation. Given a map from the enum's symbolic +// names to its int values, and a byte buffer containing the JSON-encoded +// value, it returns an int32 that can be cast to the enum type by the caller. +// +// The function can deal with both JSON representations, numeric and symbolic. +func UnmarshalJSONEnum(m map[string]int32, data []byte, enumName string) (int32, error) { + if data[0] == '"' { + // New style: enums are strings. + var repr string + if err := json.Unmarshal(data, &repr); err != nil { + return -1, err + } + val, ok := m[repr] + if !ok { + return 0, fmt.Errorf("unrecognized enum %s value %q", enumName, repr) + } + return val, nil + } + // Old style: enums are ints. + var val int32 + if err := json.Unmarshal(data, &val); err != nil { + return 0, fmt.Errorf("cannot unmarshal %#q into enum %s", data, enumName) + } + return val, nil +} + +// DebugPrint dumps the encoded data in b in a debugging format with a header +// including the string s. Used in testing but made available for general debugging. +func (p *Buffer) DebugPrint(s string, b []byte) { + var u uint64 + + obuf := p.buf + index := p.index + p.buf = b + p.index = 0 + depth := 0 + + fmt.Printf("\n--- %s ---\n", s) + +out: + for { + for i := 0; i < depth; i++ { + fmt.Print(" ") + } + + index := p.index + if index == len(p.buf) { + break + } + + op, err := p.DecodeVarint() + if err != nil { + fmt.Printf("%3d: fetching op err %v\n", index, err) + break out + } + tag := op >> 3 + wire := op & 7 + + switch wire { + default: + fmt.Printf("%3d: t=%3d unknown wire=%d\n", + index, tag, wire) + break out + + case WireBytes: + var r []byte + + r, err = p.DecodeRawBytes(false) + if err != nil { + break out + } + fmt.Printf("%3d: t=%3d bytes [%d]", index, tag, len(r)) + if len(r) <= 6 { + for i := 0; i < len(r); i++ { + fmt.Printf(" %.2x", r[i]) + } + } else { + for i := 0; i < 3; i++ { + fmt.Printf(" %.2x", r[i]) + } + fmt.Printf(" ..") + for i := len(r) - 3; i < len(r); i++ { + fmt.Printf(" %.2x", r[i]) + } + } + fmt.Printf("\n") + + case WireFixed32: + u, err = p.DecodeFixed32() + if err != nil { + fmt.Printf("%3d: t=%3d fix32 err %v\n", index, tag, err) + break out + } + fmt.Printf("%3d: t=%3d fix32 %d\n", index, tag, u) + + case WireFixed64: + u, err = p.DecodeFixed64() + if err != nil { + fmt.Printf("%3d: t=%3d fix64 err %v\n", index, tag, err) + break out + } + fmt.Printf("%3d: t=%3d fix64 %d\n", index, tag, u) + + case WireVarint: + u, err = p.DecodeVarint() + if err != nil { + fmt.Printf("%3d: t=%3d varint err %v\n", index, tag, err) + break out + } + fmt.Printf("%3d: t=%3d varint %d\n", index, tag, u) + + case WireStartGroup: + fmt.Printf("%3d: t=%3d start\n", index, tag) + depth++ + + case WireEndGroup: + depth-- + fmt.Printf("%3d: t=%3d end\n", index, tag) + } + } + + if depth != 0 { + fmt.Printf("%3d: start-end not balanced %d\n", p.index, depth) + } + fmt.Printf("\n") + + p.buf = obuf + p.index = index +} + +// SetDefaults sets unset protocol buffer fields to their default values. +// It only modifies fields that are both unset and have defined defaults. +// It recursively sets default values in any non-nil sub-messages. +func SetDefaults(pb Message) { + setDefaults(reflect.ValueOf(pb), true, false) +} + +// v is a pointer to a struct. +func setDefaults(v reflect.Value, recur, zeros bool) { + v = v.Elem() + + defaultMu.RLock() + dm, ok := defaults[v.Type()] + defaultMu.RUnlock() + if !ok { + dm = buildDefaultMessage(v.Type()) + defaultMu.Lock() + defaults[v.Type()] = dm + defaultMu.Unlock() + } + + for _, sf := range dm.scalars { + f := v.Field(sf.index) + if !f.IsNil() { + // field already set + continue + } + dv := sf.value + if dv == nil && !zeros { + // no explicit default, and don't want to set zeros + continue + } + fptr := f.Addr().Interface() // **T + // TODO: Consider batching the allocations we do here. + switch sf.kind { + case reflect.Bool: + b := new(bool) + if dv != nil { + *b = dv.(bool) + } + *(fptr.(**bool)) = b + case reflect.Float32: + f := new(float32) + if dv != nil { + *f = dv.(float32) + } + *(fptr.(**float32)) = f + case reflect.Float64: + f := new(float64) + if dv != nil { + *f = dv.(float64) + } + *(fptr.(**float64)) = f + case reflect.Int32: + // might be an enum + if ft := f.Type(); ft != int32PtrType { + // enum + f.Set(reflect.New(ft.Elem())) + if dv != nil { + f.Elem().SetInt(int64(dv.(int32))) + } + } else { + // int32 field + i := new(int32) + if dv != nil { + *i = dv.(int32) + } + *(fptr.(**int32)) = i + } + case reflect.Int64: + i := new(int64) + if dv != nil { + *i = dv.(int64) + } + *(fptr.(**int64)) = i + case reflect.String: + s := new(string) + if dv != nil { + *s = dv.(string) + } + *(fptr.(**string)) = s + case reflect.Uint8: + // exceptional case: []byte + var b []byte + if dv != nil { + db := dv.([]byte) + b = make([]byte, len(db)) + copy(b, db) + } else { + b = []byte{} + } + *(fptr.(*[]byte)) = b + case reflect.Uint32: + u := new(uint32) + if dv != nil { + *u = dv.(uint32) + } + *(fptr.(**uint32)) = u + case reflect.Uint64: + u := new(uint64) + if dv != nil { + *u = dv.(uint64) + } + *(fptr.(**uint64)) = u + default: + log.Printf("proto: can't set default for field %v (sf.kind=%v)", f, sf.kind) + } + } + + for _, ni := range dm.nested { + f := v.Field(ni) + // f is *T or []*T or map[T]*T + switch f.Kind() { + case reflect.Ptr: + if f.IsNil() { + continue + } + setDefaults(f, recur, zeros) + + case reflect.Slice: + for i := 0; i < f.Len(); i++ { + e := f.Index(i) + if e.IsNil() { + continue + } + setDefaults(e, recur, zeros) + } + + case reflect.Map: + for _, k := range f.MapKeys() { + e := f.MapIndex(k) + if e.IsNil() { + continue + } + setDefaults(e, recur, zeros) + } + } + } +} + +var ( + // defaults maps a protocol buffer struct type to a slice of the fields, + // with its scalar fields set to their proto-declared non-zero default values. + defaultMu sync.RWMutex + defaults = make(map[reflect.Type]defaultMessage) + + int32PtrType = reflect.TypeOf((*int32)(nil)) +) + +// defaultMessage represents information about the default values of a message. +type defaultMessage struct { + scalars []scalarField + nested []int // struct field index of nested messages +} + +type scalarField struct { + index int // struct field index + kind reflect.Kind // element type (the T in *T or []T) + value interface{} // the proto-declared default value, or nil +} + +// t is a struct type. +func buildDefaultMessage(t reflect.Type) (dm defaultMessage) { + sprop := GetProperties(t) + for _, prop := range sprop.Prop { + fi, ok := sprop.decoderTags.get(prop.Tag) + if !ok { + // XXX_unrecognized + continue + } + ft := t.Field(fi).Type + + sf, nested, err := fieldDefault(ft, prop) + switch { + case err != nil: + log.Print(err) + case nested: + dm.nested = append(dm.nested, fi) + case sf != nil: + sf.index = fi + dm.scalars = append(dm.scalars, *sf) + } + } + + return dm +} + +// fieldDefault returns the scalarField for field type ft. +// sf will be nil if the field can not have a default. +// nestedMessage will be true if this is a nested message. +// Note that sf.index is not set on return. +func fieldDefault(ft reflect.Type, prop *Properties) (sf *scalarField, nestedMessage bool, err error) { + var canHaveDefault bool + switch ft.Kind() { + case reflect.Ptr: + if ft.Elem().Kind() == reflect.Struct { + nestedMessage = true + } else { + canHaveDefault = true // proto2 scalar field + } + + case reflect.Slice: + switch ft.Elem().Kind() { + case reflect.Ptr: + nestedMessage = true // repeated message + case reflect.Uint8: + canHaveDefault = true // bytes field + } + + case reflect.Map: + if ft.Elem().Kind() == reflect.Ptr { + nestedMessage = true // map with message values + } + } + + if !canHaveDefault { + if nestedMessage { + return nil, true, nil + } + return nil, false, nil + } + + // We now know that ft is a pointer or slice. + sf = &scalarField{kind: ft.Elem().Kind()} + + // scalar fields without defaults + if !prop.HasDefault { + return sf, false, nil + } + + // a scalar field: either *T or []byte + switch ft.Elem().Kind() { + case reflect.Bool: + x, err := strconv.ParseBool(prop.Default) + if err != nil { + return nil, false, fmt.Errorf("proto: bad default bool %q: %v", prop.Default, err) + } + sf.value = x + case reflect.Float32: + x, err := strconv.ParseFloat(prop.Default, 32) + if err != nil { + return nil, false, fmt.Errorf("proto: bad default float32 %q: %v", prop.Default, err) + } + sf.value = float32(x) + case reflect.Float64: + x, err := strconv.ParseFloat(prop.Default, 64) + if err != nil { + return nil, false, fmt.Errorf("proto: bad default float64 %q: %v", prop.Default, err) + } + sf.value = x + case reflect.Int32: + x, err := strconv.ParseInt(prop.Default, 10, 32) + if err != nil { + return nil, false, fmt.Errorf("proto: bad default int32 %q: %v", prop.Default, err) + } + sf.value = int32(x) + case reflect.Int64: + x, err := strconv.ParseInt(prop.Default, 10, 64) + if err != nil { + return nil, false, fmt.Errorf("proto: bad default int64 %q: %v", prop.Default, err) + } + sf.value = x + case reflect.String: + sf.value = prop.Default + case reflect.Uint8: + // []byte (not *uint8) + sf.value = []byte(prop.Default) + case reflect.Uint32: + x, err := strconv.ParseUint(prop.Default, 10, 32) + if err != nil { + return nil, false, fmt.Errorf("proto: bad default uint32 %q: %v", prop.Default, err) + } + sf.value = uint32(x) + case reflect.Uint64: + x, err := strconv.ParseUint(prop.Default, 10, 64) + if err != nil { + return nil, false, fmt.Errorf("proto: bad default uint64 %q: %v", prop.Default, err) + } + sf.value = x + default: + return nil, false, fmt.Errorf("proto: unhandled def kind %v", ft.Elem().Kind()) + } + + return sf, false, nil +} + +// Map fields may have key types of non-float scalars, strings and enums. +// The easiest way to sort them in some deterministic order is to use fmt. +// If this turns out to be inefficient we can always consider other options, +// such as doing a Schwartzian transform. + +func mapKeys(vs []reflect.Value) sort.Interface { + s := mapKeySorter{ + vs: vs, + // default Less function: textual comparison + less: func(a, b reflect.Value) bool { + return fmt.Sprint(a.Interface()) < fmt.Sprint(b.Interface()) + }, + } + + // Type specialization per https://developers.google.com/protocol-buffers/docs/proto#maps; + // numeric keys are sorted numerically. + if len(vs) == 0 { + return s + } + switch vs[0].Kind() { + case reflect.Int32, reflect.Int64: + s.less = func(a, b reflect.Value) bool { return a.Int() < b.Int() } + case reflect.Uint32, reflect.Uint64: + s.less = func(a, b reflect.Value) bool { return a.Uint() < b.Uint() } + } + + return s +} + +type mapKeySorter struct { + vs []reflect.Value + less func(a, b reflect.Value) bool +} + +func (s mapKeySorter) Len() int { return len(s.vs) } +func (s mapKeySorter) Swap(i, j int) { s.vs[i], s.vs[j] = s.vs[j], s.vs[i] } +func (s mapKeySorter) Less(i, j int) bool { + return s.less(s.vs[i], s.vs[j]) +} + +// isProto3Zero reports whether v is a zero proto3 value. +func isProto3Zero(v reflect.Value) bool { + switch v.Kind() { + case reflect.Bool: + return !v.Bool() + case reflect.Int32, reflect.Int64: + return v.Int() == 0 + case reflect.Uint32, reflect.Uint64: + return v.Uint() == 0 + case reflect.Float32, reflect.Float64: + return v.Float() == 0 + case reflect.String: + return v.String() == "" + } + return false +} + +// ProtoPackageIsVersion2 is referenced from generated protocol buffer files +// to assert that that code is compatible with this version of the proto package. +const ProtoPackageIsVersion2 = true + +// ProtoPackageIsVersion1 is referenced from generated protocol buffer files +// to assert that that code is compatible with this version of the proto package. +const ProtoPackageIsVersion1 = true diff --git a/vendor/github.com/golang/protobuf/proto/map_test.go b/vendor/github.com/golang/protobuf/proto/map_test.go new file mode 100644 index 00000000..313e8792 --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/map_test.go @@ -0,0 +1,46 @@ +package proto_test + +import ( + "fmt" + "testing" + + "github.com/golang/protobuf/proto" + ppb "github.com/golang/protobuf/proto/proto3_proto" +) + +func marshalled() []byte { + m := &ppb.IntMaps{} + for i := 0; i < 1000; i++ { + m.Maps = append(m.Maps, &ppb.IntMap{ + Rtt: map[int32]int32{1: 2}, + }) + } + b, err := proto.Marshal(m) + if err != nil { + panic(fmt.Sprintf("Can't marshal %+v: %v", m, err)) + } + return b +} + +func BenchmarkConcurrentMapUnmarshal(b *testing.B) { + in := marshalled() + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + var out ppb.IntMaps + if err := proto.Unmarshal(in, &out); err != nil { + b.Errorf("Can't unmarshal ppb.IntMaps: %v", err) + } + } + }) +} + +func BenchmarkSequentialMapUnmarshal(b *testing.B) { + in := marshalled() + b.ResetTimer() + for i := 0; i < b.N; i++ { + var out ppb.IntMaps + if err := proto.Unmarshal(in, &out); err != nil { + b.Errorf("Can't unmarshal ppb.IntMaps: %v", err) + } + } +} diff --git a/vendor/github.com/golang/protobuf/proto/message_set.go b/vendor/github.com/golang/protobuf/proto/message_set.go new file mode 100644 index 00000000..fd982dec --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/message_set.go @@ -0,0 +1,311 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2010 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// 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 +// OWNER 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. + +package proto + +/* + * Support for message sets. + */ + +import ( + "bytes" + "encoding/json" + "errors" + "fmt" + "reflect" + "sort" +) + +// errNoMessageTypeID occurs when a protocol buffer does not have a message type ID. +// A message type ID is required for storing a protocol buffer in a message set. +var errNoMessageTypeID = errors.New("proto does not have a message type ID") + +// The first two types (_MessageSet_Item and messageSet) +// model what the protocol compiler produces for the following protocol message: +// message MessageSet { +// repeated group Item = 1 { +// required int32 type_id = 2; +// required string message = 3; +// }; +// } +// That is the MessageSet wire format. We can't use a proto to generate these +// because that would introduce a circular dependency between it and this package. + +type _MessageSet_Item struct { + TypeId *int32 `protobuf:"varint,2,req,name=type_id"` + Message []byte `protobuf:"bytes,3,req,name=message"` +} + +type messageSet struct { + Item []*_MessageSet_Item `protobuf:"group,1,rep"` + XXX_unrecognized []byte + // TODO: caching? +} + +// Make sure messageSet is a Message. +var _ Message = (*messageSet)(nil) + +// messageTypeIder is an interface satisfied by a protocol buffer type +// that may be stored in a MessageSet. +type messageTypeIder interface { + MessageTypeId() int32 +} + +func (ms *messageSet) find(pb Message) *_MessageSet_Item { + mti, ok := pb.(messageTypeIder) + if !ok { + return nil + } + id := mti.MessageTypeId() + for _, item := range ms.Item { + if *item.TypeId == id { + return item + } + } + return nil +} + +func (ms *messageSet) Has(pb Message) bool { + if ms.find(pb) != nil { + return true + } + return false +} + +func (ms *messageSet) Unmarshal(pb Message) error { + if item := ms.find(pb); item != nil { + return Unmarshal(item.Message, pb) + } + if _, ok := pb.(messageTypeIder); !ok { + return errNoMessageTypeID + } + return nil // TODO: return error instead? +} + +func (ms *messageSet) Marshal(pb Message) error { + msg, err := Marshal(pb) + if err != nil { + return err + } + if item := ms.find(pb); item != nil { + // reuse existing item + item.Message = msg + return nil + } + + mti, ok := pb.(messageTypeIder) + if !ok { + return errNoMessageTypeID + } + + mtid := mti.MessageTypeId() + ms.Item = append(ms.Item, &_MessageSet_Item{ + TypeId: &mtid, + Message: msg, + }) + return nil +} + +func (ms *messageSet) Reset() { *ms = messageSet{} } +func (ms *messageSet) String() string { return CompactTextString(ms) } +func (*messageSet) ProtoMessage() {} + +// Support for the message_set_wire_format message option. + +func skipVarint(buf []byte) []byte { + i := 0 + for ; buf[i]&0x80 != 0; i++ { + } + return buf[i+1:] +} + +// MarshalMessageSet encodes the extension map represented by m in the message set wire format. +// It is called by generated Marshal methods on protocol buffer messages with the message_set_wire_format option. +func MarshalMessageSet(exts interface{}) ([]byte, error) { + var m map[int32]Extension + switch exts := exts.(type) { + case *XXX_InternalExtensions: + if err := encodeExtensions(exts); err != nil { + return nil, err + } + m, _ = exts.extensionsRead() + case map[int32]Extension: + if err := encodeExtensionsMap(exts); err != nil { + return nil, err + } + m = exts + default: + return nil, errors.New("proto: not an extension map") + } + + // Sort extension IDs to provide a deterministic encoding. + // See also enc_map in encode.go. + ids := make([]int, 0, len(m)) + for id := range m { + ids = append(ids, int(id)) + } + sort.Ints(ids) + + ms := &messageSet{Item: make([]*_MessageSet_Item, 0, len(m))} + for _, id := range ids { + e := m[int32(id)] + // Remove the wire type and field number varint, as well as the length varint. + msg := skipVarint(skipVarint(e.enc)) + + ms.Item = append(ms.Item, &_MessageSet_Item{ + TypeId: Int32(int32(id)), + Message: msg, + }) + } + return Marshal(ms) +} + +// UnmarshalMessageSet decodes the extension map encoded in buf in the message set wire format. +// It is called by generated Unmarshal methods on protocol buffer messages with the message_set_wire_format option. +func UnmarshalMessageSet(buf []byte, exts interface{}) error { + var m map[int32]Extension + switch exts := exts.(type) { + case *XXX_InternalExtensions: + m = exts.extensionsWrite() + case map[int32]Extension: + m = exts + default: + return errors.New("proto: not an extension map") + } + + ms := new(messageSet) + if err := Unmarshal(buf, ms); err != nil { + return err + } + for _, item := range ms.Item { + id := *item.TypeId + msg := item.Message + + // Restore wire type and field number varint, plus length varint. + // Be careful to preserve duplicate items. + b := EncodeVarint(uint64(id)<<3 | WireBytes) + if ext, ok := m[id]; ok { + // Existing data; rip off the tag and length varint + // so we join the new data correctly. + // We can assume that ext.enc is set because we are unmarshaling. + o := ext.enc[len(b):] // skip wire type and field number + _, n := DecodeVarint(o) // calculate length of length varint + o = o[n:] // skip length varint + msg = append(o, msg...) // join old data and new data + } + b = append(b, EncodeVarint(uint64(len(msg)))...) + b = append(b, msg...) + + m[id] = Extension{enc: b} + } + return nil +} + +// MarshalMessageSetJSON encodes the extension map represented by m in JSON format. +// It is called by generated MarshalJSON methods on protocol buffer messages with the message_set_wire_format option. +func MarshalMessageSetJSON(exts interface{}) ([]byte, error) { + var m map[int32]Extension + switch exts := exts.(type) { + case *XXX_InternalExtensions: + m, _ = exts.extensionsRead() + case map[int32]Extension: + m = exts + default: + return nil, errors.New("proto: not an extension map") + } + var b bytes.Buffer + b.WriteByte('{') + + // Process the map in key order for deterministic output. + ids := make([]int32, 0, len(m)) + for id := range m { + ids = append(ids, id) + } + sort.Sort(int32Slice(ids)) // int32Slice defined in text.go + + for i, id := range ids { + ext := m[id] + if i > 0 { + b.WriteByte(',') + } + + msd, ok := messageSetMap[id] + if !ok { + // Unknown type; we can't render it, so skip it. + continue + } + fmt.Fprintf(&b, `"[%s]":`, msd.name) + + x := ext.value + if x == nil { + x = reflect.New(msd.t.Elem()).Interface() + if err := Unmarshal(ext.enc, x.(Message)); err != nil { + return nil, err + } + } + d, err := json.Marshal(x) + if err != nil { + return nil, err + } + b.Write(d) + } + b.WriteByte('}') + return b.Bytes(), nil +} + +// UnmarshalMessageSetJSON decodes the extension map encoded in buf in JSON format. +// It is called by generated UnmarshalJSON methods on protocol buffer messages with the message_set_wire_format option. +func UnmarshalMessageSetJSON(buf []byte, exts interface{}) error { + // Common-case fast path. + if len(buf) == 0 || bytes.Equal(buf, []byte("{}")) { + return nil + } + + // This is fairly tricky, and it's not clear that it is needed. + return errors.New("TODO: UnmarshalMessageSetJSON not yet implemented") +} + +// A global registry of types that can be used in a MessageSet. + +var messageSetMap = make(map[int32]messageSetDesc) + +type messageSetDesc struct { + t reflect.Type // pointer to struct + name string +} + +// RegisterMessageSetType is called from the generated code. +func RegisterMessageSetType(m Message, fieldNum int32, name string) { + messageSetMap[fieldNum] = messageSetDesc{ + t: reflect.TypeOf(m), + name: name, + } +} diff --git a/vendor/github.com/golang/protobuf/proto/message_set_test.go b/vendor/github.com/golang/protobuf/proto/message_set_test.go new file mode 100644 index 00000000..353a3ea7 --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/message_set_test.go @@ -0,0 +1,66 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2014 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// 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 +// OWNER 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. + +package proto + +import ( + "bytes" + "testing" +) + +func TestUnmarshalMessageSetWithDuplicate(t *testing.T) { + // Check that a repeated message set entry will be concatenated. + in := &messageSet{ + Item: []*_MessageSet_Item{ + {TypeId: Int32(12345), Message: []byte("hoo")}, + {TypeId: Int32(12345), Message: []byte("hah")}, + }, + } + b, err := Marshal(in) + if err != nil { + t.Fatalf("Marshal: %v", err) + } + t.Logf("Marshaled bytes: %q", b) + + var extensions XXX_InternalExtensions + if err := UnmarshalMessageSet(b, &extensions); err != nil { + t.Fatalf("UnmarshalMessageSet: %v", err) + } + ext, ok := extensions.p.extensionMap[12345] + if !ok { + t.Fatalf("Didn't retrieve extension 12345; map is %v", extensions.p.extensionMap) + } + // Skip wire type/field number and length varints. + got := skipVarint(skipVarint(ext.enc)) + if want := []byte("hoohah"); !bytes.Equal(got, want) { + t.Errorf("Combined extension is %q, want %q", got, want) + } +} diff --git a/vendor/github.com/golang/protobuf/proto/pointer_reflect.go b/vendor/github.com/golang/protobuf/proto/pointer_reflect.go new file mode 100644 index 00000000..fb512e2e --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/pointer_reflect.go @@ -0,0 +1,484 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2012 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// 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 +// OWNER 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. + +// +build appengine js + +// This file contains an implementation of proto field accesses using package reflect. +// It is slower than the code in pointer_unsafe.go but it avoids package unsafe and can +// be used on App Engine. + +package proto + +import ( + "math" + "reflect" +) + +// A structPointer is a pointer to a struct. +type structPointer struct { + v reflect.Value +} + +// toStructPointer returns a structPointer equivalent to the given reflect value. +// The reflect value must itself be a pointer to a struct. +func toStructPointer(v reflect.Value) structPointer { + return structPointer{v} +} + +// IsNil reports whether p is nil. +func structPointer_IsNil(p structPointer) bool { + return p.v.IsNil() +} + +// Interface returns the struct pointer as an interface value. +func structPointer_Interface(p structPointer, _ reflect.Type) interface{} { + return p.v.Interface() +} + +// A field identifies a field in a struct, accessible from a structPointer. +// In this implementation, a field is identified by the sequence of field indices +// passed to reflect's FieldByIndex. +type field []int + +// toField returns a field equivalent to the given reflect field. +func toField(f *reflect.StructField) field { + return f.Index +} + +// invalidField is an invalid field identifier. +var invalidField = field(nil) + +// IsValid reports whether the field identifier is valid. +func (f field) IsValid() bool { return f != nil } + +// field returns the given field in the struct as a reflect value. +func structPointer_field(p structPointer, f field) reflect.Value { + // Special case: an extension map entry with a value of type T + // passes a *T to the struct-handling code with a zero field, + // expecting that it will be treated as equivalent to *struct{ X T }, + // which has the same memory layout. We have to handle that case + // specially, because reflect will panic if we call FieldByIndex on a + // non-struct. + if f == nil { + return p.v.Elem() + } + + return p.v.Elem().FieldByIndex(f) +} + +// ifield returns the given field in the struct as an interface value. +func structPointer_ifield(p structPointer, f field) interface{} { + return structPointer_field(p, f).Addr().Interface() +} + +// Bytes returns the address of a []byte field in the struct. +func structPointer_Bytes(p structPointer, f field) *[]byte { + return structPointer_ifield(p, f).(*[]byte) +} + +// BytesSlice returns the address of a [][]byte field in the struct. +func structPointer_BytesSlice(p structPointer, f field) *[][]byte { + return structPointer_ifield(p, f).(*[][]byte) +} + +// Bool returns the address of a *bool field in the struct. +func structPointer_Bool(p structPointer, f field) **bool { + return structPointer_ifield(p, f).(**bool) +} + +// BoolVal returns the address of a bool field in the struct. +func structPointer_BoolVal(p structPointer, f field) *bool { + return structPointer_ifield(p, f).(*bool) +} + +// BoolSlice returns the address of a []bool field in the struct. +func structPointer_BoolSlice(p structPointer, f field) *[]bool { + return structPointer_ifield(p, f).(*[]bool) +} + +// String returns the address of a *string field in the struct. +func structPointer_String(p structPointer, f field) **string { + return structPointer_ifield(p, f).(**string) +} + +// StringVal returns the address of a string field in the struct. +func structPointer_StringVal(p structPointer, f field) *string { + return structPointer_ifield(p, f).(*string) +} + +// StringSlice returns the address of a []string field in the struct. +func structPointer_StringSlice(p structPointer, f field) *[]string { + return structPointer_ifield(p, f).(*[]string) +} + +// Extensions returns the address of an extension map field in the struct. +func structPointer_Extensions(p structPointer, f field) *XXX_InternalExtensions { + return structPointer_ifield(p, f).(*XXX_InternalExtensions) +} + +// ExtMap returns the address of an extension map field in the struct. +func structPointer_ExtMap(p structPointer, f field) *map[int32]Extension { + return structPointer_ifield(p, f).(*map[int32]Extension) +} + +// NewAt returns the reflect.Value for a pointer to a field in the struct. +func structPointer_NewAt(p structPointer, f field, typ reflect.Type) reflect.Value { + return structPointer_field(p, f).Addr() +} + +// SetStructPointer writes a *struct field in the struct. +func structPointer_SetStructPointer(p structPointer, f field, q structPointer) { + structPointer_field(p, f).Set(q.v) +} + +// GetStructPointer reads a *struct field in the struct. +func structPointer_GetStructPointer(p structPointer, f field) structPointer { + return structPointer{structPointer_field(p, f)} +} + +// StructPointerSlice the address of a []*struct field in the struct. +func structPointer_StructPointerSlice(p structPointer, f field) structPointerSlice { + return structPointerSlice{structPointer_field(p, f)} +} + +// A structPointerSlice represents the address of a slice of pointers to structs +// (themselves messages or groups). That is, v.Type() is *[]*struct{...}. +type structPointerSlice struct { + v reflect.Value +} + +func (p structPointerSlice) Len() int { return p.v.Len() } +func (p structPointerSlice) Index(i int) structPointer { return structPointer{p.v.Index(i)} } +func (p structPointerSlice) Append(q structPointer) { + p.v.Set(reflect.Append(p.v, q.v)) +} + +var ( + int32Type = reflect.TypeOf(int32(0)) + uint32Type = reflect.TypeOf(uint32(0)) + float32Type = reflect.TypeOf(float32(0)) + int64Type = reflect.TypeOf(int64(0)) + uint64Type = reflect.TypeOf(uint64(0)) + float64Type = reflect.TypeOf(float64(0)) +) + +// A word32 represents a field of type *int32, *uint32, *float32, or *enum. +// That is, v.Type() is *int32, *uint32, *float32, or *enum and v is assignable. +type word32 struct { + v reflect.Value +} + +// IsNil reports whether p is nil. +func word32_IsNil(p word32) bool { + return p.v.IsNil() +} + +// Set sets p to point at a newly allocated word with bits set to x. +func word32_Set(p word32, o *Buffer, x uint32) { + t := p.v.Type().Elem() + switch t { + case int32Type: + if len(o.int32s) == 0 { + o.int32s = make([]int32, uint32PoolSize) + } + o.int32s[0] = int32(x) + p.v.Set(reflect.ValueOf(&o.int32s[0])) + o.int32s = o.int32s[1:] + return + case uint32Type: + if len(o.uint32s) == 0 { + o.uint32s = make([]uint32, uint32PoolSize) + } + o.uint32s[0] = x + p.v.Set(reflect.ValueOf(&o.uint32s[0])) + o.uint32s = o.uint32s[1:] + return + case float32Type: + if len(o.float32s) == 0 { + o.float32s = make([]float32, uint32PoolSize) + } + o.float32s[0] = math.Float32frombits(x) + p.v.Set(reflect.ValueOf(&o.float32s[0])) + o.float32s = o.float32s[1:] + return + } + + // must be enum + p.v.Set(reflect.New(t)) + p.v.Elem().SetInt(int64(int32(x))) +} + +// Get gets the bits pointed at by p, as a uint32. +func word32_Get(p word32) uint32 { + elem := p.v.Elem() + switch elem.Kind() { + case reflect.Int32: + return uint32(elem.Int()) + case reflect.Uint32: + return uint32(elem.Uint()) + case reflect.Float32: + return math.Float32bits(float32(elem.Float())) + } + panic("unreachable") +} + +// Word32 returns a reference to a *int32, *uint32, *float32, or *enum field in the struct. +func structPointer_Word32(p structPointer, f field) word32 { + return word32{structPointer_field(p, f)} +} + +// A word32Val represents a field of type int32, uint32, float32, or enum. +// That is, v.Type() is int32, uint32, float32, or enum and v is assignable. +type word32Val struct { + v reflect.Value +} + +// Set sets *p to x. +func word32Val_Set(p word32Val, x uint32) { + switch p.v.Type() { + case int32Type: + p.v.SetInt(int64(x)) + return + case uint32Type: + p.v.SetUint(uint64(x)) + return + case float32Type: + p.v.SetFloat(float64(math.Float32frombits(x))) + return + } + + // must be enum + p.v.SetInt(int64(int32(x))) +} + +// Get gets the bits pointed at by p, as a uint32. +func word32Val_Get(p word32Val) uint32 { + elem := p.v + switch elem.Kind() { + case reflect.Int32: + return uint32(elem.Int()) + case reflect.Uint32: + return uint32(elem.Uint()) + case reflect.Float32: + return math.Float32bits(float32(elem.Float())) + } + panic("unreachable") +} + +// Word32Val returns a reference to a int32, uint32, float32, or enum field in the struct. +func structPointer_Word32Val(p structPointer, f field) word32Val { + return word32Val{structPointer_field(p, f)} +} + +// A word32Slice is a slice of 32-bit values. +// That is, v.Type() is []int32, []uint32, []float32, or []enum. +type word32Slice struct { + v reflect.Value +} + +func (p word32Slice) Append(x uint32) { + n, m := p.v.Len(), p.v.Cap() + if n < m { + p.v.SetLen(n + 1) + } else { + t := p.v.Type().Elem() + p.v.Set(reflect.Append(p.v, reflect.Zero(t))) + } + elem := p.v.Index(n) + switch elem.Kind() { + case reflect.Int32: + elem.SetInt(int64(int32(x))) + case reflect.Uint32: + elem.SetUint(uint64(x)) + case reflect.Float32: + elem.SetFloat(float64(math.Float32frombits(x))) + } +} + +func (p word32Slice) Len() int { + return p.v.Len() +} + +func (p word32Slice) Index(i int) uint32 { + elem := p.v.Index(i) + switch elem.Kind() { + case reflect.Int32: + return uint32(elem.Int()) + case reflect.Uint32: + return uint32(elem.Uint()) + case reflect.Float32: + return math.Float32bits(float32(elem.Float())) + } + panic("unreachable") +} + +// Word32Slice returns a reference to a []int32, []uint32, []float32, or []enum field in the struct. +func structPointer_Word32Slice(p structPointer, f field) word32Slice { + return word32Slice{structPointer_field(p, f)} +} + +// word64 is like word32 but for 64-bit values. +type word64 struct { + v reflect.Value +} + +func word64_Set(p word64, o *Buffer, x uint64) { + t := p.v.Type().Elem() + switch t { + case int64Type: + if len(o.int64s) == 0 { + o.int64s = make([]int64, uint64PoolSize) + } + o.int64s[0] = int64(x) + p.v.Set(reflect.ValueOf(&o.int64s[0])) + o.int64s = o.int64s[1:] + return + case uint64Type: + if len(o.uint64s) == 0 { + o.uint64s = make([]uint64, uint64PoolSize) + } + o.uint64s[0] = x + p.v.Set(reflect.ValueOf(&o.uint64s[0])) + o.uint64s = o.uint64s[1:] + return + case float64Type: + if len(o.float64s) == 0 { + o.float64s = make([]float64, uint64PoolSize) + } + o.float64s[0] = math.Float64frombits(x) + p.v.Set(reflect.ValueOf(&o.float64s[0])) + o.float64s = o.float64s[1:] + return + } + panic("unreachable") +} + +func word64_IsNil(p word64) bool { + return p.v.IsNil() +} + +func word64_Get(p word64) uint64 { + elem := p.v.Elem() + switch elem.Kind() { + case reflect.Int64: + return uint64(elem.Int()) + case reflect.Uint64: + return elem.Uint() + case reflect.Float64: + return math.Float64bits(elem.Float()) + } + panic("unreachable") +} + +func structPointer_Word64(p structPointer, f field) word64 { + return word64{structPointer_field(p, f)} +} + +// word64Val is like word32Val but for 64-bit values. +type word64Val struct { + v reflect.Value +} + +func word64Val_Set(p word64Val, o *Buffer, x uint64) { + switch p.v.Type() { + case int64Type: + p.v.SetInt(int64(x)) + return + case uint64Type: + p.v.SetUint(x) + return + case float64Type: + p.v.SetFloat(math.Float64frombits(x)) + return + } + panic("unreachable") +} + +func word64Val_Get(p word64Val) uint64 { + elem := p.v + switch elem.Kind() { + case reflect.Int64: + return uint64(elem.Int()) + case reflect.Uint64: + return elem.Uint() + case reflect.Float64: + return math.Float64bits(elem.Float()) + } + panic("unreachable") +} + +func structPointer_Word64Val(p structPointer, f field) word64Val { + return word64Val{structPointer_field(p, f)} +} + +type word64Slice struct { + v reflect.Value +} + +func (p word64Slice) Append(x uint64) { + n, m := p.v.Len(), p.v.Cap() + if n < m { + p.v.SetLen(n + 1) + } else { + t := p.v.Type().Elem() + p.v.Set(reflect.Append(p.v, reflect.Zero(t))) + } + elem := p.v.Index(n) + switch elem.Kind() { + case reflect.Int64: + elem.SetInt(int64(int64(x))) + case reflect.Uint64: + elem.SetUint(uint64(x)) + case reflect.Float64: + elem.SetFloat(float64(math.Float64frombits(x))) + } +} + +func (p word64Slice) Len() int { + return p.v.Len() +} + +func (p word64Slice) Index(i int) uint64 { + elem := p.v.Index(i) + switch elem.Kind() { + case reflect.Int64: + return uint64(elem.Int()) + case reflect.Uint64: + return uint64(elem.Uint()) + case reflect.Float64: + return math.Float64bits(float64(elem.Float())) + } + panic("unreachable") +} + +func structPointer_Word64Slice(p structPointer, f field) word64Slice { + return word64Slice{structPointer_field(p, f)} +} diff --git a/vendor/github.com/golang/protobuf/proto/pointer_unsafe.go b/vendor/github.com/golang/protobuf/proto/pointer_unsafe.go new file mode 100644 index 00000000..6b5567d4 --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/pointer_unsafe.go @@ -0,0 +1,270 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2012 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// 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 +// OWNER 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. + +// +build !appengine,!js + +// This file contains the implementation of the proto field accesses using package unsafe. + +package proto + +import ( + "reflect" + "unsafe" +) + +// NOTE: These type_Foo functions would more idiomatically be methods, +// but Go does not allow methods on pointer types, and we must preserve +// some pointer type for the garbage collector. We use these +// funcs with clunky names as our poor approximation to methods. +// +// An alternative would be +// type structPointer struct { p unsafe.Pointer } +// but that does not registerize as well. + +// A structPointer is a pointer to a struct. +type structPointer unsafe.Pointer + +// toStructPointer returns a structPointer equivalent to the given reflect value. +func toStructPointer(v reflect.Value) structPointer { + return structPointer(unsafe.Pointer(v.Pointer())) +} + +// IsNil reports whether p is nil. +func structPointer_IsNil(p structPointer) bool { + return p == nil +} + +// Interface returns the struct pointer, assumed to have element type t, +// as an interface value. +func structPointer_Interface(p structPointer, t reflect.Type) interface{} { + return reflect.NewAt(t, unsafe.Pointer(p)).Interface() +} + +// A field identifies a field in a struct, accessible from a structPointer. +// In this implementation, a field is identified by its byte offset from the start of the struct. +type field uintptr + +// toField returns a field equivalent to the given reflect field. +func toField(f *reflect.StructField) field { + return field(f.Offset) +} + +// invalidField is an invalid field identifier. +const invalidField = ^field(0) + +// IsValid reports whether the field identifier is valid. +func (f field) IsValid() bool { + return f != ^field(0) +} + +// Bytes returns the address of a []byte field in the struct. +func structPointer_Bytes(p structPointer, f field) *[]byte { + return (*[]byte)(unsafe.Pointer(uintptr(p) + uintptr(f))) +} + +// BytesSlice returns the address of a [][]byte field in the struct. +func structPointer_BytesSlice(p structPointer, f field) *[][]byte { + return (*[][]byte)(unsafe.Pointer(uintptr(p) + uintptr(f))) +} + +// Bool returns the address of a *bool field in the struct. +func structPointer_Bool(p structPointer, f field) **bool { + return (**bool)(unsafe.Pointer(uintptr(p) + uintptr(f))) +} + +// BoolVal returns the address of a bool field in the struct. +func structPointer_BoolVal(p structPointer, f field) *bool { + return (*bool)(unsafe.Pointer(uintptr(p) + uintptr(f))) +} + +// BoolSlice returns the address of a []bool field in the struct. +func structPointer_BoolSlice(p structPointer, f field) *[]bool { + return (*[]bool)(unsafe.Pointer(uintptr(p) + uintptr(f))) +} + +// String returns the address of a *string field in the struct. +func structPointer_String(p structPointer, f field) **string { + return (**string)(unsafe.Pointer(uintptr(p) + uintptr(f))) +} + +// StringVal returns the address of a string field in the struct. +func structPointer_StringVal(p structPointer, f field) *string { + return (*string)(unsafe.Pointer(uintptr(p) + uintptr(f))) +} + +// StringSlice returns the address of a []string field in the struct. +func structPointer_StringSlice(p structPointer, f field) *[]string { + return (*[]string)(unsafe.Pointer(uintptr(p) + uintptr(f))) +} + +// ExtMap returns the address of an extension map field in the struct. +func structPointer_Extensions(p structPointer, f field) *XXX_InternalExtensions { + return (*XXX_InternalExtensions)(unsafe.Pointer(uintptr(p) + uintptr(f))) +} + +func structPointer_ExtMap(p structPointer, f field) *map[int32]Extension { + return (*map[int32]Extension)(unsafe.Pointer(uintptr(p) + uintptr(f))) +} + +// NewAt returns the reflect.Value for a pointer to a field in the struct. +func structPointer_NewAt(p structPointer, f field, typ reflect.Type) reflect.Value { + return reflect.NewAt(typ, unsafe.Pointer(uintptr(p)+uintptr(f))) +} + +// SetStructPointer writes a *struct field in the struct. +func structPointer_SetStructPointer(p structPointer, f field, q structPointer) { + *(*structPointer)(unsafe.Pointer(uintptr(p) + uintptr(f))) = q +} + +// GetStructPointer reads a *struct field in the struct. +func structPointer_GetStructPointer(p structPointer, f field) structPointer { + return *(*structPointer)(unsafe.Pointer(uintptr(p) + uintptr(f))) +} + +// StructPointerSlice the address of a []*struct field in the struct. +func structPointer_StructPointerSlice(p structPointer, f field) *structPointerSlice { + return (*structPointerSlice)(unsafe.Pointer(uintptr(p) + uintptr(f))) +} + +// A structPointerSlice represents a slice of pointers to structs (themselves submessages or groups). +type structPointerSlice []structPointer + +func (v *structPointerSlice) Len() int { return len(*v) } +func (v *structPointerSlice) Index(i int) structPointer { return (*v)[i] } +func (v *structPointerSlice) Append(p structPointer) { *v = append(*v, p) } + +// A word32 is the address of a "pointer to 32-bit value" field. +type word32 **uint32 + +// IsNil reports whether *v is nil. +func word32_IsNil(p word32) bool { + return *p == nil +} + +// Set sets *v to point at a newly allocated word set to x. +func word32_Set(p word32, o *Buffer, x uint32) { + if len(o.uint32s) == 0 { + o.uint32s = make([]uint32, uint32PoolSize) + } + o.uint32s[0] = x + *p = &o.uint32s[0] + o.uint32s = o.uint32s[1:] +} + +// Get gets the value pointed at by *v. +func word32_Get(p word32) uint32 { + return **p +} + +// Word32 returns the address of a *int32, *uint32, *float32, or *enum field in the struct. +func structPointer_Word32(p structPointer, f field) word32 { + return word32((**uint32)(unsafe.Pointer(uintptr(p) + uintptr(f)))) +} + +// A word32Val is the address of a 32-bit value field. +type word32Val *uint32 + +// Set sets *p to x. +func word32Val_Set(p word32Val, x uint32) { + *p = x +} + +// Get gets the value pointed at by p. +func word32Val_Get(p word32Val) uint32 { + return *p +} + +// Word32Val returns the address of a *int32, *uint32, *float32, or *enum field in the struct. +func structPointer_Word32Val(p structPointer, f field) word32Val { + return word32Val((*uint32)(unsafe.Pointer(uintptr(p) + uintptr(f)))) +} + +// A word32Slice is a slice of 32-bit values. +type word32Slice []uint32 + +func (v *word32Slice) Append(x uint32) { *v = append(*v, x) } +func (v *word32Slice) Len() int { return len(*v) } +func (v *word32Slice) Index(i int) uint32 { return (*v)[i] } + +// Word32Slice returns the address of a []int32, []uint32, []float32, or []enum field in the struct. +func structPointer_Word32Slice(p structPointer, f field) *word32Slice { + return (*word32Slice)(unsafe.Pointer(uintptr(p) + uintptr(f))) +} + +// word64 is like word32 but for 64-bit values. +type word64 **uint64 + +func word64_Set(p word64, o *Buffer, x uint64) { + if len(o.uint64s) == 0 { + o.uint64s = make([]uint64, uint64PoolSize) + } + o.uint64s[0] = x + *p = &o.uint64s[0] + o.uint64s = o.uint64s[1:] +} + +func word64_IsNil(p word64) bool { + return *p == nil +} + +func word64_Get(p word64) uint64 { + return **p +} + +func structPointer_Word64(p structPointer, f field) word64 { + return word64((**uint64)(unsafe.Pointer(uintptr(p) + uintptr(f)))) +} + +// word64Val is like word32Val but for 64-bit values. +type word64Val *uint64 + +func word64Val_Set(p word64Val, o *Buffer, x uint64) { + *p = x +} + +func word64Val_Get(p word64Val) uint64 { + return *p +} + +func structPointer_Word64Val(p structPointer, f field) word64Val { + return word64Val((*uint64)(unsafe.Pointer(uintptr(p) + uintptr(f)))) +} + +// word64Slice is like word32Slice but for 64-bit values. +type word64Slice []uint64 + +func (v *word64Slice) Append(x uint64) { *v = append(*v, x) } +func (v *word64Slice) Len() int { return len(*v) } +func (v *word64Slice) Index(i int) uint64 { return (*v)[i] } + +func structPointer_Word64Slice(p structPointer, f field) *word64Slice { + return (*word64Slice)(unsafe.Pointer(uintptr(p) + uintptr(f))) +} diff --git a/vendor/github.com/golang/protobuf/proto/properties.go b/vendor/github.com/golang/protobuf/proto/properties.go new file mode 100644 index 00000000..ec2289c0 --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/properties.go @@ -0,0 +1,872 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2010 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// 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 +// OWNER 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. + +package proto + +/* + * Routines for encoding data into the wire format for protocol buffers. + */ + +import ( + "fmt" + "log" + "os" + "reflect" + "sort" + "strconv" + "strings" + "sync" +) + +const debug bool = false + +// Constants that identify the encoding of a value on the wire. +const ( + WireVarint = 0 + WireFixed64 = 1 + WireBytes = 2 + WireStartGroup = 3 + WireEndGroup = 4 + WireFixed32 = 5 +) + +const startSize = 10 // initial slice/string sizes + +// Encoders are defined in encode.go +// An encoder outputs the full representation of a field, including its +// tag and encoder type. +type encoder func(p *Buffer, prop *Properties, base structPointer) error + +// A valueEncoder encodes a single integer in a particular encoding. +type valueEncoder func(o *Buffer, x uint64) error + +// Sizers are defined in encode.go +// A sizer returns the encoded size of a field, including its tag and encoder +// type. +type sizer func(prop *Properties, base structPointer) int + +// A valueSizer returns the encoded size of a single integer in a particular +// encoding. +type valueSizer func(x uint64) int + +// Decoders are defined in decode.go +// A decoder creates a value from its wire representation. +// Unrecognized subelements are saved in unrec. +type decoder func(p *Buffer, prop *Properties, base structPointer) error + +// A valueDecoder decodes a single integer in a particular encoding. +type valueDecoder func(o *Buffer) (x uint64, err error) + +// A oneofMarshaler does the marshaling for all oneof fields in a message. +type oneofMarshaler func(Message, *Buffer) error + +// A oneofUnmarshaler does the unmarshaling for a oneof field in a message. +type oneofUnmarshaler func(Message, int, int, *Buffer) (bool, error) + +// A oneofSizer does the sizing for all oneof fields in a message. +type oneofSizer func(Message) int + +// tagMap is an optimization over map[int]int for typical protocol buffer +// use-cases. Encoded protocol buffers are often in tag order with small tag +// numbers. +type tagMap struct { + fastTags []int + slowTags map[int]int +} + +// tagMapFastLimit is the upper bound on the tag number that will be stored in +// the tagMap slice rather than its map. +const tagMapFastLimit = 1024 + +func (p *tagMap) get(t int) (int, bool) { + if t > 0 && t < tagMapFastLimit { + if t >= len(p.fastTags) { + return 0, false + } + fi := p.fastTags[t] + return fi, fi >= 0 + } + fi, ok := p.slowTags[t] + return fi, ok +} + +func (p *tagMap) put(t int, fi int) { + if t > 0 && t < tagMapFastLimit { + for len(p.fastTags) < t+1 { + p.fastTags = append(p.fastTags, -1) + } + p.fastTags[t] = fi + return + } + if p.slowTags == nil { + p.slowTags = make(map[int]int) + } + p.slowTags[t] = fi +} + +// StructProperties represents properties for all the fields of a struct. +// decoderTags and decoderOrigNames should only be used by the decoder. +type StructProperties struct { + Prop []*Properties // properties for each field + reqCount int // required count + decoderTags tagMap // map from proto tag to struct field number + decoderOrigNames map[string]int // map from original name to struct field number + order []int // list of struct field numbers in tag order + unrecField field // field id of the XXX_unrecognized []byte field + extendable bool // is this an extendable proto + + oneofMarshaler oneofMarshaler + oneofUnmarshaler oneofUnmarshaler + oneofSizer oneofSizer + stype reflect.Type + + // OneofTypes contains information about the oneof fields in this message. + // It is keyed by the original name of a field. + OneofTypes map[string]*OneofProperties +} + +// OneofProperties represents information about a specific field in a oneof. +type OneofProperties struct { + Type reflect.Type // pointer to generated struct type for this oneof field + Field int // struct field number of the containing oneof in the message + Prop *Properties +} + +// Implement the sorting interface so we can sort the fields in tag order, as recommended by the spec. +// See encode.go, (*Buffer).enc_struct. + +func (sp *StructProperties) Len() int { return len(sp.order) } +func (sp *StructProperties) Less(i, j int) bool { + return sp.Prop[sp.order[i]].Tag < sp.Prop[sp.order[j]].Tag +} +func (sp *StructProperties) Swap(i, j int) { sp.order[i], sp.order[j] = sp.order[j], sp.order[i] } + +// Properties represents the protocol-specific behavior of a single struct field. +type Properties struct { + Name string // name of the field, for error messages + OrigName string // original name before protocol compiler (always set) + JSONName string // name to use for JSON; determined by protoc + Wire string + WireType int + Tag int + Required bool + Optional bool + Repeated bool + Packed bool // relevant for repeated primitives only + Enum string // set for enum types only + proto3 bool // whether this is known to be a proto3 field; set for []byte only + oneof bool // whether this is a oneof field + + Default string // default value + HasDefault bool // whether an explicit default was provided + def_uint64 uint64 + + enc encoder + valEnc valueEncoder // set for bool and numeric types only + field field + tagcode []byte // encoding of EncodeVarint((Tag<<3)|WireType) + tagbuf [8]byte + stype reflect.Type // set for struct types only + sprop *StructProperties // set for struct types only + isMarshaler bool + isUnmarshaler bool + + mtype reflect.Type // set for map types only + mkeyprop *Properties // set for map types only + mvalprop *Properties // set for map types only + + size sizer + valSize valueSizer // set for bool and numeric types only + + dec decoder + valDec valueDecoder // set for bool and numeric types only + + // If this is a packable field, this will be the decoder for the packed version of the field. + packedDec decoder +} + +// String formats the properties in the protobuf struct field tag style. +func (p *Properties) String() string { + s := p.Wire + s = "," + s += strconv.Itoa(p.Tag) + if p.Required { + s += ",req" + } + if p.Optional { + s += ",opt" + } + if p.Repeated { + s += ",rep" + } + if p.Packed { + s += ",packed" + } + s += ",name=" + p.OrigName + if p.JSONName != p.OrigName { + s += ",json=" + p.JSONName + } + if p.proto3 { + s += ",proto3" + } + if p.oneof { + s += ",oneof" + } + if len(p.Enum) > 0 { + s += ",enum=" + p.Enum + } + if p.HasDefault { + s += ",def=" + p.Default + } + return s +} + +// Parse populates p by parsing a string in the protobuf struct field tag style. +func (p *Properties) Parse(s string) { + // "bytes,49,opt,name=foo,def=hello!" + fields := strings.Split(s, ",") // breaks def=, but handled below. + if len(fields) < 2 { + fmt.Fprintf(os.Stderr, "proto: tag has too few fields: %q\n", s) + return + } + + p.Wire = fields[0] + switch p.Wire { + case "varint": + p.WireType = WireVarint + p.valEnc = (*Buffer).EncodeVarint + p.valDec = (*Buffer).DecodeVarint + p.valSize = sizeVarint + case "fixed32": + p.WireType = WireFixed32 + p.valEnc = (*Buffer).EncodeFixed32 + p.valDec = (*Buffer).DecodeFixed32 + p.valSize = sizeFixed32 + case "fixed64": + p.WireType = WireFixed64 + p.valEnc = (*Buffer).EncodeFixed64 + p.valDec = (*Buffer).DecodeFixed64 + p.valSize = sizeFixed64 + case "zigzag32": + p.WireType = WireVarint + p.valEnc = (*Buffer).EncodeZigzag32 + p.valDec = (*Buffer).DecodeZigzag32 + p.valSize = sizeZigzag32 + case "zigzag64": + p.WireType = WireVarint + p.valEnc = (*Buffer).EncodeZigzag64 + p.valDec = (*Buffer).DecodeZigzag64 + p.valSize = sizeZigzag64 + case "bytes", "group": + p.WireType = WireBytes + // no numeric converter for non-numeric types + default: + fmt.Fprintf(os.Stderr, "proto: tag has unknown wire type: %q\n", s) + return + } + + var err error + p.Tag, err = strconv.Atoi(fields[1]) + if err != nil { + return + } + + for i := 2; i < len(fields); i++ { + f := fields[i] + switch { + case f == "req": + p.Required = true + case f == "opt": + p.Optional = true + case f == "rep": + p.Repeated = true + case f == "packed": + p.Packed = true + case strings.HasPrefix(f, "name="): + p.OrigName = f[5:] + case strings.HasPrefix(f, "json="): + p.JSONName = f[5:] + case strings.HasPrefix(f, "enum="): + p.Enum = f[5:] + case f == "proto3": + p.proto3 = true + case f == "oneof": + p.oneof = true + case strings.HasPrefix(f, "def="): + p.HasDefault = true + p.Default = f[4:] // rest of string + if i+1 < len(fields) { + // Commas aren't escaped, and def is always last. + p.Default += "," + strings.Join(fields[i+1:], ",") + break + } + } + } +} + +func logNoSliceEnc(t1, t2 reflect.Type) { + fmt.Fprintf(os.Stderr, "proto: no slice oenc for %T = []%T\n", t1, t2) +} + +var protoMessageType = reflect.TypeOf((*Message)(nil)).Elem() + +// Initialize the fields for encoding and decoding. +func (p *Properties) setEncAndDec(typ reflect.Type, f *reflect.StructField, lockGetProp bool) { + p.enc = nil + p.dec = nil + p.size = nil + + switch t1 := typ; t1.Kind() { + default: + fmt.Fprintf(os.Stderr, "proto: no coders for %v\n", t1) + + // proto3 scalar types + + case reflect.Bool: + p.enc = (*Buffer).enc_proto3_bool + p.dec = (*Buffer).dec_proto3_bool + p.size = size_proto3_bool + case reflect.Int32: + p.enc = (*Buffer).enc_proto3_int32 + p.dec = (*Buffer).dec_proto3_int32 + p.size = size_proto3_int32 + case reflect.Uint32: + p.enc = (*Buffer).enc_proto3_uint32 + p.dec = (*Buffer).dec_proto3_int32 // can reuse + p.size = size_proto3_uint32 + case reflect.Int64, reflect.Uint64: + p.enc = (*Buffer).enc_proto3_int64 + p.dec = (*Buffer).dec_proto3_int64 + p.size = size_proto3_int64 + case reflect.Float32: + p.enc = (*Buffer).enc_proto3_uint32 // can just treat them as bits + p.dec = (*Buffer).dec_proto3_int32 + p.size = size_proto3_uint32 + case reflect.Float64: + p.enc = (*Buffer).enc_proto3_int64 // can just treat them as bits + p.dec = (*Buffer).dec_proto3_int64 + p.size = size_proto3_int64 + case reflect.String: + p.enc = (*Buffer).enc_proto3_string + p.dec = (*Buffer).dec_proto3_string + p.size = size_proto3_string + + case reflect.Ptr: + switch t2 := t1.Elem(); t2.Kind() { + default: + fmt.Fprintf(os.Stderr, "proto: no encoder function for %v -> %v\n", t1, t2) + break + case reflect.Bool: + p.enc = (*Buffer).enc_bool + p.dec = (*Buffer).dec_bool + p.size = size_bool + case reflect.Int32: + p.enc = (*Buffer).enc_int32 + p.dec = (*Buffer).dec_int32 + p.size = size_int32 + case reflect.Uint32: + p.enc = (*Buffer).enc_uint32 + p.dec = (*Buffer).dec_int32 // can reuse + p.size = size_uint32 + case reflect.Int64, reflect.Uint64: + p.enc = (*Buffer).enc_int64 + p.dec = (*Buffer).dec_int64 + p.size = size_int64 + case reflect.Float32: + p.enc = (*Buffer).enc_uint32 // can just treat them as bits + p.dec = (*Buffer).dec_int32 + p.size = size_uint32 + case reflect.Float64: + p.enc = (*Buffer).enc_int64 // can just treat them as bits + p.dec = (*Buffer).dec_int64 + p.size = size_int64 + case reflect.String: + p.enc = (*Buffer).enc_string + p.dec = (*Buffer).dec_string + p.size = size_string + case reflect.Struct: + p.stype = t1.Elem() + p.isMarshaler = isMarshaler(t1) + p.isUnmarshaler = isUnmarshaler(t1) + if p.Wire == "bytes" { + p.enc = (*Buffer).enc_struct_message + p.dec = (*Buffer).dec_struct_message + p.size = size_struct_message + } else { + p.enc = (*Buffer).enc_struct_group + p.dec = (*Buffer).dec_struct_group + p.size = size_struct_group + } + } + + case reflect.Slice: + switch t2 := t1.Elem(); t2.Kind() { + default: + logNoSliceEnc(t1, t2) + break + case reflect.Bool: + if p.Packed { + p.enc = (*Buffer).enc_slice_packed_bool + p.size = size_slice_packed_bool + } else { + p.enc = (*Buffer).enc_slice_bool + p.size = size_slice_bool + } + p.dec = (*Buffer).dec_slice_bool + p.packedDec = (*Buffer).dec_slice_packed_bool + case reflect.Int32: + if p.Packed { + p.enc = (*Buffer).enc_slice_packed_int32 + p.size = size_slice_packed_int32 + } else { + p.enc = (*Buffer).enc_slice_int32 + p.size = size_slice_int32 + } + p.dec = (*Buffer).dec_slice_int32 + p.packedDec = (*Buffer).dec_slice_packed_int32 + case reflect.Uint32: + if p.Packed { + p.enc = (*Buffer).enc_slice_packed_uint32 + p.size = size_slice_packed_uint32 + } else { + p.enc = (*Buffer).enc_slice_uint32 + p.size = size_slice_uint32 + } + p.dec = (*Buffer).dec_slice_int32 + p.packedDec = (*Buffer).dec_slice_packed_int32 + case reflect.Int64, reflect.Uint64: + if p.Packed { + p.enc = (*Buffer).enc_slice_packed_int64 + p.size = size_slice_packed_int64 + } else { + p.enc = (*Buffer).enc_slice_int64 + p.size = size_slice_int64 + } + p.dec = (*Buffer).dec_slice_int64 + p.packedDec = (*Buffer).dec_slice_packed_int64 + case reflect.Uint8: + p.dec = (*Buffer).dec_slice_byte + if p.proto3 { + p.enc = (*Buffer).enc_proto3_slice_byte + p.size = size_proto3_slice_byte + } else { + p.enc = (*Buffer).enc_slice_byte + p.size = size_slice_byte + } + case reflect.Float32, reflect.Float64: + switch t2.Bits() { + case 32: + // can just treat them as bits + if p.Packed { + p.enc = (*Buffer).enc_slice_packed_uint32 + p.size = size_slice_packed_uint32 + } else { + p.enc = (*Buffer).enc_slice_uint32 + p.size = size_slice_uint32 + } + p.dec = (*Buffer).dec_slice_int32 + p.packedDec = (*Buffer).dec_slice_packed_int32 + case 64: + // can just treat them as bits + if p.Packed { + p.enc = (*Buffer).enc_slice_packed_int64 + p.size = size_slice_packed_int64 + } else { + p.enc = (*Buffer).enc_slice_int64 + p.size = size_slice_int64 + } + p.dec = (*Buffer).dec_slice_int64 + p.packedDec = (*Buffer).dec_slice_packed_int64 + default: + logNoSliceEnc(t1, t2) + break + } + case reflect.String: + p.enc = (*Buffer).enc_slice_string + p.dec = (*Buffer).dec_slice_string + p.size = size_slice_string + case reflect.Ptr: + switch t3 := t2.Elem(); t3.Kind() { + default: + fmt.Fprintf(os.Stderr, "proto: no ptr oenc for %T -> %T -> %T\n", t1, t2, t3) + break + case reflect.Struct: + p.stype = t2.Elem() + p.isMarshaler = isMarshaler(t2) + p.isUnmarshaler = isUnmarshaler(t2) + if p.Wire == "bytes" { + p.enc = (*Buffer).enc_slice_struct_message + p.dec = (*Buffer).dec_slice_struct_message + p.size = size_slice_struct_message + } else { + p.enc = (*Buffer).enc_slice_struct_group + p.dec = (*Buffer).dec_slice_struct_group + p.size = size_slice_struct_group + } + } + case reflect.Slice: + switch t2.Elem().Kind() { + default: + fmt.Fprintf(os.Stderr, "proto: no slice elem oenc for %T -> %T -> %T\n", t1, t2, t2.Elem()) + break + case reflect.Uint8: + p.enc = (*Buffer).enc_slice_slice_byte + p.dec = (*Buffer).dec_slice_slice_byte + p.size = size_slice_slice_byte + } + } + + case reflect.Map: + p.enc = (*Buffer).enc_new_map + p.dec = (*Buffer).dec_new_map + p.size = size_new_map + + p.mtype = t1 + p.mkeyprop = &Properties{} + p.mkeyprop.init(reflect.PtrTo(p.mtype.Key()), "Key", f.Tag.Get("protobuf_key"), nil, lockGetProp) + p.mvalprop = &Properties{} + vtype := p.mtype.Elem() + if vtype.Kind() != reflect.Ptr && vtype.Kind() != reflect.Slice { + // The value type is not a message (*T) or bytes ([]byte), + // so we need encoders for the pointer to this type. + vtype = reflect.PtrTo(vtype) + } + p.mvalprop.init(vtype, "Value", f.Tag.Get("protobuf_val"), nil, lockGetProp) + } + + // precalculate tag code + wire := p.WireType + if p.Packed { + wire = WireBytes + } + x := uint32(p.Tag)<<3 | uint32(wire) + i := 0 + for i = 0; x > 127; i++ { + p.tagbuf[i] = 0x80 | uint8(x&0x7F) + x >>= 7 + } + p.tagbuf[i] = uint8(x) + p.tagcode = p.tagbuf[0 : i+1] + + if p.stype != nil { + if lockGetProp { + p.sprop = GetProperties(p.stype) + } else { + p.sprop = getPropertiesLocked(p.stype) + } + } +} + +var ( + marshalerType = reflect.TypeOf((*Marshaler)(nil)).Elem() + unmarshalerType = reflect.TypeOf((*Unmarshaler)(nil)).Elem() +) + +// isMarshaler reports whether type t implements Marshaler. +func isMarshaler(t reflect.Type) bool { + // We're checking for (likely) pointer-receiver methods + // so if t is not a pointer, something is very wrong. + // The calls above only invoke isMarshaler on pointer types. + if t.Kind() != reflect.Ptr { + panic("proto: misuse of isMarshaler") + } + return t.Implements(marshalerType) +} + +// isUnmarshaler reports whether type t implements Unmarshaler. +func isUnmarshaler(t reflect.Type) bool { + // We're checking for (likely) pointer-receiver methods + // so if t is not a pointer, something is very wrong. + // The calls above only invoke isUnmarshaler on pointer types. + if t.Kind() != reflect.Ptr { + panic("proto: misuse of isUnmarshaler") + } + return t.Implements(unmarshalerType) +} + +// Init populates the properties from a protocol buffer struct tag. +func (p *Properties) Init(typ reflect.Type, name, tag string, f *reflect.StructField) { + p.init(typ, name, tag, f, true) +} + +func (p *Properties) init(typ reflect.Type, name, tag string, f *reflect.StructField, lockGetProp bool) { + // "bytes,49,opt,def=hello!" + p.Name = name + p.OrigName = name + if f != nil { + p.field = toField(f) + } + if tag == "" { + return + } + p.Parse(tag) + p.setEncAndDec(typ, f, lockGetProp) +} + +var ( + propertiesMu sync.RWMutex + propertiesMap = make(map[reflect.Type]*StructProperties) +) + +// GetProperties returns the list of properties for the type represented by t. +// t must represent a generated struct type of a protocol message. +func GetProperties(t reflect.Type) *StructProperties { + if t.Kind() != reflect.Struct { + panic("proto: type must have kind struct") + } + + // Most calls to GetProperties in a long-running program will be + // retrieving details for types we have seen before. + propertiesMu.RLock() + sprop, ok := propertiesMap[t] + propertiesMu.RUnlock() + if ok { + if collectStats { + stats.Chit++ + } + return sprop + } + + propertiesMu.Lock() + sprop = getPropertiesLocked(t) + propertiesMu.Unlock() + return sprop +} + +// getPropertiesLocked requires that propertiesMu is held. +func getPropertiesLocked(t reflect.Type) *StructProperties { + if prop, ok := propertiesMap[t]; ok { + if collectStats { + stats.Chit++ + } + return prop + } + if collectStats { + stats.Cmiss++ + } + + prop := new(StructProperties) + // in case of recursive protos, fill this in now. + propertiesMap[t] = prop + + // build properties + prop.extendable = reflect.PtrTo(t).Implements(extendableProtoType) || + reflect.PtrTo(t).Implements(extendableProtoV1Type) + prop.unrecField = invalidField + prop.Prop = make([]*Properties, t.NumField()) + prop.order = make([]int, t.NumField()) + + for i := 0; i < t.NumField(); i++ { + f := t.Field(i) + p := new(Properties) + name := f.Name + p.init(f.Type, name, f.Tag.Get("protobuf"), &f, false) + + if f.Name == "XXX_InternalExtensions" { // special case + p.enc = (*Buffer).enc_exts + p.dec = nil // not needed + p.size = size_exts + } else if f.Name == "XXX_extensions" { // special case + p.enc = (*Buffer).enc_map + p.dec = nil // not needed + p.size = size_map + } else if f.Name == "XXX_unrecognized" { // special case + prop.unrecField = toField(&f) + } + oneof := f.Tag.Get("protobuf_oneof") // special case + if oneof != "" { + // Oneof fields don't use the traditional protobuf tag. + p.OrigName = oneof + } + prop.Prop[i] = p + prop.order[i] = i + if debug { + print(i, " ", f.Name, " ", t.String(), " ") + if p.Tag > 0 { + print(p.String()) + } + print("\n") + } + if p.enc == nil && !strings.HasPrefix(f.Name, "XXX_") && oneof == "" { + fmt.Fprintln(os.Stderr, "proto: no encoder for", f.Name, f.Type.String(), "[GetProperties]") + } + } + + // Re-order prop.order. + sort.Sort(prop) + + type oneofMessage interface { + XXX_OneofFuncs() (func(Message, *Buffer) error, func(Message, int, int, *Buffer) (bool, error), func(Message) int, []interface{}) + } + if om, ok := reflect.Zero(reflect.PtrTo(t)).Interface().(oneofMessage); ok { + var oots []interface{} + prop.oneofMarshaler, prop.oneofUnmarshaler, prop.oneofSizer, oots = om.XXX_OneofFuncs() + prop.stype = t + + // Interpret oneof metadata. + prop.OneofTypes = make(map[string]*OneofProperties) + for _, oot := range oots { + oop := &OneofProperties{ + Type: reflect.ValueOf(oot).Type(), // *T + Prop: new(Properties), + } + sft := oop.Type.Elem().Field(0) + oop.Prop.Name = sft.Name + oop.Prop.Parse(sft.Tag.Get("protobuf")) + // There will be exactly one interface field that + // this new value is assignable to. + for i := 0; i < t.NumField(); i++ { + f := t.Field(i) + if f.Type.Kind() != reflect.Interface { + continue + } + if !oop.Type.AssignableTo(f.Type) { + continue + } + oop.Field = i + break + } + prop.OneofTypes[oop.Prop.OrigName] = oop + } + } + + // build required counts + // build tags + reqCount := 0 + prop.decoderOrigNames = make(map[string]int) + for i, p := range prop.Prop { + if strings.HasPrefix(p.Name, "XXX_") { + // Internal fields should not appear in tags/origNames maps. + // They are handled specially when encoding and decoding. + continue + } + if p.Required { + reqCount++ + } + prop.decoderTags.put(p.Tag, i) + prop.decoderOrigNames[p.OrigName] = i + } + prop.reqCount = reqCount + + return prop +} + +// Return the Properties object for the x[0]'th field of the structure. +func propByIndex(t reflect.Type, x []int) *Properties { + if len(x) != 1 { + fmt.Fprintf(os.Stderr, "proto: field index dimension %d (not 1) for type %s\n", len(x), t) + return nil + } + prop := GetProperties(t) + return prop.Prop[x[0]] +} + +// Get the address and type of a pointer to a struct from an interface. +func getbase(pb Message) (t reflect.Type, b structPointer, err error) { + if pb == nil { + err = ErrNil + return + } + // get the reflect type of the pointer to the struct. + t = reflect.TypeOf(pb) + // get the address of the struct. + value := reflect.ValueOf(pb) + b = toStructPointer(value) + return +} + +// A global registry of enum types. +// The generated code will register the generated maps by calling RegisterEnum. + +var enumValueMaps = make(map[string]map[string]int32) + +// RegisterEnum is called from the generated code to install the enum descriptor +// maps into the global table to aid parsing text format protocol buffers. +func RegisterEnum(typeName string, unusedNameMap map[int32]string, valueMap map[string]int32) { + if _, ok := enumValueMaps[typeName]; ok { + panic("proto: duplicate enum registered: " + typeName) + } + enumValueMaps[typeName] = valueMap +} + +// EnumValueMap returns the mapping from names to integers of the +// enum type enumType, or a nil if not found. +func EnumValueMap(enumType string) map[string]int32 { + return enumValueMaps[enumType] +} + +// A registry of all linked message types. +// The string is a fully-qualified proto name ("pkg.Message"). +var ( + protoTypes = make(map[string]reflect.Type) + revProtoTypes = make(map[reflect.Type]string) +) + +// RegisterType is called from generated code and maps from the fully qualified +// proto name to the type (pointer to struct) of the protocol buffer. +func RegisterType(x Message, name string) { + if _, ok := protoTypes[name]; ok { + // TODO: Some day, make this a panic. + log.Printf("proto: duplicate proto type registered: %s", name) + return + } + t := reflect.TypeOf(x) + protoTypes[name] = t + revProtoTypes[t] = name +} + +// MessageName returns the fully-qualified proto name for the given message type. +func MessageName(x Message) string { + type xname interface { + XXX_MessageName() string + } + if m, ok := x.(xname); ok { + return m.XXX_MessageName() + } + return revProtoTypes[reflect.TypeOf(x)] +} + +// MessageType returns the message type (pointer to struct) for a named message. +func MessageType(name string) reflect.Type { return protoTypes[name] } + +// A registry of all linked proto files. +var ( + protoFiles = make(map[string][]byte) // file name => fileDescriptor +) + +// RegisterFile is called from generated code and maps from the +// full file name of a .proto file to its compressed FileDescriptorProto. +func RegisterFile(filename string, fileDescriptor []byte) { + protoFiles[filename] = fileDescriptor +} + +// FileDescriptor returns the compressed FileDescriptorProto for a .proto file. +func FileDescriptor(filename string) []byte { return protoFiles[filename] } diff --git a/vendor/github.com/golang/protobuf/proto/proto3_proto/proto3.pb.go b/vendor/github.com/golang/protobuf/proto/proto3_proto/proto3.pb.go new file mode 100644 index 00000000..cc4d0489 --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/proto3_proto/proto3.pb.go @@ -0,0 +1,347 @@ +// Code generated by protoc-gen-go. +// source: proto3_proto/proto3.proto +// DO NOT EDIT! + +/* +Package proto3_proto is a generated protocol buffer package. + +It is generated from these files: + proto3_proto/proto3.proto + +It has these top-level messages: + Message + Nested + MessageWithMap + IntMap + IntMaps +*/ +package proto3_proto + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" +import google_protobuf "github.com/golang/protobuf/ptypes/any" +import testdata "github.com/golang/protobuf/proto/testdata" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package + +type Message_Humour int32 + +const ( + Message_UNKNOWN Message_Humour = 0 + Message_PUNS Message_Humour = 1 + Message_SLAPSTICK Message_Humour = 2 + Message_BILL_BAILEY Message_Humour = 3 +) + +var Message_Humour_name = map[int32]string{ + 0: "UNKNOWN", + 1: "PUNS", + 2: "SLAPSTICK", + 3: "BILL_BAILEY", +} +var Message_Humour_value = map[string]int32{ + "UNKNOWN": 0, + "PUNS": 1, + "SLAPSTICK": 2, + "BILL_BAILEY": 3, +} + +func (x Message_Humour) String() string { + return proto.EnumName(Message_Humour_name, int32(x)) +} +func (Message_Humour) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{0, 0} } + +type Message struct { + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + Hilarity Message_Humour `protobuf:"varint,2,opt,name=hilarity,enum=proto3_proto.Message_Humour" json:"hilarity,omitempty"` + HeightInCm uint32 `protobuf:"varint,3,opt,name=height_in_cm,json=heightInCm" json:"height_in_cm,omitempty"` + Data []byte `protobuf:"bytes,4,opt,name=data,proto3" json:"data,omitempty"` + ResultCount int64 `protobuf:"varint,7,opt,name=result_count,json=resultCount" json:"result_count,omitempty"` + TrueScotsman bool `protobuf:"varint,8,opt,name=true_scotsman,json=trueScotsman" json:"true_scotsman,omitempty"` + Score float32 `protobuf:"fixed32,9,opt,name=score" json:"score,omitempty"` + Key []uint64 `protobuf:"varint,5,rep,packed,name=key" json:"key,omitempty"` + ShortKey []int32 `protobuf:"varint,19,rep,packed,name=short_key,json=shortKey" json:"short_key,omitempty"` + Nested *Nested `protobuf:"bytes,6,opt,name=nested" json:"nested,omitempty"` + RFunny []Message_Humour `protobuf:"varint,16,rep,packed,name=r_funny,json=rFunny,enum=proto3_proto.Message_Humour" json:"r_funny,omitempty"` + Terrain map[string]*Nested `protobuf:"bytes,10,rep,name=terrain" json:"terrain,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + Proto2Field *testdata.SubDefaults `protobuf:"bytes,11,opt,name=proto2_field,json=proto2Field" json:"proto2_field,omitempty"` + Proto2Value map[string]*testdata.SubDefaults `protobuf:"bytes,13,rep,name=proto2_value,json=proto2Value" json:"proto2_value,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + Anything *google_protobuf.Any `protobuf:"bytes,14,opt,name=anything" json:"anything,omitempty"` + ManyThings []*google_protobuf.Any `protobuf:"bytes,15,rep,name=many_things,json=manyThings" json:"many_things,omitempty"` + Submessage *Message `protobuf:"bytes,17,opt,name=submessage" json:"submessage,omitempty"` + Children []*Message `protobuf:"bytes,18,rep,name=children" json:"children,omitempty"` +} + +func (m *Message) Reset() { *m = Message{} } +func (m *Message) String() string { return proto.CompactTextString(m) } +func (*Message) ProtoMessage() {} +func (*Message) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } + +func (m *Message) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *Message) GetHilarity() Message_Humour { + if m != nil { + return m.Hilarity + } + return Message_UNKNOWN +} + +func (m *Message) GetHeightInCm() uint32 { + if m != nil { + return m.HeightInCm + } + return 0 +} + +func (m *Message) GetData() []byte { + if m != nil { + return m.Data + } + return nil +} + +func (m *Message) GetResultCount() int64 { + if m != nil { + return m.ResultCount + } + return 0 +} + +func (m *Message) GetTrueScotsman() bool { + if m != nil { + return m.TrueScotsman + } + return false +} + +func (m *Message) GetScore() float32 { + if m != nil { + return m.Score + } + return 0 +} + +func (m *Message) GetKey() []uint64 { + if m != nil { + return m.Key + } + return nil +} + +func (m *Message) GetShortKey() []int32 { + if m != nil { + return m.ShortKey + } + return nil +} + +func (m *Message) GetNested() *Nested { + if m != nil { + return m.Nested + } + return nil +} + +func (m *Message) GetRFunny() []Message_Humour { + if m != nil { + return m.RFunny + } + return nil +} + +func (m *Message) GetTerrain() map[string]*Nested { + if m != nil { + return m.Terrain + } + return nil +} + +func (m *Message) GetProto2Field() *testdata.SubDefaults { + if m != nil { + return m.Proto2Field + } + return nil +} + +func (m *Message) GetProto2Value() map[string]*testdata.SubDefaults { + if m != nil { + return m.Proto2Value + } + return nil +} + +func (m *Message) GetAnything() *google_protobuf.Any { + if m != nil { + return m.Anything + } + return nil +} + +func (m *Message) GetManyThings() []*google_protobuf.Any { + if m != nil { + return m.ManyThings + } + return nil +} + +func (m *Message) GetSubmessage() *Message { + if m != nil { + return m.Submessage + } + return nil +} + +func (m *Message) GetChildren() []*Message { + if m != nil { + return m.Children + } + return nil +} + +type Nested struct { + Bunny string `protobuf:"bytes,1,opt,name=bunny" json:"bunny,omitempty"` + Cute bool `protobuf:"varint,2,opt,name=cute" json:"cute,omitempty"` +} + +func (m *Nested) Reset() { *m = Nested{} } +func (m *Nested) String() string { return proto.CompactTextString(m) } +func (*Nested) ProtoMessage() {} +func (*Nested) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } + +func (m *Nested) GetBunny() string { + if m != nil { + return m.Bunny + } + return "" +} + +func (m *Nested) GetCute() bool { + if m != nil { + return m.Cute + } + return false +} + +type MessageWithMap struct { + ByteMapping map[bool][]byte `protobuf:"bytes,1,rep,name=byte_mapping,json=byteMapping" json:"byte_mapping,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value,proto3"` +} + +func (m *MessageWithMap) Reset() { *m = MessageWithMap{} } +func (m *MessageWithMap) String() string { return proto.CompactTextString(m) } +func (*MessageWithMap) ProtoMessage() {} +func (*MessageWithMap) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } + +func (m *MessageWithMap) GetByteMapping() map[bool][]byte { + if m != nil { + return m.ByteMapping + } + return nil +} + +type IntMap struct { + Rtt map[int32]int32 `protobuf:"bytes,1,rep,name=rtt" json:"rtt,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"varint,2,opt,name=value"` +} + +func (m *IntMap) Reset() { *m = IntMap{} } +func (m *IntMap) String() string { return proto.CompactTextString(m) } +func (*IntMap) ProtoMessage() {} +func (*IntMap) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } + +func (m *IntMap) GetRtt() map[int32]int32 { + if m != nil { + return m.Rtt + } + return nil +} + +type IntMaps struct { + Maps []*IntMap `protobuf:"bytes,1,rep,name=maps" json:"maps,omitempty"` +} + +func (m *IntMaps) Reset() { *m = IntMaps{} } +func (m *IntMaps) String() string { return proto.CompactTextString(m) } +func (*IntMaps) ProtoMessage() {} +func (*IntMaps) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} } + +func (m *IntMaps) GetMaps() []*IntMap { + if m != nil { + return m.Maps + } + return nil +} + +func init() { + proto.RegisterType((*Message)(nil), "proto3_proto.Message") + proto.RegisterType((*Nested)(nil), "proto3_proto.Nested") + proto.RegisterType((*MessageWithMap)(nil), "proto3_proto.MessageWithMap") + proto.RegisterType((*IntMap)(nil), "proto3_proto.IntMap") + proto.RegisterType((*IntMaps)(nil), "proto3_proto.IntMaps") + proto.RegisterEnum("proto3_proto.Message_Humour", Message_Humour_name, Message_Humour_value) +} + +func init() { proto.RegisterFile("proto3_proto/proto3.proto", fileDescriptor0) } + +var fileDescriptor0 = []byte{ + // 733 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x84, 0x53, 0x6d, 0x6f, 0xf3, 0x34, + 0x14, 0x25, 0x4d, 0x5f, 0xd2, 0x9b, 0x74, 0x0b, 0x5e, 0x91, 0xbc, 0x02, 0x52, 0x28, 0x12, 0x8a, + 0x78, 0x49, 0xa1, 0xd3, 0xd0, 0x84, 0x10, 0x68, 0x1b, 0x9b, 0xa8, 0xd6, 0x95, 0xca, 0xdd, 0x98, + 0xf8, 0x14, 0xa5, 0xad, 0xdb, 0x46, 0x34, 0x4e, 0x49, 0x1c, 0xa4, 0xfc, 0x1d, 0xfe, 0x28, 0x8f, + 0x6c, 0xa7, 0x5d, 0x36, 0x65, 0xcf, 0xf3, 0x29, 0xf6, 0xf1, 0xb9, 0xf7, 0x9c, 0x1c, 0x5f, 0xc3, + 0xe9, 0x2e, 0x89, 0x79, 0x7c, 0xe6, 0xcb, 0xcf, 0x40, 0x6d, 0x3c, 0xf9, 0x41, 0x56, 0xf9, 0xa8, + 0x77, 0xba, 0x8e, 0xe3, 0xf5, 0x96, 0x2a, 0xca, 0x3c, 0x5b, 0x0d, 0x02, 0x96, 0x2b, 0x62, 0xef, + 0x84, 0xd3, 0x94, 0x2f, 0x03, 0x1e, 0x0c, 0xc4, 0x42, 0x81, 0xfd, 0xff, 0x5b, 0xd0, 0xba, 0xa7, + 0x69, 0x1a, 0xac, 0x29, 0x42, 0x50, 0x67, 0x41, 0x44, 0xb1, 0xe6, 0x68, 0x6e, 0x9b, 0xc8, 0x35, + 0xba, 0x00, 0x63, 0x13, 0x6e, 0x83, 0x24, 0xe4, 0x39, 0xae, 0x39, 0x9a, 0x7b, 0x34, 0xfc, 0xcc, + 0x2b, 0x0b, 0x7a, 0x45, 0xb1, 0xf7, 0x7b, 0x16, 0xc5, 0x59, 0x42, 0x0e, 0x6c, 0xe4, 0x80, 0xb5, + 0xa1, 0xe1, 0x7a, 0xc3, 0xfd, 0x90, 0xf9, 0x8b, 0x08, 0xeb, 0x8e, 0xe6, 0x76, 0x08, 0x28, 0x6c, + 0xc4, 0xae, 0x23, 0xa1, 0x27, 0xec, 0xe0, 0xba, 0xa3, 0xb9, 0x16, 0x91, 0x6b, 0xf4, 0x05, 0x58, + 0x09, 0x4d, 0xb3, 0x2d, 0xf7, 0x17, 0x71, 0xc6, 0x38, 0x6e, 0x39, 0x9a, 0xab, 0x13, 0x53, 0x61, + 0xd7, 0x02, 0x42, 0x5f, 0x42, 0x87, 0x27, 0x19, 0xf5, 0xd3, 0x45, 0xcc, 0xd3, 0x28, 0x60, 0xd8, + 0x70, 0x34, 0xd7, 0x20, 0x96, 0x00, 0x67, 0x05, 0x86, 0xba, 0xd0, 0x48, 0x17, 0x71, 0x42, 0x71, + 0xdb, 0xd1, 0xdc, 0x1a, 0x51, 0x1b, 0x64, 0x83, 0xfe, 0x37, 0xcd, 0x71, 0xc3, 0xd1, 0xdd, 0x3a, + 0x11, 0x4b, 0xf4, 0x29, 0xb4, 0xd3, 0x4d, 0x9c, 0x70, 0x5f, 0xe0, 0x27, 0x8e, 0xee, 0x36, 0x88, + 0x21, 0x81, 0x3b, 0x9a, 0xa3, 0x6f, 0xa1, 0xc9, 0x68, 0xca, 0xe9, 0x12, 0x37, 0x1d, 0xcd, 0x35, + 0x87, 0xdd, 0x97, 0xbf, 0x3e, 0x91, 0x67, 0xa4, 0xe0, 0xa0, 0x73, 0x68, 0x25, 0xfe, 0x2a, 0x63, + 0x2c, 0xc7, 0xb6, 0xa3, 0x7f, 0x30, 0xa9, 0x66, 0x72, 0x2b, 0xb8, 0xe8, 0x67, 0x68, 0x71, 0x9a, + 0x24, 0x41, 0xc8, 0x30, 0x38, 0xba, 0x6b, 0x0e, 0xfb, 0xd5, 0x65, 0x0f, 0x8a, 0x74, 0xc3, 0x78, + 0x92, 0x93, 0x7d, 0x09, 0xba, 0x00, 0x75, 0xff, 0x43, 0x7f, 0x15, 0xd2, 0xed, 0x12, 0x9b, 0xd2, + 0xe8, 0x27, 0xde, 0xfe, 0xae, 0xbd, 0x59, 0x36, 0xff, 0x8d, 0xae, 0x82, 0x6c, 0xcb, 0x53, 0x62, + 0x2a, 0xea, 0xad, 0x60, 0xa2, 0xd1, 0xa1, 0xf2, 0xdf, 0x60, 0x9b, 0x51, 0xdc, 0x91, 0xe2, 0x5f, + 0x55, 0x8b, 0x4f, 0x25, 0xf3, 0x4f, 0x41, 0x54, 0x06, 0x8a, 0x56, 0x12, 0x41, 0xdf, 0x83, 0x11, + 0xb0, 0x9c, 0x6f, 0x42, 0xb6, 0xc6, 0x47, 0x45, 0x52, 0x6a, 0x0e, 0xbd, 0xfd, 0x1c, 0x7a, 0x97, + 0x2c, 0x27, 0x07, 0x16, 0x3a, 0x07, 0x33, 0x0a, 0x58, 0xee, 0xcb, 0x5d, 0x8a, 0x8f, 0xa5, 0x76, + 0x75, 0x11, 0x08, 0xe2, 0x83, 0xe4, 0xa1, 0x73, 0x80, 0x34, 0x9b, 0x47, 0xca, 0x14, 0xfe, 0xb8, + 0xf8, 0xd7, 0x2a, 0xc7, 0xa4, 0x44, 0x44, 0x3f, 0x80, 0xb1, 0xd8, 0x84, 0xdb, 0x65, 0x42, 0x19, + 0x46, 0x52, 0xea, 0x8d, 0xa2, 0x03, 0xad, 0x37, 0x05, 0xab, 0x1c, 0xf8, 0x7e, 0x72, 0xd4, 0xd3, + 0x90, 0x93, 0xf3, 0x35, 0x34, 0x54, 0x70, 0xb5, 0xf7, 0xcc, 0x86, 0xa2, 0xfc, 0x54, 0xbb, 0xd0, + 0x7a, 0x8f, 0x60, 0xbf, 0x4e, 0xb1, 0xa2, 0xeb, 0x37, 0x2f, 0xbb, 0xbe, 0x71, 0x91, 0xcf, 0x6d, + 0xfb, 0xbf, 0x42, 0x53, 0x0d, 0x14, 0x32, 0xa1, 0xf5, 0x38, 0xb9, 0x9b, 0xfc, 0xf1, 0x34, 0xb1, + 0x3f, 0x42, 0x06, 0xd4, 0xa7, 0x8f, 0x93, 0x99, 0xad, 0xa1, 0x0e, 0xb4, 0x67, 0xe3, 0xcb, 0xe9, + 0xec, 0x61, 0x74, 0x7d, 0x67, 0xd7, 0xd0, 0x31, 0x98, 0x57, 0xa3, 0xf1, 0xd8, 0xbf, 0xba, 0x1c, + 0x8d, 0x6f, 0xfe, 0xb2, 0xf5, 0xfe, 0x10, 0x9a, 0xca, 0xac, 0x78, 0x33, 0x73, 0x39, 0xbe, 0xca, + 0x8f, 0xda, 0x88, 0x57, 0xba, 0xc8, 0xb8, 0x32, 0x64, 0x10, 0xb9, 0xee, 0xff, 0xa7, 0xc1, 0x51, + 0x91, 0xd9, 0x53, 0xc8, 0x37, 0xf7, 0xc1, 0x0e, 0x4d, 0xc1, 0x9a, 0xe7, 0x9c, 0xfa, 0x51, 0xb0, + 0xdb, 0x89, 0x39, 0xd0, 0x64, 0xce, 0xdf, 0x55, 0xe6, 0x5c, 0xd4, 0x78, 0x57, 0x39, 0xa7, 0xf7, + 0x8a, 0x5f, 0x4c, 0xd5, 0xfc, 0x19, 0xe9, 0xfd, 0x02, 0xf6, 0x6b, 0x42, 0x39, 0x30, 0x43, 0x05, + 0xd6, 0x2d, 0x07, 0x66, 0x95, 0x93, 0xf9, 0x07, 0x9a, 0x23, 0xc6, 0x85, 0xb7, 0x01, 0xe8, 0x09, + 0xe7, 0x85, 0xa5, 0xcf, 0x5f, 0x5a, 0x52, 0x14, 0x8f, 0x70, 0xae, 0x2c, 0x08, 0x66, 0xef, 0x47, + 0x30, 0xf6, 0x40, 0x59, 0xb2, 0x51, 0x21, 0xd9, 0x28, 0x4b, 0x9e, 0x41, 0x4b, 0xf5, 0x4b, 0x91, + 0x0b, 0xf5, 0x28, 0xd8, 0xa5, 0x85, 0x68, 0xb7, 0x4a, 0x94, 0x48, 0xc6, 0xbc, 0xa9, 0x8e, 0xde, + 0x05, 0x00, 0x00, 0xff, 0xff, 0x75, 0x38, 0xad, 0x84, 0xe4, 0x05, 0x00, 0x00, +} diff --git a/vendor/github.com/golang/protobuf/proto/proto3_proto/proto3.proto b/vendor/github.com/golang/protobuf/proto/proto3_proto/proto3.proto new file mode 100644 index 00000000..20486557 --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/proto3_proto/proto3.proto @@ -0,0 +1,87 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2014 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// 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 +// OWNER 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. + +syntax = "proto3"; + +import "google/protobuf/any.proto"; +import "testdata/test.proto"; + +package proto3_proto; + +message Message { + enum Humour { + UNKNOWN = 0; + PUNS = 1; + SLAPSTICK = 2; + BILL_BAILEY = 3; + } + + string name = 1; + Humour hilarity = 2; + uint32 height_in_cm = 3; + bytes data = 4; + int64 result_count = 7; + bool true_scotsman = 8; + float score = 9; + + repeated uint64 key = 5; + repeated int32 short_key = 19; + Nested nested = 6; + repeated Humour r_funny = 16; + + map terrain = 10; + testdata.SubDefaults proto2_field = 11; + map proto2_value = 13; + + google.protobuf.Any anything = 14; + repeated google.protobuf.Any many_things = 15; + + Message submessage = 17; + repeated Message children = 18; +} + +message Nested { + string bunny = 1; + bool cute = 2; +} + +message MessageWithMap { + map byte_mapping = 1; +} + + +message IntMap { + map rtt = 1; +} + +message IntMaps { + repeated IntMap maps = 1; +} diff --git a/vendor/github.com/golang/protobuf/proto/proto3_test.go b/vendor/github.com/golang/protobuf/proto/proto3_test.go new file mode 100644 index 00000000..735837f2 --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/proto3_test.go @@ -0,0 +1,135 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2014 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// 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 +// OWNER 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. + +package proto_test + +import ( + "testing" + + "github.com/golang/protobuf/proto" + pb "github.com/golang/protobuf/proto/proto3_proto" + tpb "github.com/golang/protobuf/proto/testdata" +) + +func TestProto3ZeroValues(t *testing.T) { + tests := []struct { + desc string + m proto.Message + }{ + {"zero message", &pb.Message{}}, + {"empty bytes field", &pb.Message{Data: []byte{}}}, + } + for _, test := range tests { + b, err := proto.Marshal(test.m) + if err != nil { + t.Errorf("%s: proto.Marshal: %v", test.desc, err) + continue + } + if len(b) > 0 { + t.Errorf("%s: Encoding is non-empty: %q", test.desc, b) + } + } +} + +func TestRoundTripProto3(t *testing.T) { + m := &pb.Message{ + Name: "David", // (2 | 1<<3): 0x0a 0x05 "David" + Hilarity: pb.Message_PUNS, // (0 | 2<<3): 0x10 0x01 + HeightInCm: 178, // (0 | 3<<3): 0x18 0xb2 0x01 + Data: []byte("roboto"), // (2 | 4<<3): 0x20 0x06 "roboto" + ResultCount: 47, // (0 | 7<<3): 0x38 0x2f + TrueScotsman: true, // (0 | 8<<3): 0x40 0x01 + Score: 8.1, // (5 | 9<<3): 0x4d <8.1> + + Key: []uint64{1, 0xdeadbeef}, + Nested: &pb.Nested{ + Bunny: "Monty", + }, + } + t.Logf(" m: %v", m) + + b, err := proto.Marshal(m) + if err != nil { + t.Fatalf("proto.Marshal: %v", err) + } + t.Logf(" b: %q", b) + + m2 := new(pb.Message) + if err := proto.Unmarshal(b, m2); err != nil { + t.Fatalf("proto.Unmarshal: %v", err) + } + t.Logf("m2: %v", m2) + + if !proto.Equal(m, m2) { + t.Errorf("proto.Equal returned false:\n m: %v\nm2: %v", m, m2) + } +} + +func TestGettersForBasicTypesExist(t *testing.T) { + var m pb.Message + if got := m.GetNested().GetBunny(); got != "" { + t.Errorf("m.GetNested().GetBunny() = %q, want empty string", got) + } + if got := m.GetNested().GetCute(); got { + t.Errorf("m.GetNested().GetCute() = %t, want false", got) + } +} + +func TestProto3SetDefaults(t *testing.T) { + in := &pb.Message{ + Terrain: map[string]*pb.Nested{ + "meadow": new(pb.Nested), + }, + Proto2Field: new(tpb.SubDefaults), + Proto2Value: map[string]*tpb.SubDefaults{ + "badlands": new(tpb.SubDefaults), + }, + } + + got := proto.Clone(in).(*pb.Message) + proto.SetDefaults(got) + + // There are no defaults in proto3. Everything should be the zero value, but + // we need to remember to set defaults for nested proto2 messages. + want := &pb.Message{ + Terrain: map[string]*pb.Nested{ + "meadow": new(pb.Nested), + }, + Proto2Field: &tpb.SubDefaults{N: proto.Int64(7)}, + Proto2Value: map[string]*tpb.SubDefaults{ + "badlands": &tpb.SubDefaults{N: proto.Int64(7)}, + }, + } + + if !proto.Equal(got, want) { + t.Errorf("with in = %v\nproto.SetDefaults(in) =>\ngot %v\nwant %v", in, got, want) + } +} diff --git a/vendor/github.com/golang/protobuf/proto/size2_test.go b/vendor/github.com/golang/protobuf/proto/size2_test.go new file mode 100644 index 00000000..a2729c39 --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/size2_test.go @@ -0,0 +1,63 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2012 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// 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 +// OWNER 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. + +package proto + +import ( + "testing" +) + +// This is a separate file and package from size_test.go because that one uses +// generated messages and thus may not be in package proto without having a circular +// dependency, whereas this file tests unexported details of size.go. + +func TestVarintSize(t *testing.T) { + // Check the edge cases carefully. + testCases := []struct { + n uint64 + size int + }{ + {0, 1}, + {1, 1}, + {127, 1}, + {128, 2}, + {16383, 2}, + {16384, 3}, + {1<<63 - 1, 9}, + {1 << 63, 10}, + } + for _, tc := range testCases { + size := sizeVarint(tc.n) + if size != tc.size { + t.Errorf("sizeVarint(%d) = %d, want %d", tc.n, size, tc.size) + } + } +} diff --git a/vendor/github.com/golang/protobuf/proto/size_test.go b/vendor/github.com/golang/protobuf/proto/size_test.go new file mode 100644 index 00000000..af1034dc --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/size_test.go @@ -0,0 +1,164 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2012 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// 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 +// OWNER 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. + +package proto_test + +import ( + "log" + "strings" + "testing" + + . "github.com/golang/protobuf/proto" + proto3pb "github.com/golang/protobuf/proto/proto3_proto" + pb "github.com/golang/protobuf/proto/testdata" +) + +var messageWithExtension1 = &pb.MyMessage{Count: Int32(7)} + +// messageWithExtension2 is in equal_test.go. +var messageWithExtension3 = &pb.MyMessage{Count: Int32(8)} + +func init() { + if err := SetExtension(messageWithExtension1, pb.E_Ext_More, &pb.Ext{Data: String("Abbott")}); err != nil { + log.Panicf("SetExtension: %v", err) + } + if err := SetExtension(messageWithExtension3, pb.E_Ext_More, &pb.Ext{Data: String("Costello")}); err != nil { + log.Panicf("SetExtension: %v", err) + } + + // Force messageWithExtension3 to have the extension encoded. + Marshal(messageWithExtension3) + +} + +var SizeTests = []struct { + desc string + pb Message +}{ + {"empty", &pb.OtherMessage{}}, + // Basic types. + {"bool", &pb.Defaults{F_Bool: Bool(true)}}, + {"int32", &pb.Defaults{F_Int32: Int32(12)}}, + {"negative int32", &pb.Defaults{F_Int32: Int32(-1)}}, + {"small int64", &pb.Defaults{F_Int64: Int64(1)}}, + {"big int64", &pb.Defaults{F_Int64: Int64(1 << 20)}}, + {"negative int64", &pb.Defaults{F_Int64: Int64(-1)}}, + {"fixed32", &pb.Defaults{F_Fixed32: Uint32(71)}}, + {"fixed64", &pb.Defaults{F_Fixed64: Uint64(72)}}, + {"uint32", &pb.Defaults{F_Uint32: Uint32(123)}}, + {"uint64", &pb.Defaults{F_Uint64: Uint64(124)}}, + {"float", &pb.Defaults{F_Float: Float32(12.6)}}, + {"double", &pb.Defaults{F_Double: Float64(13.9)}}, + {"string", &pb.Defaults{F_String: String("niles")}}, + {"bytes", &pb.Defaults{F_Bytes: []byte("wowsa")}}, + {"bytes, empty", &pb.Defaults{F_Bytes: []byte{}}}, + {"sint32", &pb.Defaults{F_Sint32: Int32(65)}}, + {"sint64", &pb.Defaults{F_Sint64: Int64(67)}}, + {"enum", &pb.Defaults{F_Enum: pb.Defaults_BLUE.Enum()}}, + // Repeated. + {"empty repeated bool", &pb.MoreRepeated{Bools: []bool{}}}, + {"repeated bool", &pb.MoreRepeated{Bools: []bool{false, true, true, false}}}, + {"packed repeated bool", &pb.MoreRepeated{BoolsPacked: []bool{false, true, true, false, true, true, true}}}, + {"repeated int32", &pb.MoreRepeated{Ints: []int32{1, 12203, 1729, -1}}}, + {"repeated int32 packed", &pb.MoreRepeated{IntsPacked: []int32{1, 12203, 1729}}}, + {"repeated int64 packed", &pb.MoreRepeated{Int64SPacked: []int64{ + // Need enough large numbers to verify that the header is counting the number of bytes + // for the field, not the number of elements. + 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, + 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, 1 << 62, + }}}, + {"repeated string", &pb.MoreRepeated{Strings: []string{"r", "ken", "gri"}}}, + {"repeated fixed", &pb.MoreRepeated{Fixeds: []uint32{1, 2, 3, 4}}}, + // Nested. + {"nested", &pb.OldMessage{Nested: &pb.OldMessage_Nested{Name: String("whatever")}}}, + {"group", &pb.GroupOld{G: &pb.GroupOld_G{X: Int32(12345)}}}, + // Other things. + {"unrecognized", &pb.MoreRepeated{XXX_unrecognized: []byte{13<<3 | 0, 4}}}, + {"extension (unencoded)", messageWithExtension1}, + {"extension (encoded)", messageWithExtension3}, + // proto3 message + {"proto3 empty", &proto3pb.Message{}}, + {"proto3 bool", &proto3pb.Message{TrueScotsman: true}}, + {"proto3 int64", &proto3pb.Message{ResultCount: 1}}, + {"proto3 uint32", &proto3pb.Message{HeightInCm: 123}}, + {"proto3 float", &proto3pb.Message{Score: 12.6}}, + {"proto3 string", &proto3pb.Message{Name: "Snezana"}}, + {"proto3 bytes", &proto3pb.Message{Data: []byte("wowsa")}}, + {"proto3 bytes, empty", &proto3pb.Message{Data: []byte{}}}, + {"proto3 enum", &proto3pb.Message{Hilarity: proto3pb.Message_PUNS}}, + {"proto3 map field with empty bytes", &proto3pb.MessageWithMap{ByteMapping: map[bool][]byte{false: []byte{}}}}, + + {"map field", &pb.MessageWithMap{NameMapping: map[int32]string{1: "Rob", 7: "Andrew"}}}, + {"map field with message", &pb.MessageWithMap{MsgMapping: map[int64]*pb.FloatingPoint{0x7001: &pb.FloatingPoint{F: Float64(2.0)}}}}, + {"map field with bytes", &pb.MessageWithMap{ByteMapping: map[bool][]byte{true: []byte("this time for sure")}}}, + {"map field with empty bytes", &pb.MessageWithMap{ByteMapping: map[bool][]byte{true: []byte{}}}}, + + {"map field with big entry", &pb.MessageWithMap{NameMapping: map[int32]string{8: strings.Repeat("x", 125)}}}, + {"map field with big key and val", &pb.MessageWithMap{StrToStr: map[string]string{strings.Repeat("x", 70): strings.Repeat("y", 70)}}}, + {"map field with big numeric key", &pb.MessageWithMap{NameMapping: map[int32]string{0xf00d: "om nom nom"}}}, + + {"oneof not set", &pb.Oneof{}}, + {"oneof bool", &pb.Oneof{Union: &pb.Oneof_F_Bool{true}}}, + {"oneof zero int32", &pb.Oneof{Union: &pb.Oneof_F_Int32{0}}}, + {"oneof big int32", &pb.Oneof{Union: &pb.Oneof_F_Int32{1 << 20}}}, + {"oneof int64", &pb.Oneof{Union: &pb.Oneof_F_Int64{42}}}, + {"oneof fixed32", &pb.Oneof{Union: &pb.Oneof_F_Fixed32{43}}}, + {"oneof fixed64", &pb.Oneof{Union: &pb.Oneof_F_Fixed64{44}}}, + {"oneof uint32", &pb.Oneof{Union: &pb.Oneof_F_Uint32{45}}}, + {"oneof uint64", &pb.Oneof{Union: &pb.Oneof_F_Uint64{46}}}, + {"oneof float", &pb.Oneof{Union: &pb.Oneof_F_Float{47.1}}}, + {"oneof double", &pb.Oneof{Union: &pb.Oneof_F_Double{48.9}}}, + {"oneof string", &pb.Oneof{Union: &pb.Oneof_F_String{"Rhythmic Fman"}}}, + {"oneof bytes", &pb.Oneof{Union: &pb.Oneof_F_Bytes{[]byte("let go")}}}, + {"oneof sint32", &pb.Oneof{Union: &pb.Oneof_F_Sint32{50}}}, + {"oneof sint64", &pb.Oneof{Union: &pb.Oneof_F_Sint64{51}}}, + {"oneof enum", &pb.Oneof{Union: &pb.Oneof_F_Enum{pb.MyMessage_BLUE}}}, + {"message for oneof", &pb.GoTestField{Label: String("k"), Type: String("v")}}, + {"oneof message", &pb.Oneof{Union: &pb.Oneof_F_Message{&pb.GoTestField{Label: String("k"), Type: String("v")}}}}, + {"oneof group", &pb.Oneof{Union: &pb.Oneof_FGroup{&pb.Oneof_F_Group{X: Int32(52)}}}}, + {"oneof largest tag", &pb.Oneof{Union: &pb.Oneof_F_Largest_Tag{1}}}, + {"multiple oneofs", &pb.Oneof{Union: &pb.Oneof_F_Int32{1}, Tormato: &pb.Oneof_Value{2}}}, +} + +func TestSize(t *testing.T) { + for _, tc := range SizeTests { + size := Size(tc.pb) + b, err := Marshal(tc.pb) + if err != nil { + t.Errorf("%v: Marshal failed: %v", tc.desc, err) + continue + } + if size != len(b) { + t.Errorf("%v: Size(%v) = %d, want %d", tc.desc, tc.pb, size, len(b)) + t.Logf("%v: bytes: %#v", tc.desc, b) + } + } +} diff --git a/vendor/github.com/golang/protobuf/proto/testdata/Makefile b/vendor/github.com/golang/protobuf/proto/testdata/Makefile new file mode 100644 index 00000000..fc288628 --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/testdata/Makefile @@ -0,0 +1,50 @@ +# Go support for Protocol Buffers - Google's data interchange format +# +# Copyright 2010 The Go Authors. All rights reserved. +# https://github.com/golang/protobuf +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# 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 +# OWNER 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. + + +include ../../Make.protobuf + +all: regenerate + +regenerate: + rm -f test.pb.go + make test.pb.go + +# The following rules are just aids to development. Not needed for typical testing. + +diff: regenerate + git diff test.pb.go + +restore: + cp test.pb.go.golden test.pb.go + +preserve: + cp test.pb.go test.pb.go.golden diff --git a/vendor/github.com/golang/protobuf/proto/testdata/golden_test.go b/vendor/github.com/golang/protobuf/proto/testdata/golden_test.go new file mode 100644 index 00000000..7172d0e9 --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/testdata/golden_test.go @@ -0,0 +1,86 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2012 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// 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 +// OWNER 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. + +// Verify that the compiler output for test.proto is unchanged. + +package testdata + +import ( + "crypto/sha1" + "fmt" + "io/ioutil" + "os" + "os/exec" + "path/filepath" + "testing" +) + +// sum returns in string form (for easy comparison) the SHA-1 hash of the named file. +func sum(t *testing.T, name string) string { + data, err := ioutil.ReadFile(name) + if err != nil { + t.Fatal(err) + } + t.Logf("sum(%q): length is %d", name, len(data)) + hash := sha1.New() + _, err = hash.Write(data) + if err != nil { + t.Fatal(err) + } + return fmt.Sprintf("% x", hash.Sum(nil)) +} + +func run(t *testing.T, name string, args ...string) { + cmd := exec.Command(name, args...) + cmd.Stdin = os.Stdin + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + err := cmd.Run() + if err != nil { + t.Fatal(err) + } +} + +func TestGolden(t *testing.T) { + // Compute the original checksum. + goldenSum := sum(t, "test.pb.go") + // Run the proto compiler. + run(t, "protoc", "--go_out="+os.TempDir(), "test.proto") + newFile := filepath.Join(os.TempDir(), "test.pb.go") + defer os.Remove(newFile) + // Compute the new checksum. + newSum := sum(t, newFile) + // Verify + if newSum != goldenSum { + run(t, "diff", "-u", "test.pb.go", newFile) + t.Fatal("Code generated by protoc-gen-go has changed; update test.pb.go") + } +} diff --git a/vendor/github.com/golang/protobuf/proto/testdata/test.pb.go b/vendor/github.com/golang/protobuf/proto/testdata/test.pb.go new file mode 100644 index 00000000..e980d1a0 --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/testdata/test.pb.go @@ -0,0 +1,4147 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: test.proto + +/* +Package testdata is a generated protocol buffer package. + +It is generated from these files: + test.proto + +It has these top-level messages: + GoEnum + GoTestField + GoTest + GoTestRequiredGroupField + GoSkipTest + NonPackedTest + PackedTest + MaxTag + OldMessage + NewMessage + InnerMessage + OtherMessage + RequiredInnerMessage + MyMessage + Ext + ComplexExtension + DefaultsMessage + MyMessageSet + Empty + MessageList + Strings + Defaults + SubDefaults + RepeatedEnum + MoreRepeated + GroupOld + GroupNew + FloatingPoint + MessageWithMap + Oneof + Communique +*/ +package testdata + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package + +type FOO int32 + +const ( + FOO_FOO1 FOO = 1 +) + +var FOO_name = map[int32]string{ + 1: "FOO1", +} +var FOO_value = map[string]int32{ + "FOO1": 1, +} + +func (x FOO) Enum() *FOO { + p := new(FOO) + *p = x + return p +} +func (x FOO) String() string { + return proto.EnumName(FOO_name, int32(x)) +} +func (x *FOO) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(FOO_value, data, "FOO") + if err != nil { + return err + } + *x = FOO(value) + return nil +} +func (FOO) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } + +// An enum, for completeness. +type GoTest_KIND int32 + +const ( + GoTest_VOID GoTest_KIND = 0 + // Basic types + GoTest_BOOL GoTest_KIND = 1 + GoTest_BYTES GoTest_KIND = 2 + GoTest_FINGERPRINT GoTest_KIND = 3 + GoTest_FLOAT GoTest_KIND = 4 + GoTest_INT GoTest_KIND = 5 + GoTest_STRING GoTest_KIND = 6 + GoTest_TIME GoTest_KIND = 7 + // Groupings + GoTest_TUPLE GoTest_KIND = 8 + GoTest_ARRAY GoTest_KIND = 9 + GoTest_MAP GoTest_KIND = 10 + // Table types + GoTest_TABLE GoTest_KIND = 11 + // Functions + GoTest_FUNCTION GoTest_KIND = 12 +) + +var GoTest_KIND_name = map[int32]string{ + 0: "VOID", + 1: "BOOL", + 2: "BYTES", + 3: "FINGERPRINT", + 4: "FLOAT", + 5: "INT", + 6: "STRING", + 7: "TIME", + 8: "TUPLE", + 9: "ARRAY", + 10: "MAP", + 11: "TABLE", + 12: "FUNCTION", +} +var GoTest_KIND_value = map[string]int32{ + "VOID": 0, + "BOOL": 1, + "BYTES": 2, + "FINGERPRINT": 3, + "FLOAT": 4, + "INT": 5, + "STRING": 6, + "TIME": 7, + "TUPLE": 8, + "ARRAY": 9, + "MAP": 10, + "TABLE": 11, + "FUNCTION": 12, +} + +func (x GoTest_KIND) Enum() *GoTest_KIND { + p := new(GoTest_KIND) + *p = x + return p +} +func (x GoTest_KIND) String() string { + return proto.EnumName(GoTest_KIND_name, int32(x)) +} +func (x *GoTest_KIND) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(GoTest_KIND_value, data, "GoTest_KIND") + if err != nil { + return err + } + *x = GoTest_KIND(value) + return nil +} +func (GoTest_KIND) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{2, 0} } + +type MyMessage_Color int32 + +const ( + MyMessage_RED MyMessage_Color = 0 + MyMessage_GREEN MyMessage_Color = 1 + MyMessage_BLUE MyMessage_Color = 2 +) + +var MyMessage_Color_name = map[int32]string{ + 0: "RED", + 1: "GREEN", + 2: "BLUE", +} +var MyMessage_Color_value = map[string]int32{ + "RED": 0, + "GREEN": 1, + "BLUE": 2, +} + +func (x MyMessage_Color) Enum() *MyMessage_Color { + p := new(MyMessage_Color) + *p = x + return p +} +func (x MyMessage_Color) String() string { + return proto.EnumName(MyMessage_Color_name, int32(x)) +} +func (x *MyMessage_Color) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(MyMessage_Color_value, data, "MyMessage_Color") + if err != nil { + return err + } + *x = MyMessage_Color(value) + return nil +} +func (MyMessage_Color) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{13, 0} } + +type DefaultsMessage_DefaultsEnum int32 + +const ( + DefaultsMessage_ZERO DefaultsMessage_DefaultsEnum = 0 + DefaultsMessage_ONE DefaultsMessage_DefaultsEnum = 1 + DefaultsMessage_TWO DefaultsMessage_DefaultsEnum = 2 +) + +var DefaultsMessage_DefaultsEnum_name = map[int32]string{ + 0: "ZERO", + 1: "ONE", + 2: "TWO", +} +var DefaultsMessage_DefaultsEnum_value = map[string]int32{ + "ZERO": 0, + "ONE": 1, + "TWO": 2, +} + +func (x DefaultsMessage_DefaultsEnum) Enum() *DefaultsMessage_DefaultsEnum { + p := new(DefaultsMessage_DefaultsEnum) + *p = x + return p +} +func (x DefaultsMessage_DefaultsEnum) String() string { + return proto.EnumName(DefaultsMessage_DefaultsEnum_name, int32(x)) +} +func (x *DefaultsMessage_DefaultsEnum) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(DefaultsMessage_DefaultsEnum_value, data, "DefaultsMessage_DefaultsEnum") + if err != nil { + return err + } + *x = DefaultsMessage_DefaultsEnum(value) + return nil +} +func (DefaultsMessage_DefaultsEnum) EnumDescriptor() ([]byte, []int) { + return fileDescriptor0, []int{16, 0} +} + +type Defaults_Color int32 + +const ( + Defaults_RED Defaults_Color = 0 + Defaults_GREEN Defaults_Color = 1 + Defaults_BLUE Defaults_Color = 2 +) + +var Defaults_Color_name = map[int32]string{ + 0: "RED", + 1: "GREEN", + 2: "BLUE", +} +var Defaults_Color_value = map[string]int32{ + "RED": 0, + "GREEN": 1, + "BLUE": 2, +} + +func (x Defaults_Color) Enum() *Defaults_Color { + p := new(Defaults_Color) + *p = x + return p +} +func (x Defaults_Color) String() string { + return proto.EnumName(Defaults_Color_name, int32(x)) +} +func (x *Defaults_Color) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(Defaults_Color_value, data, "Defaults_Color") + if err != nil { + return err + } + *x = Defaults_Color(value) + return nil +} +func (Defaults_Color) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{21, 0} } + +type RepeatedEnum_Color int32 + +const ( + RepeatedEnum_RED RepeatedEnum_Color = 1 +) + +var RepeatedEnum_Color_name = map[int32]string{ + 1: "RED", +} +var RepeatedEnum_Color_value = map[string]int32{ + "RED": 1, +} + +func (x RepeatedEnum_Color) Enum() *RepeatedEnum_Color { + p := new(RepeatedEnum_Color) + *p = x + return p +} +func (x RepeatedEnum_Color) String() string { + return proto.EnumName(RepeatedEnum_Color_name, int32(x)) +} +func (x *RepeatedEnum_Color) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(RepeatedEnum_Color_value, data, "RepeatedEnum_Color") + if err != nil { + return err + } + *x = RepeatedEnum_Color(value) + return nil +} +func (RepeatedEnum_Color) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{23, 0} } + +type GoEnum struct { + Foo *FOO `protobuf:"varint,1,req,name=foo,enum=testdata.FOO" json:"foo,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *GoEnum) Reset() { *m = GoEnum{} } +func (m *GoEnum) String() string { return proto.CompactTextString(m) } +func (*GoEnum) ProtoMessage() {} +func (*GoEnum) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } + +func (m *GoEnum) GetFoo() FOO { + if m != nil && m.Foo != nil { + return *m.Foo + } + return FOO_FOO1 +} + +type GoTestField struct { + Label *string `protobuf:"bytes,1,req,name=Label" json:"Label,omitempty"` + Type *string `protobuf:"bytes,2,req,name=Type" json:"Type,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *GoTestField) Reset() { *m = GoTestField{} } +func (m *GoTestField) String() string { return proto.CompactTextString(m) } +func (*GoTestField) ProtoMessage() {} +func (*GoTestField) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } + +func (m *GoTestField) GetLabel() string { + if m != nil && m.Label != nil { + return *m.Label + } + return "" +} + +func (m *GoTestField) GetType() string { + if m != nil && m.Type != nil { + return *m.Type + } + return "" +} + +type GoTest struct { + // Some typical parameters + Kind *GoTest_KIND `protobuf:"varint,1,req,name=Kind,enum=testdata.GoTest_KIND" json:"Kind,omitempty"` + Table *string `protobuf:"bytes,2,opt,name=Table" json:"Table,omitempty"` + Param *int32 `protobuf:"varint,3,opt,name=Param" json:"Param,omitempty"` + // Required, repeated and optional foreign fields. + RequiredField *GoTestField `protobuf:"bytes,4,req,name=RequiredField" json:"RequiredField,omitempty"` + RepeatedField []*GoTestField `protobuf:"bytes,5,rep,name=RepeatedField" json:"RepeatedField,omitempty"` + OptionalField *GoTestField `protobuf:"bytes,6,opt,name=OptionalField" json:"OptionalField,omitempty"` + // Required fields of all basic types + F_BoolRequired *bool `protobuf:"varint,10,req,name=F_Bool_required,json=FBoolRequired" json:"F_Bool_required,omitempty"` + F_Int32Required *int32 `protobuf:"varint,11,req,name=F_Int32_required,json=FInt32Required" json:"F_Int32_required,omitempty"` + F_Int64Required *int64 `protobuf:"varint,12,req,name=F_Int64_required,json=FInt64Required" json:"F_Int64_required,omitempty"` + F_Fixed32Required *uint32 `protobuf:"fixed32,13,req,name=F_Fixed32_required,json=FFixed32Required" json:"F_Fixed32_required,omitempty"` + F_Fixed64Required *uint64 `protobuf:"fixed64,14,req,name=F_Fixed64_required,json=FFixed64Required" json:"F_Fixed64_required,omitempty"` + F_Uint32Required *uint32 `protobuf:"varint,15,req,name=F_Uint32_required,json=FUint32Required" json:"F_Uint32_required,omitempty"` + F_Uint64Required *uint64 `protobuf:"varint,16,req,name=F_Uint64_required,json=FUint64Required" json:"F_Uint64_required,omitempty"` + F_FloatRequired *float32 `protobuf:"fixed32,17,req,name=F_Float_required,json=FFloatRequired" json:"F_Float_required,omitempty"` + F_DoubleRequired *float64 `protobuf:"fixed64,18,req,name=F_Double_required,json=FDoubleRequired" json:"F_Double_required,omitempty"` + F_StringRequired *string `protobuf:"bytes,19,req,name=F_String_required,json=FStringRequired" json:"F_String_required,omitempty"` + F_BytesRequired []byte `protobuf:"bytes,101,req,name=F_Bytes_required,json=FBytesRequired" json:"F_Bytes_required,omitempty"` + F_Sint32Required *int32 `protobuf:"zigzag32,102,req,name=F_Sint32_required,json=FSint32Required" json:"F_Sint32_required,omitempty"` + F_Sint64Required *int64 `protobuf:"zigzag64,103,req,name=F_Sint64_required,json=FSint64Required" json:"F_Sint64_required,omitempty"` + // Repeated fields of all basic types + F_BoolRepeated []bool `protobuf:"varint,20,rep,name=F_Bool_repeated,json=FBoolRepeated" json:"F_Bool_repeated,omitempty"` + F_Int32Repeated []int32 `protobuf:"varint,21,rep,name=F_Int32_repeated,json=FInt32Repeated" json:"F_Int32_repeated,omitempty"` + F_Int64Repeated []int64 `protobuf:"varint,22,rep,name=F_Int64_repeated,json=FInt64Repeated" json:"F_Int64_repeated,omitempty"` + F_Fixed32Repeated []uint32 `protobuf:"fixed32,23,rep,name=F_Fixed32_repeated,json=FFixed32Repeated" json:"F_Fixed32_repeated,omitempty"` + F_Fixed64Repeated []uint64 `protobuf:"fixed64,24,rep,name=F_Fixed64_repeated,json=FFixed64Repeated" json:"F_Fixed64_repeated,omitempty"` + F_Uint32Repeated []uint32 `protobuf:"varint,25,rep,name=F_Uint32_repeated,json=FUint32Repeated" json:"F_Uint32_repeated,omitempty"` + F_Uint64Repeated []uint64 `protobuf:"varint,26,rep,name=F_Uint64_repeated,json=FUint64Repeated" json:"F_Uint64_repeated,omitempty"` + F_FloatRepeated []float32 `protobuf:"fixed32,27,rep,name=F_Float_repeated,json=FFloatRepeated" json:"F_Float_repeated,omitempty"` + F_DoubleRepeated []float64 `protobuf:"fixed64,28,rep,name=F_Double_repeated,json=FDoubleRepeated" json:"F_Double_repeated,omitempty"` + F_StringRepeated []string `protobuf:"bytes,29,rep,name=F_String_repeated,json=FStringRepeated" json:"F_String_repeated,omitempty"` + F_BytesRepeated [][]byte `protobuf:"bytes,201,rep,name=F_Bytes_repeated,json=FBytesRepeated" json:"F_Bytes_repeated,omitempty"` + F_Sint32Repeated []int32 `protobuf:"zigzag32,202,rep,name=F_Sint32_repeated,json=FSint32Repeated" json:"F_Sint32_repeated,omitempty"` + F_Sint64Repeated []int64 `protobuf:"zigzag64,203,rep,name=F_Sint64_repeated,json=FSint64Repeated" json:"F_Sint64_repeated,omitempty"` + // Optional fields of all basic types + F_BoolOptional *bool `protobuf:"varint,30,opt,name=F_Bool_optional,json=FBoolOptional" json:"F_Bool_optional,omitempty"` + F_Int32Optional *int32 `protobuf:"varint,31,opt,name=F_Int32_optional,json=FInt32Optional" json:"F_Int32_optional,omitempty"` + F_Int64Optional *int64 `protobuf:"varint,32,opt,name=F_Int64_optional,json=FInt64Optional" json:"F_Int64_optional,omitempty"` + F_Fixed32Optional *uint32 `protobuf:"fixed32,33,opt,name=F_Fixed32_optional,json=FFixed32Optional" json:"F_Fixed32_optional,omitempty"` + F_Fixed64Optional *uint64 `protobuf:"fixed64,34,opt,name=F_Fixed64_optional,json=FFixed64Optional" json:"F_Fixed64_optional,omitempty"` + F_Uint32Optional *uint32 `protobuf:"varint,35,opt,name=F_Uint32_optional,json=FUint32Optional" json:"F_Uint32_optional,omitempty"` + F_Uint64Optional *uint64 `protobuf:"varint,36,opt,name=F_Uint64_optional,json=FUint64Optional" json:"F_Uint64_optional,omitempty"` + F_FloatOptional *float32 `protobuf:"fixed32,37,opt,name=F_Float_optional,json=FFloatOptional" json:"F_Float_optional,omitempty"` + F_DoubleOptional *float64 `protobuf:"fixed64,38,opt,name=F_Double_optional,json=FDoubleOptional" json:"F_Double_optional,omitempty"` + F_StringOptional *string `protobuf:"bytes,39,opt,name=F_String_optional,json=FStringOptional" json:"F_String_optional,omitempty"` + F_BytesOptional []byte `protobuf:"bytes,301,opt,name=F_Bytes_optional,json=FBytesOptional" json:"F_Bytes_optional,omitempty"` + F_Sint32Optional *int32 `protobuf:"zigzag32,302,opt,name=F_Sint32_optional,json=FSint32Optional" json:"F_Sint32_optional,omitempty"` + F_Sint64Optional *int64 `protobuf:"zigzag64,303,opt,name=F_Sint64_optional,json=FSint64Optional" json:"F_Sint64_optional,omitempty"` + // Default-valued fields of all basic types + F_BoolDefaulted *bool `protobuf:"varint,40,opt,name=F_Bool_defaulted,json=FBoolDefaulted,def=1" json:"F_Bool_defaulted,omitempty"` + F_Int32Defaulted *int32 `protobuf:"varint,41,opt,name=F_Int32_defaulted,json=FInt32Defaulted,def=32" json:"F_Int32_defaulted,omitempty"` + F_Int64Defaulted *int64 `protobuf:"varint,42,opt,name=F_Int64_defaulted,json=FInt64Defaulted,def=64" json:"F_Int64_defaulted,omitempty"` + F_Fixed32Defaulted *uint32 `protobuf:"fixed32,43,opt,name=F_Fixed32_defaulted,json=FFixed32Defaulted,def=320" json:"F_Fixed32_defaulted,omitempty"` + F_Fixed64Defaulted *uint64 `protobuf:"fixed64,44,opt,name=F_Fixed64_defaulted,json=FFixed64Defaulted,def=640" json:"F_Fixed64_defaulted,omitempty"` + F_Uint32Defaulted *uint32 `protobuf:"varint,45,opt,name=F_Uint32_defaulted,json=FUint32Defaulted,def=3200" json:"F_Uint32_defaulted,omitempty"` + F_Uint64Defaulted *uint64 `protobuf:"varint,46,opt,name=F_Uint64_defaulted,json=FUint64Defaulted,def=6400" json:"F_Uint64_defaulted,omitempty"` + F_FloatDefaulted *float32 `protobuf:"fixed32,47,opt,name=F_Float_defaulted,json=FFloatDefaulted,def=314159" json:"F_Float_defaulted,omitempty"` + F_DoubleDefaulted *float64 `protobuf:"fixed64,48,opt,name=F_Double_defaulted,json=FDoubleDefaulted,def=271828" json:"F_Double_defaulted,omitempty"` + F_StringDefaulted *string `protobuf:"bytes,49,opt,name=F_String_defaulted,json=FStringDefaulted,def=hello, \"world!\"\n" json:"F_String_defaulted,omitempty"` + F_BytesDefaulted []byte `protobuf:"bytes,401,opt,name=F_Bytes_defaulted,json=FBytesDefaulted,def=Bignose" json:"F_Bytes_defaulted,omitempty"` + F_Sint32Defaulted *int32 `protobuf:"zigzag32,402,opt,name=F_Sint32_defaulted,json=FSint32Defaulted,def=-32" json:"F_Sint32_defaulted,omitempty"` + F_Sint64Defaulted *int64 `protobuf:"zigzag64,403,opt,name=F_Sint64_defaulted,json=FSint64Defaulted,def=-64" json:"F_Sint64_defaulted,omitempty"` + // Packed repeated fields (no string or bytes). + F_BoolRepeatedPacked []bool `protobuf:"varint,50,rep,packed,name=F_Bool_repeated_packed,json=FBoolRepeatedPacked" json:"F_Bool_repeated_packed,omitempty"` + F_Int32RepeatedPacked []int32 `protobuf:"varint,51,rep,packed,name=F_Int32_repeated_packed,json=FInt32RepeatedPacked" json:"F_Int32_repeated_packed,omitempty"` + F_Int64RepeatedPacked []int64 `protobuf:"varint,52,rep,packed,name=F_Int64_repeated_packed,json=FInt64RepeatedPacked" json:"F_Int64_repeated_packed,omitempty"` + F_Fixed32RepeatedPacked []uint32 `protobuf:"fixed32,53,rep,packed,name=F_Fixed32_repeated_packed,json=FFixed32RepeatedPacked" json:"F_Fixed32_repeated_packed,omitempty"` + F_Fixed64RepeatedPacked []uint64 `protobuf:"fixed64,54,rep,packed,name=F_Fixed64_repeated_packed,json=FFixed64RepeatedPacked" json:"F_Fixed64_repeated_packed,omitempty"` + F_Uint32RepeatedPacked []uint32 `protobuf:"varint,55,rep,packed,name=F_Uint32_repeated_packed,json=FUint32RepeatedPacked" json:"F_Uint32_repeated_packed,omitempty"` + F_Uint64RepeatedPacked []uint64 `protobuf:"varint,56,rep,packed,name=F_Uint64_repeated_packed,json=FUint64RepeatedPacked" json:"F_Uint64_repeated_packed,omitempty"` + F_FloatRepeatedPacked []float32 `protobuf:"fixed32,57,rep,packed,name=F_Float_repeated_packed,json=FFloatRepeatedPacked" json:"F_Float_repeated_packed,omitempty"` + F_DoubleRepeatedPacked []float64 `protobuf:"fixed64,58,rep,packed,name=F_Double_repeated_packed,json=FDoubleRepeatedPacked" json:"F_Double_repeated_packed,omitempty"` + F_Sint32RepeatedPacked []int32 `protobuf:"zigzag32,502,rep,packed,name=F_Sint32_repeated_packed,json=FSint32RepeatedPacked" json:"F_Sint32_repeated_packed,omitempty"` + F_Sint64RepeatedPacked []int64 `protobuf:"zigzag64,503,rep,packed,name=F_Sint64_repeated_packed,json=FSint64RepeatedPacked" json:"F_Sint64_repeated_packed,omitempty"` + Requiredgroup *GoTest_RequiredGroup `protobuf:"group,70,req,name=RequiredGroup,json=requiredgroup" json:"requiredgroup,omitempty"` + Repeatedgroup []*GoTest_RepeatedGroup `protobuf:"group,80,rep,name=RepeatedGroup,json=repeatedgroup" json:"repeatedgroup,omitempty"` + Optionalgroup *GoTest_OptionalGroup `protobuf:"group,90,opt,name=OptionalGroup,json=optionalgroup" json:"optionalgroup,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *GoTest) Reset() { *m = GoTest{} } +func (m *GoTest) String() string { return proto.CompactTextString(m) } +func (*GoTest) ProtoMessage() {} +func (*GoTest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } + +const Default_GoTest_F_BoolDefaulted bool = true +const Default_GoTest_F_Int32Defaulted int32 = 32 +const Default_GoTest_F_Int64Defaulted int64 = 64 +const Default_GoTest_F_Fixed32Defaulted uint32 = 320 +const Default_GoTest_F_Fixed64Defaulted uint64 = 640 +const Default_GoTest_F_Uint32Defaulted uint32 = 3200 +const Default_GoTest_F_Uint64Defaulted uint64 = 6400 +const Default_GoTest_F_FloatDefaulted float32 = 314159 +const Default_GoTest_F_DoubleDefaulted float64 = 271828 +const Default_GoTest_F_StringDefaulted string = "hello, \"world!\"\n" + +var Default_GoTest_F_BytesDefaulted []byte = []byte("Bignose") + +const Default_GoTest_F_Sint32Defaulted int32 = -32 +const Default_GoTest_F_Sint64Defaulted int64 = -64 + +func (m *GoTest) GetKind() GoTest_KIND { + if m != nil && m.Kind != nil { + return *m.Kind + } + return GoTest_VOID +} + +func (m *GoTest) GetTable() string { + if m != nil && m.Table != nil { + return *m.Table + } + return "" +} + +func (m *GoTest) GetParam() int32 { + if m != nil && m.Param != nil { + return *m.Param + } + return 0 +} + +func (m *GoTest) GetRequiredField() *GoTestField { + if m != nil { + return m.RequiredField + } + return nil +} + +func (m *GoTest) GetRepeatedField() []*GoTestField { + if m != nil { + return m.RepeatedField + } + return nil +} + +func (m *GoTest) GetOptionalField() *GoTestField { + if m != nil { + return m.OptionalField + } + return nil +} + +func (m *GoTest) GetF_BoolRequired() bool { + if m != nil && m.F_BoolRequired != nil { + return *m.F_BoolRequired + } + return false +} + +func (m *GoTest) GetF_Int32Required() int32 { + if m != nil && m.F_Int32Required != nil { + return *m.F_Int32Required + } + return 0 +} + +func (m *GoTest) GetF_Int64Required() int64 { + if m != nil && m.F_Int64Required != nil { + return *m.F_Int64Required + } + return 0 +} + +func (m *GoTest) GetF_Fixed32Required() uint32 { + if m != nil && m.F_Fixed32Required != nil { + return *m.F_Fixed32Required + } + return 0 +} + +func (m *GoTest) GetF_Fixed64Required() uint64 { + if m != nil && m.F_Fixed64Required != nil { + return *m.F_Fixed64Required + } + return 0 +} + +func (m *GoTest) GetF_Uint32Required() uint32 { + if m != nil && m.F_Uint32Required != nil { + return *m.F_Uint32Required + } + return 0 +} + +func (m *GoTest) GetF_Uint64Required() uint64 { + if m != nil && m.F_Uint64Required != nil { + return *m.F_Uint64Required + } + return 0 +} + +func (m *GoTest) GetF_FloatRequired() float32 { + if m != nil && m.F_FloatRequired != nil { + return *m.F_FloatRequired + } + return 0 +} + +func (m *GoTest) GetF_DoubleRequired() float64 { + if m != nil && m.F_DoubleRequired != nil { + return *m.F_DoubleRequired + } + return 0 +} + +func (m *GoTest) GetF_StringRequired() string { + if m != nil && m.F_StringRequired != nil { + return *m.F_StringRequired + } + return "" +} + +func (m *GoTest) GetF_BytesRequired() []byte { + if m != nil { + return m.F_BytesRequired + } + return nil +} + +func (m *GoTest) GetF_Sint32Required() int32 { + if m != nil && m.F_Sint32Required != nil { + return *m.F_Sint32Required + } + return 0 +} + +func (m *GoTest) GetF_Sint64Required() int64 { + if m != nil && m.F_Sint64Required != nil { + return *m.F_Sint64Required + } + return 0 +} + +func (m *GoTest) GetF_BoolRepeated() []bool { + if m != nil { + return m.F_BoolRepeated + } + return nil +} + +func (m *GoTest) GetF_Int32Repeated() []int32 { + if m != nil { + return m.F_Int32Repeated + } + return nil +} + +func (m *GoTest) GetF_Int64Repeated() []int64 { + if m != nil { + return m.F_Int64Repeated + } + return nil +} + +func (m *GoTest) GetF_Fixed32Repeated() []uint32 { + if m != nil { + return m.F_Fixed32Repeated + } + return nil +} + +func (m *GoTest) GetF_Fixed64Repeated() []uint64 { + if m != nil { + return m.F_Fixed64Repeated + } + return nil +} + +func (m *GoTest) GetF_Uint32Repeated() []uint32 { + if m != nil { + return m.F_Uint32Repeated + } + return nil +} + +func (m *GoTest) GetF_Uint64Repeated() []uint64 { + if m != nil { + return m.F_Uint64Repeated + } + return nil +} + +func (m *GoTest) GetF_FloatRepeated() []float32 { + if m != nil { + return m.F_FloatRepeated + } + return nil +} + +func (m *GoTest) GetF_DoubleRepeated() []float64 { + if m != nil { + return m.F_DoubleRepeated + } + return nil +} + +func (m *GoTest) GetF_StringRepeated() []string { + if m != nil { + return m.F_StringRepeated + } + return nil +} + +func (m *GoTest) GetF_BytesRepeated() [][]byte { + if m != nil { + return m.F_BytesRepeated + } + return nil +} + +func (m *GoTest) GetF_Sint32Repeated() []int32 { + if m != nil { + return m.F_Sint32Repeated + } + return nil +} + +func (m *GoTest) GetF_Sint64Repeated() []int64 { + if m != nil { + return m.F_Sint64Repeated + } + return nil +} + +func (m *GoTest) GetF_BoolOptional() bool { + if m != nil && m.F_BoolOptional != nil { + return *m.F_BoolOptional + } + return false +} + +func (m *GoTest) GetF_Int32Optional() int32 { + if m != nil && m.F_Int32Optional != nil { + return *m.F_Int32Optional + } + return 0 +} + +func (m *GoTest) GetF_Int64Optional() int64 { + if m != nil && m.F_Int64Optional != nil { + return *m.F_Int64Optional + } + return 0 +} + +func (m *GoTest) GetF_Fixed32Optional() uint32 { + if m != nil && m.F_Fixed32Optional != nil { + return *m.F_Fixed32Optional + } + return 0 +} + +func (m *GoTest) GetF_Fixed64Optional() uint64 { + if m != nil && m.F_Fixed64Optional != nil { + return *m.F_Fixed64Optional + } + return 0 +} + +func (m *GoTest) GetF_Uint32Optional() uint32 { + if m != nil && m.F_Uint32Optional != nil { + return *m.F_Uint32Optional + } + return 0 +} + +func (m *GoTest) GetF_Uint64Optional() uint64 { + if m != nil && m.F_Uint64Optional != nil { + return *m.F_Uint64Optional + } + return 0 +} + +func (m *GoTest) GetF_FloatOptional() float32 { + if m != nil && m.F_FloatOptional != nil { + return *m.F_FloatOptional + } + return 0 +} + +func (m *GoTest) GetF_DoubleOptional() float64 { + if m != nil && m.F_DoubleOptional != nil { + return *m.F_DoubleOptional + } + return 0 +} + +func (m *GoTest) GetF_StringOptional() string { + if m != nil && m.F_StringOptional != nil { + return *m.F_StringOptional + } + return "" +} + +func (m *GoTest) GetF_BytesOptional() []byte { + if m != nil { + return m.F_BytesOptional + } + return nil +} + +func (m *GoTest) GetF_Sint32Optional() int32 { + if m != nil && m.F_Sint32Optional != nil { + return *m.F_Sint32Optional + } + return 0 +} + +func (m *GoTest) GetF_Sint64Optional() int64 { + if m != nil && m.F_Sint64Optional != nil { + return *m.F_Sint64Optional + } + return 0 +} + +func (m *GoTest) GetF_BoolDefaulted() bool { + if m != nil && m.F_BoolDefaulted != nil { + return *m.F_BoolDefaulted + } + return Default_GoTest_F_BoolDefaulted +} + +func (m *GoTest) GetF_Int32Defaulted() int32 { + if m != nil && m.F_Int32Defaulted != nil { + return *m.F_Int32Defaulted + } + return Default_GoTest_F_Int32Defaulted +} + +func (m *GoTest) GetF_Int64Defaulted() int64 { + if m != nil && m.F_Int64Defaulted != nil { + return *m.F_Int64Defaulted + } + return Default_GoTest_F_Int64Defaulted +} + +func (m *GoTest) GetF_Fixed32Defaulted() uint32 { + if m != nil && m.F_Fixed32Defaulted != nil { + return *m.F_Fixed32Defaulted + } + return Default_GoTest_F_Fixed32Defaulted +} + +func (m *GoTest) GetF_Fixed64Defaulted() uint64 { + if m != nil && m.F_Fixed64Defaulted != nil { + return *m.F_Fixed64Defaulted + } + return Default_GoTest_F_Fixed64Defaulted +} + +func (m *GoTest) GetF_Uint32Defaulted() uint32 { + if m != nil && m.F_Uint32Defaulted != nil { + return *m.F_Uint32Defaulted + } + return Default_GoTest_F_Uint32Defaulted +} + +func (m *GoTest) GetF_Uint64Defaulted() uint64 { + if m != nil && m.F_Uint64Defaulted != nil { + return *m.F_Uint64Defaulted + } + return Default_GoTest_F_Uint64Defaulted +} + +func (m *GoTest) GetF_FloatDefaulted() float32 { + if m != nil && m.F_FloatDefaulted != nil { + return *m.F_FloatDefaulted + } + return Default_GoTest_F_FloatDefaulted +} + +func (m *GoTest) GetF_DoubleDefaulted() float64 { + if m != nil && m.F_DoubleDefaulted != nil { + return *m.F_DoubleDefaulted + } + return Default_GoTest_F_DoubleDefaulted +} + +func (m *GoTest) GetF_StringDefaulted() string { + if m != nil && m.F_StringDefaulted != nil { + return *m.F_StringDefaulted + } + return Default_GoTest_F_StringDefaulted +} + +func (m *GoTest) GetF_BytesDefaulted() []byte { + if m != nil && m.F_BytesDefaulted != nil { + return m.F_BytesDefaulted + } + return append([]byte(nil), Default_GoTest_F_BytesDefaulted...) +} + +func (m *GoTest) GetF_Sint32Defaulted() int32 { + if m != nil && m.F_Sint32Defaulted != nil { + return *m.F_Sint32Defaulted + } + return Default_GoTest_F_Sint32Defaulted +} + +func (m *GoTest) GetF_Sint64Defaulted() int64 { + if m != nil && m.F_Sint64Defaulted != nil { + return *m.F_Sint64Defaulted + } + return Default_GoTest_F_Sint64Defaulted +} + +func (m *GoTest) GetF_BoolRepeatedPacked() []bool { + if m != nil { + return m.F_BoolRepeatedPacked + } + return nil +} + +func (m *GoTest) GetF_Int32RepeatedPacked() []int32 { + if m != nil { + return m.F_Int32RepeatedPacked + } + return nil +} + +func (m *GoTest) GetF_Int64RepeatedPacked() []int64 { + if m != nil { + return m.F_Int64RepeatedPacked + } + return nil +} + +func (m *GoTest) GetF_Fixed32RepeatedPacked() []uint32 { + if m != nil { + return m.F_Fixed32RepeatedPacked + } + return nil +} + +func (m *GoTest) GetF_Fixed64RepeatedPacked() []uint64 { + if m != nil { + return m.F_Fixed64RepeatedPacked + } + return nil +} + +func (m *GoTest) GetF_Uint32RepeatedPacked() []uint32 { + if m != nil { + return m.F_Uint32RepeatedPacked + } + return nil +} + +func (m *GoTest) GetF_Uint64RepeatedPacked() []uint64 { + if m != nil { + return m.F_Uint64RepeatedPacked + } + return nil +} + +func (m *GoTest) GetF_FloatRepeatedPacked() []float32 { + if m != nil { + return m.F_FloatRepeatedPacked + } + return nil +} + +func (m *GoTest) GetF_DoubleRepeatedPacked() []float64 { + if m != nil { + return m.F_DoubleRepeatedPacked + } + return nil +} + +func (m *GoTest) GetF_Sint32RepeatedPacked() []int32 { + if m != nil { + return m.F_Sint32RepeatedPacked + } + return nil +} + +func (m *GoTest) GetF_Sint64RepeatedPacked() []int64 { + if m != nil { + return m.F_Sint64RepeatedPacked + } + return nil +} + +func (m *GoTest) GetRequiredgroup() *GoTest_RequiredGroup { + if m != nil { + return m.Requiredgroup + } + return nil +} + +func (m *GoTest) GetRepeatedgroup() []*GoTest_RepeatedGroup { + if m != nil { + return m.Repeatedgroup + } + return nil +} + +func (m *GoTest) GetOptionalgroup() *GoTest_OptionalGroup { + if m != nil { + return m.Optionalgroup + } + return nil +} + +// Required, repeated, and optional groups. +type GoTest_RequiredGroup struct { + RequiredField *string `protobuf:"bytes,71,req,name=RequiredField" json:"RequiredField,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *GoTest_RequiredGroup) Reset() { *m = GoTest_RequiredGroup{} } +func (m *GoTest_RequiredGroup) String() string { return proto.CompactTextString(m) } +func (*GoTest_RequiredGroup) ProtoMessage() {} +func (*GoTest_RequiredGroup) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2, 0} } + +func (m *GoTest_RequiredGroup) GetRequiredField() string { + if m != nil && m.RequiredField != nil { + return *m.RequiredField + } + return "" +} + +type GoTest_RepeatedGroup struct { + RequiredField *string `protobuf:"bytes,81,req,name=RequiredField" json:"RequiredField,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *GoTest_RepeatedGroup) Reset() { *m = GoTest_RepeatedGroup{} } +func (m *GoTest_RepeatedGroup) String() string { return proto.CompactTextString(m) } +func (*GoTest_RepeatedGroup) ProtoMessage() {} +func (*GoTest_RepeatedGroup) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2, 1} } + +func (m *GoTest_RepeatedGroup) GetRequiredField() string { + if m != nil && m.RequiredField != nil { + return *m.RequiredField + } + return "" +} + +type GoTest_OptionalGroup struct { + RequiredField *string `protobuf:"bytes,91,req,name=RequiredField" json:"RequiredField,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *GoTest_OptionalGroup) Reset() { *m = GoTest_OptionalGroup{} } +func (m *GoTest_OptionalGroup) String() string { return proto.CompactTextString(m) } +func (*GoTest_OptionalGroup) ProtoMessage() {} +func (*GoTest_OptionalGroup) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2, 2} } + +func (m *GoTest_OptionalGroup) GetRequiredField() string { + if m != nil && m.RequiredField != nil { + return *m.RequiredField + } + return "" +} + +// For testing a group containing a required field. +type GoTestRequiredGroupField struct { + Group *GoTestRequiredGroupField_Group `protobuf:"group,1,req,name=Group,json=group" json:"group,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *GoTestRequiredGroupField) Reset() { *m = GoTestRequiredGroupField{} } +func (m *GoTestRequiredGroupField) String() string { return proto.CompactTextString(m) } +func (*GoTestRequiredGroupField) ProtoMessage() {} +func (*GoTestRequiredGroupField) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } + +func (m *GoTestRequiredGroupField) GetGroup() *GoTestRequiredGroupField_Group { + if m != nil { + return m.Group + } + return nil +} + +type GoTestRequiredGroupField_Group struct { + Field *int32 `protobuf:"varint,2,req,name=Field" json:"Field,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *GoTestRequiredGroupField_Group) Reset() { *m = GoTestRequiredGroupField_Group{} } +func (m *GoTestRequiredGroupField_Group) String() string { return proto.CompactTextString(m) } +func (*GoTestRequiredGroupField_Group) ProtoMessage() {} +func (*GoTestRequiredGroupField_Group) Descriptor() ([]byte, []int) { + return fileDescriptor0, []int{3, 0} +} + +func (m *GoTestRequiredGroupField_Group) GetField() int32 { + if m != nil && m.Field != nil { + return *m.Field + } + return 0 +} + +// For testing skipping of unrecognized fields. +// Numbers are all big, larger than tag numbers in GoTestField, +// the message used in the corresponding test. +type GoSkipTest struct { + SkipInt32 *int32 `protobuf:"varint,11,req,name=skip_int32,json=skipInt32" json:"skip_int32,omitempty"` + SkipFixed32 *uint32 `protobuf:"fixed32,12,req,name=skip_fixed32,json=skipFixed32" json:"skip_fixed32,omitempty"` + SkipFixed64 *uint64 `protobuf:"fixed64,13,req,name=skip_fixed64,json=skipFixed64" json:"skip_fixed64,omitempty"` + SkipString *string `protobuf:"bytes,14,req,name=skip_string,json=skipString" json:"skip_string,omitempty"` + Skipgroup *GoSkipTest_SkipGroup `protobuf:"group,15,req,name=SkipGroup,json=skipgroup" json:"skipgroup,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *GoSkipTest) Reset() { *m = GoSkipTest{} } +func (m *GoSkipTest) String() string { return proto.CompactTextString(m) } +func (*GoSkipTest) ProtoMessage() {} +func (*GoSkipTest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} } + +func (m *GoSkipTest) GetSkipInt32() int32 { + if m != nil && m.SkipInt32 != nil { + return *m.SkipInt32 + } + return 0 +} + +func (m *GoSkipTest) GetSkipFixed32() uint32 { + if m != nil && m.SkipFixed32 != nil { + return *m.SkipFixed32 + } + return 0 +} + +func (m *GoSkipTest) GetSkipFixed64() uint64 { + if m != nil && m.SkipFixed64 != nil { + return *m.SkipFixed64 + } + return 0 +} + +func (m *GoSkipTest) GetSkipString() string { + if m != nil && m.SkipString != nil { + return *m.SkipString + } + return "" +} + +func (m *GoSkipTest) GetSkipgroup() *GoSkipTest_SkipGroup { + if m != nil { + return m.Skipgroup + } + return nil +} + +type GoSkipTest_SkipGroup struct { + GroupInt32 *int32 `protobuf:"varint,16,req,name=group_int32,json=groupInt32" json:"group_int32,omitempty"` + GroupString *string `protobuf:"bytes,17,req,name=group_string,json=groupString" json:"group_string,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *GoSkipTest_SkipGroup) Reset() { *m = GoSkipTest_SkipGroup{} } +func (m *GoSkipTest_SkipGroup) String() string { return proto.CompactTextString(m) } +func (*GoSkipTest_SkipGroup) ProtoMessage() {} +func (*GoSkipTest_SkipGroup) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4, 0} } + +func (m *GoSkipTest_SkipGroup) GetGroupInt32() int32 { + if m != nil && m.GroupInt32 != nil { + return *m.GroupInt32 + } + return 0 +} + +func (m *GoSkipTest_SkipGroup) GetGroupString() string { + if m != nil && m.GroupString != nil { + return *m.GroupString + } + return "" +} + +// For testing packed/non-packed decoder switching. +// A serialized instance of one should be deserializable as the other. +type NonPackedTest struct { + A []int32 `protobuf:"varint,1,rep,name=a" json:"a,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *NonPackedTest) Reset() { *m = NonPackedTest{} } +func (m *NonPackedTest) String() string { return proto.CompactTextString(m) } +func (*NonPackedTest) ProtoMessage() {} +func (*NonPackedTest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} } + +func (m *NonPackedTest) GetA() []int32 { + if m != nil { + return m.A + } + return nil +} + +type PackedTest struct { + B []int32 `protobuf:"varint,1,rep,packed,name=b" json:"b,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *PackedTest) Reset() { *m = PackedTest{} } +func (m *PackedTest) String() string { return proto.CompactTextString(m) } +func (*PackedTest) ProtoMessage() {} +func (*PackedTest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} } + +func (m *PackedTest) GetB() []int32 { + if m != nil { + return m.B + } + return nil +} + +type MaxTag struct { + // Maximum possible tag number. + LastField *string `protobuf:"bytes,536870911,opt,name=last_field,json=lastField" json:"last_field,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *MaxTag) Reset() { *m = MaxTag{} } +func (m *MaxTag) String() string { return proto.CompactTextString(m) } +func (*MaxTag) ProtoMessage() {} +func (*MaxTag) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} } + +func (m *MaxTag) GetLastField() string { + if m != nil && m.LastField != nil { + return *m.LastField + } + return "" +} + +type OldMessage struct { + Nested *OldMessage_Nested `protobuf:"bytes,1,opt,name=nested" json:"nested,omitempty"` + Num *int32 `protobuf:"varint,2,opt,name=num" json:"num,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *OldMessage) Reset() { *m = OldMessage{} } +func (m *OldMessage) String() string { return proto.CompactTextString(m) } +func (*OldMessage) ProtoMessage() {} +func (*OldMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} } + +func (m *OldMessage) GetNested() *OldMessage_Nested { + if m != nil { + return m.Nested + } + return nil +} + +func (m *OldMessage) GetNum() int32 { + if m != nil && m.Num != nil { + return *m.Num + } + return 0 +} + +type OldMessage_Nested struct { + Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *OldMessage_Nested) Reset() { *m = OldMessage_Nested{} } +func (m *OldMessage_Nested) String() string { return proto.CompactTextString(m) } +func (*OldMessage_Nested) ProtoMessage() {} +func (*OldMessage_Nested) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8, 0} } + +func (m *OldMessage_Nested) GetName() string { + if m != nil && m.Name != nil { + return *m.Name + } + return "" +} + +// NewMessage is wire compatible with OldMessage; +// imagine it as a future version. +type NewMessage struct { + Nested *NewMessage_Nested `protobuf:"bytes,1,opt,name=nested" json:"nested,omitempty"` + // This is an int32 in OldMessage. + Num *int64 `protobuf:"varint,2,opt,name=num" json:"num,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *NewMessage) Reset() { *m = NewMessage{} } +func (m *NewMessage) String() string { return proto.CompactTextString(m) } +func (*NewMessage) ProtoMessage() {} +func (*NewMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} } + +func (m *NewMessage) GetNested() *NewMessage_Nested { + if m != nil { + return m.Nested + } + return nil +} + +func (m *NewMessage) GetNum() int64 { + if m != nil && m.Num != nil { + return *m.Num + } + return 0 +} + +type NewMessage_Nested struct { + Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + FoodGroup *string `protobuf:"bytes,2,opt,name=food_group,json=foodGroup" json:"food_group,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *NewMessage_Nested) Reset() { *m = NewMessage_Nested{} } +func (m *NewMessage_Nested) String() string { return proto.CompactTextString(m) } +func (*NewMessage_Nested) ProtoMessage() {} +func (*NewMessage_Nested) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9, 0} } + +func (m *NewMessage_Nested) GetName() string { + if m != nil && m.Name != nil { + return *m.Name + } + return "" +} + +func (m *NewMessage_Nested) GetFoodGroup() string { + if m != nil && m.FoodGroup != nil { + return *m.FoodGroup + } + return "" +} + +type InnerMessage struct { + Host *string `protobuf:"bytes,1,req,name=host" json:"host,omitempty"` + Port *int32 `protobuf:"varint,2,opt,name=port,def=4000" json:"port,omitempty"` + Connected *bool `protobuf:"varint,3,opt,name=connected" json:"connected,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *InnerMessage) Reset() { *m = InnerMessage{} } +func (m *InnerMessage) String() string { return proto.CompactTextString(m) } +func (*InnerMessage) ProtoMessage() {} +func (*InnerMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} } + +const Default_InnerMessage_Port int32 = 4000 + +func (m *InnerMessage) GetHost() string { + if m != nil && m.Host != nil { + return *m.Host + } + return "" +} + +func (m *InnerMessage) GetPort() int32 { + if m != nil && m.Port != nil { + return *m.Port + } + return Default_InnerMessage_Port +} + +func (m *InnerMessage) GetConnected() bool { + if m != nil && m.Connected != nil { + return *m.Connected + } + return false +} + +type OtherMessage struct { + Key *int64 `protobuf:"varint,1,opt,name=key" json:"key,omitempty"` + Value []byte `protobuf:"bytes,2,opt,name=value" json:"value,omitempty"` + Weight *float32 `protobuf:"fixed32,3,opt,name=weight" json:"weight,omitempty"` + Inner *InnerMessage `protobuf:"bytes,4,opt,name=inner" json:"inner,omitempty"` + proto.XXX_InternalExtensions `json:"-"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *OtherMessage) Reset() { *m = OtherMessage{} } +func (m *OtherMessage) String() string { return proto.CompactTextString(m) } +func (*OtherMessage) ProtoMessage() {} +func (*OtherMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} } + +var extRange_OtherMessage = []proto.ExtensionRange{ + {100, 536870911}, +} + +func (*OtherMessage) ExtensionRangeArray() []proto.ExtensionRange { + return extRange_OtherMessage +} + +func (m *OtherMessage) GetKey() int64 { + if m != nil && m.Key != nil { + return *m.Key + } + return 0 +} + +func (m *OtherMessage) GetValue() []byte { + if m != nil { + return m.Value + } + return nil +} + +func (m *OtherMessage) GetWeight() float32 { + if m != nil && m.Weight != nil { + return *m.Weight + } + return 0 +} + +func (m *OtherMessage) GetInner() *InnerMessage { + if m != nil { + return m.Inner + } + return nil +} + +type RequiredInnerMessage struct { + LeoFinallyWonAnOscar *InnerMessage `protobuf:"bytes,1,req,name=leo_finally_won_an_oscar,json=leoFinallyWonAnOscar" json:"leo_finally_won_an_oscar,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *RequiredInnerMessage) Reset() { *m = RequiredInnerMessage{} } +func (m *RequiredInnerMessage) String() string { return proto.CompactTextString(m) } +func (*RequiredInnerMessage) ProtoMessage() {} +func (*RequiredInnerMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{12} } + +func (m *RequiredInnerMessage) GetLeoFinallyWonAnOscar() *InnerMessage { + if m != nil { + return m.LeoFinallyWonAnOscar + } + return nil +} + +type MyMessage struct { + Count *int32 `protobuf:"varint,1,req,name=count" json:"count,omitempty"` + Name *string `protobuf:"bytes,2,opt,name=name" json:"name,omitempty"` + Quote *string `protobuf:"bytes,3,opt,name=quote" json:"quote,omitempty"` + Pet []string `protobuf:"bytes,4,rep,name=pet" json:"pet,omitempty"` + Inner *InnerMessage `protobuf:"bytes,5,opt,name=inner" json:"inner,omitempty"` + Others []*OtherMessage `protobuf:"bytes,6,rep,name=others" json:"others,omitempty"` + WeMustGoDeeper *RequiredInnerMessage `protobuf:"bytes,13,opt,name=we_must_go_deeper,json=weMustGoDeeper" json:"we_must_go_deeper,omitempty"` + RepInner []*InnerMessage `protobuf:"bytes,12,rep,name=rep_inner,json=repInner" json:"rep_inner,omitempty"` + Bikeshed *MyMessage_Color `protobuf:"varint,7,opt,name=bikeshed,enum=testdata.MyMessage_Color" json:"bikeshed,omitempty"` + Somegroup *MyMessage_SomeGroup `protobuf:"group,8,opt,name=SomeGroup,json=somegroup" json:"somegroup,omitempty"` + // This field becomes [][]byte in the generated code. + RepBytes [][]byte `protobuf:"bytes,10,rep,name=rep_bytes,json=repBytes" json:"rep_bytes,omitempty"` + Bigfloat *float64 `protobuf:"fixed64,11,opt,name=bigfloat" json:"bigfloat,omitempty"` + proto.XXX_InternalExtensions `json:"-"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *MyMessage) Reset() { *m = MyMessage{} } +func (m *MyMessage) String() string { return proto.CompactTextString(m) } +func (*MyMessage) ProtoMessage() {} +func (*MyMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{13} } + +var extRange_MyMessage = []proto.ExtensionRange{ + {100, 536870911}, +} + +func (*MyMessage) ExtensionRangeArray() []proto.ExtensionRange { + return extRange_MyMessage +} + +func (m *MyMessage) GetCount() int32 { + if m != nil && m.Count != nil { + return *m.Count + } + return 0 +} + +func (m *MyMessage) GetName() string { + if m != nil && m.Name != nil { + return *m.Name + } + return "" +} + +func (m *MyMessage) GetQuote() string { + if m != nil && m.Quote != nil { + return *m.Quote + } + return "" +} + +func (m *MyMessage) GetPet() []string { + if m != nil { + return m.Pet + } + return nil +} + +func (m *MyMessage) GetInner() *InnerMessage { + if m != nil { + return m.Inner + } + return nil +} + +func (m *MyMessage) GetOthers() []*OtherMessage { + if m != nil { + return m.Others + } + return nil +} + +func (m *MyMessage) GetWeMustGoDeeper() *RequiredInnerMessage { + if m != nil { + return m.WeMustGoDeeper + } + return nil +} + +func (m *MyMessage) GetRepInner() []*InnerMessage { + if m != nil { + return m.RepInner + } + return nil +} + +func (m *MyMessage) GetBikeshed() MyMessage_Color { + if m != nil && m.Bikeshed != nil { + return *m.Bikeshed + } + return MyMessage_RED +} + +func (m *MyMessage) GetSomegroup() *MyMessage_SomeGroup { + if m != nil { + return m.Somegroup + } + return nil +} + +func (m *MyMessage) GetRepBytes() [][]byte { + if m != nil { + return m.RepBytes + } + return nil +} + +func (m *MyMessage) GetBigfloat() float64 { + if m != nil && m.Bigfloat != nil { + return *m.Bigfloat + } + return 0 +} + +type MyMessage_SomeGroup struct { + GroupField *int32 `protobuf:"varint,9,opt,name=group_field,json=groupField" json:"group_field,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *MyMessage_SomeGroup) Reset() { *m = MyMessage_SomeGroup{} } +func (m *MyMessage_SomeGroup) String() string { return proto.CompactTextString(m) } +func (*MyMessage_SomeGroup) ProtoMessage() {} +func (*MyMessage_SomeGroup) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{13, 0} } + +func (m *MyMessage_SomeGroup) GetGroupField() int32 { + if m != nil && m.GroupField != nil { + return *m.GroupField + } + return 0 +} + +type Ext struct { + Data *string `protobuf:"bytes,1,opt,name=data" json:"data,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *Ext) Reset() { *m = Ext{} } +func (m *Ext) String() string { return proto.CompactTextString(m) } +func (*Ext) ProtoMessage() {} +func (*Ext) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{14} } + +func (m *Ext) GetData() string { + if m != nil && m.Data != nil { + return *m.Data + } + return "" +} + +var E_Ext_More = &proto.ExtensionDesc{ + ExtendedType: (*MyMessage)(nil), + ExtensionType: (*Ext)(nil), + Field: 103, + Name: "testdata.Ext.more", + Tag: "bytes,103,opt,name=more", + Filename: "test.proto", +} + +var E_Ext_Text = &proto.ExtensionDesc{ + ExtendedType: (*MyMessage)(nil), + ExtensionType: (*string)(nil), + Field: 104, + Name: "testdata.Ext.text", + Tag: "bytes,104,opt,name=text", + Filename: "test.proto", +} + +var E_Ext_Number = &proto.ExtensionDesc{ + ExtendedType: (*MyMessage)(nil), + ExtensionType: (*int32)(nil), + Field: 105, + Name: "testdata.Ext.number", + Tag: "varint,105,opt,name=number", + Filename: "test.proto", +} + +type ComplexExtension struct { + First *int32 `protobuf:"varint,1,opt,name=first" json:"first,omitempty"` + Second *int32 `protobuf:"varint,2,opt,name=second" json:"second,omitempty"` + Third []int32 `protobuf:"varint,3,rep,name=third" json:"third,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *ComplexExtension) Reset() { *m = ComplexExtension{} } +func (m *ComplexExtension) String() string { return proto.CompactTextString(m) } +func (*ComplexExtension) ProtoMessage() {} +func (*ComplexExtension) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{15} } + +func (m *ComplexExtension) GetFirst() int32 { + if m != nil && m.First != nil { + return *m.First + } + return 0 +} + +func (m *ComplexExtension) GetSecond() int32 { + if m != nil && m.Second != nil { + return *m.Second + } + return 0 +} + +func (m *ComplexExtension) GetThird() []int32 { + if m != nil { + return m.Third + } + return nil +} + +type DefaultsMessage struct { + proto.XXX_InternalExtensions `json:"-"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *DefaultsMessage) Reset() { *m = DefaultsMessage{} } +func (m *DefaultsMessage) String() string { return proto.CompactTextString(m) } +func (*DefaultsMessage) ProtoMessage() {} +func (*DefaultsMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{16} } + +var extRange_DefaultsMessage = []proto.ExtensionRange{ + {100, 536870911}, +} + +func (*DefaultsMessage) ExtensionRangeArray() []proto.ExtensionRange { + return extRange_DefaultsMessage +} + +type MyMessageSet struct { + proto.XXX_InternalExtensions `json:"-"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *MyMessageSet) Reset() { *m = MyMessageSet{} } +func (m *MyMessageSet) String() string { return proto.CompactTextString(m) } +func (*MyMessageSet) ProtoMessage() {} +func (*MyMessageSet) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{17} } + +func (m *MyMessageSet) Marshal() ([]byte, error) { + return proto.MarshalMessageSet(&m.XXX_InternalExtensions) +} +func (m *MyMessageSet) Unmarshal(buf []byte) error { + return proto.UnmarshalMessageSet(buf, &m.XXX_InternalExtensions) +} +func (m *MyMessageSet) MarshalJSON() ([]byte, error) { + return proto.MarshalMessageSetJSON(&m.XXX_InternalExtensions) +} +func (m *MyMessageSet) UnmarshalJSON(buf []byte) error { + return proto.UnmarshalMessageSetJSON(buf, &m.XXX_InternalExtensions) +} + +// ensure MyMessageSet satisfies proto.Marshaler and proto.Unmarshaler +var _ proto.Marshaler = (*MyMessageSet)(nil) +var _ proto.Unmarshaler = (*MyMessageSet)(nil) + +var extRange_MyMessageSet = []proto.ExtensionRange{ + {100, 2147483646}, +} + +func (*MyMessageSet) ExtensionRangeArray() []proto.ExtensionRange { + return extRange_MyMessageSet +} + +type Empty struct { + XXX_unrecognized []byte `json:"-"` +} + +func (m *Empty) Reset() { *m = Empty{} } +func (m *Empty) String() string { return proto.CompactTextString(m) } +func (*Empty) ProtoMessage() {} +func (*Empty) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{18} } + +type MessageList struct { + Message []*MessageList_Message `protobuf:"group,1,rep,name=Message,json=message" json:"message,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *MessageList) Reset() { *m = MessageList{} } +func (m *MessageList) String() string { return proto.CompactTextString(m) } +func (*MessageList) ProtoMessage() {} +func (*MessageList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{19} } + +func (m *MessageList) GetMessage() []*MessageList_Message { + if m != nil { + return m.Message + } + return nil +} + +type MessageList_Message struct { + Name *string `protobuf:"bytes,2,req,name=name" json:"name,omitempty"` + Count *int32 `protobuf:"varint,3,req,name=count" json:"count,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *MessageList_Message) Reset() { *m = MessageList_Message{} } +func (m *MessageList_Message) String() string { return proto.CompactTextString(m) } +func (*MessageList_Message) ProtoMessage() {} +func (*MessageList_Message) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{19, 0} } + +func (m *MessageList_Message) GetName() string { + if m != nil && m.Name != nil { + return *m.Name + } + return "" +} + +func (m *MessageList_Message) GetCount() int32 { + if m != nil && m.Count != nil { + return *m.Count + } + return 0 +} + +type Strings struct { + StringField *string `protobuf:"bytes,1,opt,name=string_field,json=stringField" json:"string_field,omitempty"` + BytesField []byte `protobuf:"bytes,2,opt,name=bytes_field,json=bytesField" json:"bytes_field,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *Strings) Reset() { *m = Strings{} } +func (m *Strings) String() string { return proto.CompactTextString(m) } +func (*Strings) ProtoMessage() {} +func (*Strings) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{20} } + +func (m *Strings) GetStringField() string { + if m != nil && m.StringField != nil { + return *m.StringField + } + return "" +} + +func (m *Strings) GetBytesField() []byte { + if m != nil { + return m.BytesField + } + return nil +} + +type Defaults struct { + // Default-valued fields of all basic types. + // Same as GoTest, but copied here to make testing easier. + F_Bool *bool `protobuf:"varint,1,opt,name=F_Bool,json=FBool,def=1" json:"F_Bool,omitempty"` + F_Int32 *int32 `protobuf:"varint,2,opt,name=F_Int32,json=FInt32,def=32" json:"F_Int32,omitempty"` + F_Int64 *int64 `protobuf:"varint,3,opt,name=F_Int64,json=FInt64,def=64" json:"F_Int64,omitempty"` + F_Fixed32 *uint32 `protobuf:"fixed32,4,opt,name=F_Fixed32,json=FFixed32,def=320" json:"F_Fixed32,omitempty"` + F_Fixed64 *uint64 `protobuf:"fixed64,5,opt,name=F_Fixed64,json=FFixed64,def=640" json:"F_Fixed64,omitempty"` + F_Uint32 *uint32 `protobuf:"varint,6,opt,name=F_Uint32,json=FUint32,def=3200" json:"F_Uint32,omitempty"` + F_Uint64 *uint64 `protobuf:"varint,7,opt,name=F_Uint64,json=FUint64,def=6400" json:"F_Uint64,omitempty"` + F_Float *float32 `protobuf:"fixed32,8,opt,name=F_Float,json=FFloat,def=314159" json:"F_Float,omitempty"` + F_Double *float64 `protobuf:"fixed64,9,opt,name=F_Double,json=FDouble,def=271828" json:"F_Double,omitempty"` + F_String *string `protobuf:"bytes,10,opt,name=F_String,json=FString,def=hello, \"world!\"\n" json:"F_String,omitempty"` + F_Bytes []byte `protobuf:"bytes,11,opt,name=F_Bytes,json=FBytes,def=Bignose" json:"F_Bytes,omitempty"` + F_Sint32 *int32 `protobuf:"zigzag32,12,opt,name=F_Sint32,json=FSint32,def=-32" json:"F_Sint32,omitempty"` + F_Sint64 *int64 `protobuf:"zigzag64,13,opt,name=F_Sint64,json=FSint64,def=-64" json:"F_Sint64,omitempty"` + F_Enum *Defaults_Color `protobuf:"varint,14,opt,name=F_Enum,json=FEnum,enum=testdata.Defaults_Color,def=1" json:"F_Enum,omitempty"` + // More fields with crazy defaults. + F_Pinf *float32 `protobuf:"fixed32,15,opt,name=F_Pinf,json=FPinf,def=inf" json:"F_Pinf,omitempty"` + F_Ninf *float32 `protobuf:"fixed32,16,opt,name=F_Ninf,json=FNinf,def=-inf" json:"F_Ninf,omitempty"` + F_Nan *float32 `protobuf:"fixed32,17,opt,name=F_Nan,json=FNan,def=nan" json:"F_Nan,omitempty"` + // Sub-message. + Sub *SubDefaults `protobuf:"bytes,18,opt,name=sub" json:"sub,omitempty"` + // Redundant but explicit defaults. + StrZero *string `protobuf:"bytes,19,opt,name=str_zero,json=strZero,def=" json:"str_zero,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *Defaults) Reset() { *m = Defaults{} } +func (m *Defaults) String() string { return proto.CompactTextString(m) } +func (*Defaults) ProtoMessage() {} +func (*Defaults) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{21} } + +const Default_Defaults_F_Bool bool = true +const Default_Defaults_F_Int32 int32 = 32 +const Default_Defaults_F_Int64 int64 = 64 +const Default_Defaults_F_Fixed32 uint32 = 320 +const Default_Defaults_F_Fixed64 uint64 = 640 +const Default_Defaults_F_Uint32 uint32 = 3200 +const Default_Defaults_F_Uint64 uint64 = 6400 +const Default_Defaults_F_Float float32 = 314159 +const Default_Defaults_F_Double float64 = 271828 +const Default_Defaults_F_String string = "hello, \"world!\"\n" + +var Default_Defaults_F_Bytes []byte = []byte("Bignose") + +const Default_Defaults_F_Sint32 int32 = -32 +const Default_Defaults_F_Sint64 int64 = -64 +const Default_Defaults_F_Enum Defaults_Color = Defaults_GREEN + +var Default_Defaults_F_Pinf float32 = float32(math.Inf(1)) +var Default_Defaults_F_Ninf float32 = float32(math.Inf(-1)) +var Default_Defaults_F_Nan float32 = float32(math.NaN()) + +func (m *Defaults) GetF_Bool() bool { + if m != nil && m.F_Bool != nil { + return *m.F_Bool + } + return Default_Defaults_F_Bool +} + +func (m *Defaults) GetF_Int32() int32 { + if m != nil && m.F_Int32 != nil { + return *m.F_Int32 + } + return Default_Defaults_F_Int32 +} + +func (m *Defaults) GetF_Int64() int64 { + if m != nil && m.F_Int64 != nil { + return *m.F_Int64 + } + return Default_Defaults_F_Int64 +} + +func (m *Defaults) GetF_Fixed32() uint32 { + if m != nil && m.F_Fixed32 != nil { + return *m.F_Fixed32 + } + return Default_Defaults_F_Fixed32 +} + +func (m *Defaults) GetF_Fixed64() uint64 { + if m != nil && m.F_Fixed64 != nil { + return *m.F_Fixed64 + } + return Default_Defaults_F_Fixed64 +} + +func (m *Defaults) GetF_Uint32() uint32 { + if m != nil && m.F_Uint32 != nil { + return *m.F_Uint32 + } + return Default_Defaults_F_Uint32 +} + +func (m *Defaults) GetF_Uint64() uint64 { + if m != nil && m.F_Uint64 != nil { + return *m.F_Uint64 + } + return Default_Defaults_F_Uint64 +} + +func (m *Defaults) GetF_Float() float32 { + if m != nil && m.F_Float != nil { + return *m.F_Float + } + return Default_Defaults_F_Float +} + +func (m *Defaults) GetF_Double() float64 { + if m != nil && m.F_Double != nil { + return *m.F_Double + } + return Default_Defaults_F_Double +} + +func (m *Defaults) GetF_String() string { + if m != nil && m.F_String != nil { + return *m.F_String + } + return Default_Defaults_F_String +} + +func (m *Defaults) GetF_Bytes() []byte { + if m != nil && m.F_Bytes != nil { + return m.F_Bytes + } + return append([]byte(nil), Default_Defaults_F_Bytes...) +} + +func (m *Defaults) GetF_Sint32() int32 { + if m != nil && m.F_Sint32 != nil { + return *m.F_Sint32 + } + return Default_Defaults_F_Sint32 +} + +func (m *Defaults) GetF_Sint64() int64 { + if m != nil && m.F_Sint64 != nil { + return *m.F_Sint64 + } + return Default_Defaults_F_Sint64 +} + +func (m *Defaults) GetF_Enum() Defaults_Color { + if m != nil && m.F_Enum != nil { + return *m.F_Enum + } + return Default_Defaults_F_Enum +} + +func (m *Defaults) GetF_Pinf() float32 { + if m != nil && m.F_Pinf != nil { + return *m.F_Pinf + } + return Default_Defaults_F_Pinf +} + +func (m *Defaults) GetF_Ninf() float32 { + if m != nil && m.F_Ninf != nil { + return *m.F_Ninf + } + return Default_Defaults_F_Ninf +} + +func (m *Defaults) GetF_Nan() float32 { + if m != nil && m.F_Nan != nil { + return *m.F_Nan + } + return Default_Defaults_F_Nan +} + +func (m *Defaults) GetSub() *SubDefaults { + if m != nil { + return m.Sub + } + return nil +} + +func (m *Defaults) GetStrZero() string { + if m != nil && m.StrZero != nil { + return *m.StrZero + } + return "" +} + +type SubDefaults struct { + N *int64 `protobuf:"varint,1,opt,name=n,def=7" json:"n,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *SubDefaults) Reset() { *m = SubDefaults{} } +func (m *SubDefaults) String() string { return proto.CompactTextString(m) } +func (*SubDefaults) ProtoMessage() {} +func (*SubDefaults) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{22} } + +const Default_SubDefaults_N int64 = 7 + +func (m *SubDefaults) GetN() int64 { + if m != nil && m.N != nil { + return *m.N + } + return Default_SubDefaults_N +} + +type RepeatedEnum struct { + Color []RepeatedEnum_Color `protobuf:"varint,1,rep,name=color,enum=testdata.RepeatedEnum_Color" json:"color,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *RepeatedEnum) Reset() { *m = RepeatedEnum{} } +func (m *RepeatedEnum) String() string { return proto.CompactTextString(m) } +func (*RepeatedEnum) ProtoMessage() {} +func (*RepeatedEnum) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{23} } + +func (m *RepeatedEnum) GetColor() []RepeatedEnum_Color { + if m != nil { + return m.Color + } + return nil +} + +type MoreRepeated struct { + Bools []bool `protobuf:"varint,1,rep,name=bools" json:"bools,omitempty"` + BoolsPacked []bool `protobuf:"varint,2,rep,packed,name=bools_packed,json=boolsPacked" json:"bools_packed,omitempty"` + Ints []int32 `protobuf:"varint,3,rep,name=ints" json:"ints,omitempty"` + IntsPacked []int32 `protobuf:"varint,4,rep,packed,name=ints_packed,json=intsPacked" json:"ints_packed,omitempty"` + Int64SPacked []int64 `protobuf:"varint,7,rep,packed,name=int64s_packed,json=int64sPacked" json:"int64s_packed,omitempty"` + Strings []string `protobuf:"bytes,5,rep,name=strings" json:"strings,omitempty"` + Fixeds []uint32 `protobuf:"fixed32,6,rep,name=fixeds" json:"fixeds,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *MoreRepeated) Reset() { *m = MoreRepeated{} } +func (m *MoreRepeated) String() string { return proto.CompactTextString(m) } +func (*MoreRepeated) ProtoMessage() {} +func (*MoreRepeated) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{24} } + +func (m *MoreRepeated) GetBools() []bool { + if m != nil { + return m.Bools + } + return nil +} + +func (m *MoreRepeated) GetBoolsPacked() []bool { + if m != nil { + return m.BoolsPacked + } + return nil +} + +func (m *MoreRepeated) GetInts() []int32 { + if m != nil { + return m.Ints + } + return nil +} + +func (m *MoreRepeated) GetIntsPacked() []int32 { + if m != nil { + return m.IntsPacked + } + return nil +} + +func (m *MoreRepeated) GetInt64SPacked() []int64 { + if m != nil { + return m.Int64SPacked + } + return nil +} + +func (m *MoreRepeated) GetStrings() []string { + if m != nil { + return m.Strings + } + return nil +} + +func (m *MoreRepeated) GetFixeds() []uint32 { + if m != nil { + return m.Fixeds + } + return nil +} + +type GroupOld struct { + G *GroupOld_G `protobuf:"group,101,opt,name=G,json=g" json:"g,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *GroupOld) Reset() { *m = GroupOld{} } +func (m *GroupOld) String() string { return proto.CompactTextString(m) } +func (*GroupOld) ProtoMessage() {} +func (*GroupOld) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{25} } + +func (m *GroupOld) GetG() *GroupOld_G { + if m != nil { + return m.G + } + return nil +} + +type GroupOld_G struct { + X *int32 `protobuf:"varint,2,opt,name=x" json:"x,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *GroupOld_G) Reset() { *m = GroupOld_G{} } +func (m *GroupOld_G) String() string { return proto.CompactTextString(m) } +func (*GroupOld_G) ProtoMessage() {} +func (*GroupOld_G) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{25, 0} } + +func (m *GroupOld_G) GetX() int32 { + if m != nil && m.X != nil { + return *m.X + } + return 0 +} + +type GroupNew struct { + G *GroupNew_G `protobuf:"group,101,opt,name=G,json=g" json:"g,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *GroupNew) Reset() { *m = GroupNew{} } +func (m *GroupNew) String() string { return proto.CompactTextString(m) } +func (*GroupNew) ProtoMessage() {} +func (*GroupNew) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{26} } + +func (m *GroupNew) GetG() *GroupNew_G { + if m != nil { + return m.G + } + return nil +} + +type GroupNew_G struct { + X *int32 `protobuf:"varint,2,opt,name=x" json:"x,omitempty"` + Y *int32 `protobuf:"varint,3,opt,name=y" json:"y,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *GroupNew_G) Reset() { *m = GroupNew_G{} } +func (m *GroupNew_G) String() string { return proto.CompactTextString(m) } +func (*GroupNew_G) ProtoMessage() {} +func (*GroupNew_G) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{26, 0} } + +func (m *GroupNew_G) GetX() int32 { + if m != nil && m.X != nil { + return *m.X + } + return 0 +} + +func (m *GroupNew_G) GetY() int32 { + if m != nil && m.Y != nil { + return *m.Y + } + return 0 +} + +type FloatingPoint struct { + F *float64 `protobuf:"fixed64,1,req,name=f" json:"f,omitempty"` + Exact *bool `protobuf:"varint,2,opt,name=exact" json:"exact,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *FloatingPoint) Reset() { *m = FloatingPoint{} } +func (m *FloatingPoint) String() string { return proto.CompactTextString(m) } +func (*FloatingPoint) ProtoMessage() {} +func (*FloatingPoint) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{27} } + +func (m *FloatingPoint) GetF() float64 { + if m != nil && m.F != nil { + return *m.F + } + return 0 +} + +func (m *FloatingPoint) GetExact() bool { + if m != nil && m.Exact != nil { + return *m.Exact + } + return false +} + +type MessageWithMap struct { + NameMapping map[int32]string `protobuf:"bytes,1,rep,name=name_mapping,json=nameMapping" json:"name_mapping,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + MsgMapping map[int64]*FloatingPoint `protobuf:"bytes,2,rep,name=msg_mapping,json=msgMapping" json:"msg_mapping,omitempty" protobuf_key:"zigzag64,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + ByteMapping map[bool][]byte `protobuf:"bytes,3,rep,name=byte_mapping,json=byteMapping" json:"byte_mapping,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + StrToStr map[string]string `protobuf:"bytes,4,rep,name=str_to_str,json=strToStr" json:"str_to_str,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *MessageWithMap) Reset() { *m = MessageWithMap{} } +func (m *MessageWithMap) String() string { return proto.CompactTextString(m) } +func (*MessageWithMap) ProtoMessage() {} +func (*MessageWithMap) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{28} } + +func (m *MessageWithMap) GetNameMapping() map[int32]string { + if m != nil { + return m.NameMapping + } + return nil +} + +func (m *MessageWithMap) GetMsgMapping() map[int64]*FloatingPoint { + if m != nil { + return m.MsgMapping + } + return nil +} + +func (m *MessageWithMap) GetByteMapping() map[bool][]byte { + if m != nil { + return m.ByteMapping + } + return nil +} + +func (m *MessageWithMap) GetStrToStr() map[string]string { + if m != nil { + return m.StrToStr + } + return nil +} + +type Oneof struct { + // Types that are valid to be assigned to Union: + // *Oneof_F_Bool + // *Oneof_F_Int32 + // *Oneof_F_Int64 + // *Oneof_F_Fixed32 + // *Oneof_F_Fixed64 + // *Oneof_F_Uint32 + // *Oneof_F_Uint64 + // *Oneof_F_Float + // *Oneof_F_Double + // *Oneof_F_String + // *Oneof_F_Bytes + // *Oneof_F_Sint32 + // *Oneof_F_Sint64 + // *Oneof_F_Enum + // *Oneof_F_Message + // *Oneof_FGroup + // *Oneof_F_Largest_Tag + Union isOneof_Union `protobuf_oneof:"union"` + // Types that are valid to be assigned to Tormato: + // *Oneof_Value + Tormato isOneof_Tormato `protobuf_oneof:"tormato"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *Oneof) Reset() { *m = Oneof{} } +func (m *Oneof) String() string { return proto.CompactTextString(m) } +func (*Oneof) ProtoMessage() {} +func (*Oneof) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{29} } + +type isOneof_Union interface { + isOneof_Union() +} +type isOneof_Tormato interface { + isOneof_Tormato() +} + +type Oneof_F_Bool struct { + F_Bool bool `protobuf:"varint,1,opt,name=F_Bool,json=FBool,oneof"` +} +type Oneof_F_Int32 struct { + F_Int32 int32 `protobuf:"varint,2,opt,name=F_Int32,json=FInt32,oneof"` +} +type Oneof_F_Int64 struct { + F_Int64 int64 `protobuf:"varint,3,opt,name=F_Int64,json=FInt64,oneof"` +} +type Oneof_F_Fixed32 struct { + F_Fixed32 uint32 `protobuf:"fixed32,4,opt,name=F_Fixed32,json=FFixed32,oneof"` +} +type Oneof_F_Fixed64 struct { + F_Fixed64 uint64 `protobuf:"fixed64,5,opt,name=F_Fixed64,json=FFixed64,oneof"` +} +type Oneof_F_Uint32 struct { + F_Uint32 uint32 `protobuf:"varint,6,opt,name=F_Uint32,json=FUint32,oneof"` +} +type Oneof_F_Uint64 struct { + F_Uint64 uint64 `protobuf:"varint,7,opt,name=F_Uint64,json=FUint64,oneof"` +} +type Oneof_F_Float struct { + F_Float float32 `protobuf:"fixed32,8,opt,name=F_Float,json=FFloat,oneof"` +} +type Oneof_F_Double struct { + F_Double float64 `protobuf:"fixed64,9,opt,name=F_Double,json=FDouble,oneof"` +} +type Oneof_F_String struct { + F_String string `protobuf:"bytes,10,opt,name=F_String,json=FString,oneof"` +} +type Oneof_F_Bytes struct { + F_Bytes []byte `protobuf:"bytes,11,opt,name=F_Bytes,json=FBytes,oneof"` +} +type Oneof_F_Sint32 struct { + F_Sint32 int32 `protobuf:"zigzag32,12,opt,name=F_Sint32,json=FSint32,oneof"` +} +type Oneof_F_Sint64 struct { + F_Sint64 int64 `protobuf:"zigzag64,13,opt,name=F_Sint64,json=FSint64,oneof"` +} +type Oneof_F_Enum struct { + F_Enum MyMessage_Color `protobuf:"varint,14,opt,name=F_Enum,json=FEnum,enum=testdata.MyMessage_Color,oneof"` +} +type Oneof_F_Message struct { + F_Message *GoTestField `protobuf:"bytes,15,opt,name=F_Message,json=FMessage,oneof"` +} +type Oneof_FGroup struct { + FGroup *Oneof_F_Group `protobuf:"group,16,opt,name=F_Group,json=fGroup,oneof"` +} +type Oneof_F_Largest_Tag struct { + F_Largest_Tag int32 `protobuf:"varint,536870911,opt,name=F_Largest_Tag,json=FLargestTag,oneof"` +} +type Oneof_Value struct { + Value int32 `protobuf:"varint,100,opt,name=value,oneof"` +} + +func (*Oneof_F_Bool) isOneof_Union() {} +func (*Oneof_F_Int32) isOneof_Union() {} +func (*Oneof_F_Int64) isOneof_Union() {} +func (*Oneof_F_Fixed32) isOneof_Union() {} +func (*Oneof_F_Fixed64) isOneof_Union() {} +func (*Oneof_F_Uint32) isOneof_Union() {} +func (*Oneof_F_Uint64) isOneof_Union() {} +func (*Oneof_F_Float) isOneof_Union() {} +func (*Oneof_F_Double) isOneof_Union() {} +func (*Oneof_F_String) isOneof_Union() {} +func (*Oneof_F_Bytes) isOneof_Union() {} +func (*Oneof_F_Sint32) isOneof_Union() {} +func (*Oneof_F_Sint64) isOneof_Union() {} +func (*Oneof_F_Enum) isOneof_Union() {} +func (*Oneof_F_Message) isOneof_Union() {} +func (*Oneof_FGroup) isOneof_Union() {} +func (*Oneof_F_Largest_Tag) isOneof_Union() {} +func (*Oneof_Value) isOneof_Tormato() {} + +func (m *Oneof) GetUnion() isOneof_Union { + if m != nil { + return m.Union + } + return nil +} +func (m *Oneof) GetTormato() isOneof_Tormato { + if m != nil { + return m.Tormato + } + return nil +} + +func (m *Oneof) GetF_Bool() bool { + if x, ok := m.GetUnion().(*Oneof_F_Bool); ok { + return x.F_Bool + } + return false +} + +func (m *Oneof) GetF_Int32() int32 { + if x, ok := m.GetUnion().(*Oneof_F_Int32); ok { + return x.F_Int32 + } + return 0 +} + +func (m *Oneof) GetF_Int64() int64 { + if x, ok := m.GetUnion().(*Oneof_F_Int64); ok { + return x.F_Int64 + } + return 0 +} + +func (m *Oneof) GetF_Fixed32() uint32 { + if x, ok := m.GetUnion().(*Oneof_F_Fixed32); ok { + return x.F_Fixed32 + } + return 0 +} + +func (m *Oneof) GetF_Fixed64() uint64 { + if x, ok := m.GetUnion().(*Oneof_F_Fixed64); ok { + return x.F_Fixed64 + } + return 0 +} + +func (m *Oneof) GetF_Uint32() uint32 { + if x, ok := m.GetUnion().(*Oneof_F_Uint32); ok { + return x.F_Uint32 + } + return 0 +} + +func (m *Oneof) GetF_Uint64() uint64 { + if x, ok := m.GetUnion().(*Oneof_F_Uint64); ok { + return x.F_Uint64 + } + return 0 +} + +func (m *Oneof) GetF_Float() float32 { + if x, ok := m.GetUnion().(*Oneof_F_Float); ok { + return x.F_Float + } + return 0 +} + +func (m *Oneof) GetF_Double() float64 { + if x, ok := m.GetUnion().(*Oneof_F_Double); ok { + return x.F_Double + } + return 0 +} + +func (m *Oneof) GetF_String() string { + if x, ok := m.GetUnion().(*Oneof_F_String); ok { + return x.F_String + } + return "" +} + +func (m *Oneof) GetF_Bytes() []byte { + if x, ok := m.GetUnion().(*Oneof_F_Bytes); ok { + return x.F_Bytes + } + return nil +} + +func (m *Oneof) GetF_Sint32() int32 { + if x, ok := m.GetUnion().(*Oneof_F_Sint32); ok { + return x.F_Sint32 + } + return 0 +} + +func (m *Oneof) GetF_Sint64() int64 { + if x, ok := m.GetUnion().(*Oneof_F_Sint64); ok { + return x.F_Sint64 + } + return 0 +} + +func (m *Oneof) GetF_Enum() MyMessage_Color { + if x, ok := m.GetUnion().(*Oneof_F_Enum); ok { + return x.F_Enum + } + return MyMessage_RED +} + +func (m *Oneof) GetF_Message() *GoTestField { + if x, ok := m.GetUnion().(*Oneof_F_Message); ok { + return x.F_Message + } + return nil +} + +func (m *Oneof) GetFGroup() *Oneof_F_Group { + if x, ok := m.GetUnion().(*Oneof_FGroup); ok { + return x.FGroup + } + return nil +} + +func (m *Oneof) GetF_Largest_Tag() int32 { + if x, ok := m.GetUnion().(*Oneof_F_Largest_Tag); ok { + return x.F_Largest_Tag + } + return 0 +} + +func (m *Oneof) GetValue() int32 { + if x, ok := m.GetTormato().(*Oneof_Value); ok { + return x.Value + } + return 0 +} + +// XXX_OneofFuncs is for the internal use of the proto package. +func (*Oneof) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { + return _Oneof_OneofMarshaler, _Oneof_OneofUnmarshaler, _Oneof_OneofSizer, []interface{}{ + (*Oneof_F_Bool)(nil), + (*Oneof_F_Int32)(nil), + (*Oneof_F_Int64)(nil), + (*Oneof_F_Fixed32)(nil), + (*Oneof_F_Fixed64)(nil), + (*Oneof_F_Uint32)(nil), + (*Oneof_F_Uint64)(nil), + (*Oneof_F_Float)(nil), + (*Oneof_F_Double)(nil), + (*Oneof_F_String)(nil), + (*Oneof_F_Bytes)(nil), + (*Oneof_F_Sint32)(nil), + (*Oneof_F_Sint64)(nil), + (*Oneof_F_Enum)(nil), + (*Oneof_F_Message)(nil), + (*Oneof_FGroup)(nil), + (*Oneof_F_Largest_Tag)(nil), + (*Oneof_Value)(nil), + } +} + +func _Oneof_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { + m := msg.(*Oneof) + // union + switch x := m.Union.(type) { + case *Oneof_F_Bool: + t := uint64(0) + if x.F_Bool { + t = 1 + } + b.EncodeVarint(1<<3 | proto.WireVarint) + b.EncodeVarint(t) + case *Oneof_F_Int32: + b.EncodeVarint(2<<3 | proto.WireVarint) + b.EncodeVarint(uint64(x.F_Int32)) + case *Oneof_F_Int64: + b.EncodeVarint(3<<3 | proto.WireVarint) + b.EncodeVarint(uint64(x.F_Int64)) + case *Oneof_F_Fixed32: + b.EncodeVarint(4<<3 | proto.WireFixed32) + b.EncodeFixed32(uint64(x.F_Fixed32)) + case *Oneof_F_Fixed64: + b.EncodeVarint(5<<3 | proto.WireFixed64) + b.EncodeFixed64(uint64(x.F_Fixed64)) + case *Oneof_F_Uint32: + b.EncodeVarint(6<<3 | proto.WireVarint) + b.EncodeVarint(uint64(x.F_Uint32)) + case *Oneof_F_Uint64: + b.EncodeVarint(7<<3 | proto.WireVarint) + b.EncodeVarint(uint64(x.F_Uint64)) + case *Oneof_F_Float: + b.EncodeVarint(8<<3 | proto.WireFixed32) + b.EncodeFixed32(uint64(math.Float32bits(x.F_Float))) + case *Oneof_F_Double: + b.EncodeVarint(9<<3 | proto.WireFixed64) + b.EncodeFixed64(math.Float64bits(x.F_Double)) + case *Oneof_F_String: + b.EncodeVarint(10<<3 | proto.WireBytes) + b.EncodeStringBytes(x.F_String) + case *Oneof_F_Bytes: + b.EncodeVarint(11<<3 | proto.WireBytes) + b.EncodeRawBytes(x.F_Bytes) + case *Oneof_F_Sint32: + b.EncodeVarint(12<<3 | proto.WireVarint) + b.EncodeZigzag32(uint64(x.F_Sint32)) + case *Oneof_F_Sint64: + b.EncodeVarint(13<<3 | proto.WireVarint) + b.EncodeZigzag64(uint64(x.F_Sint64)) + case *Oneof_F_Enum: + b.EncodeVarint(14<<3 | proto.WireVarint) + b.EncodeVarint(uint64(x.F_Enum)) + case *Oneof_F_Message: + b.EncodeVarint(15<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.F_Message); err != nil { + return err + } + case *Oneof_FGroup: + b.EncodeVarint(16<<3 | proto.WireStartGroup) + if err := b.Marshal(x.FGroup); err != nil { + return err + } + b.EncodeVarint(16<<3 | proto.WireEndGroup) + case *Oneof_F_Largest_Tag: + b.EncodeVarint(536870911<<3 | proto.WireVarint) + b.EncodeVarint(uint64(x.F_Largest_Tag)) + case nil: + default: + return fmt.Errorf("Oneof.Union has unexpected type %T", x) + } + // tormato + switch x := m.Tormato.(type) { + case *Oneof_Value: + b.EncodeVarint(100<<3 | proto.WireVarint) + b.EncodeVarint(uint64(x.Value)) + case nil: + default: + return fmt.Errorf("Oneof.Tormato has unexpected type %T", x) + } + return nil +} + +func _Oneof_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { + m := msg.(*Oneof) + switch tag { + case 1: // union.F_Bool + if wire != proto.WireVarint { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeVarint() + m.Union = &Oneof_F_Bool{x != 0} + return true, err + case 2: // union.F_Int32 + if wire != proto.WireVarint { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeVarint() + m.Union = &Oneof_F_Int32{int32(x)} + return true, err + case 3: // union.F_Int64 + if wire != proto.WireVarint { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeVarint() + m.Union = &Oneof_F_Int64{int64(x)} + return true, err + case 4: // union.F_Fixed32 + if wire != proto.WireFixed32 { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeFixed32() + m.Union = &Oneof_F_Fixed32{uint32(x)} + return true, err + case 5: // union.F_Fixed64 + if wire != proto.WireFixed64 { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeFixed64() + m.Union = &Oneof_F_Fixed64{x} + return true, err + case 6: // union.F_Uint32 + if wire != proto.WireVarint { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeVarint() + m.Union = &Oneof_F_Uint32{uint32(x)} + return true, err + case 7: // union.F_Uint64 + if wire != proto.WireVarint { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeVarint() + m.Union = &Oneof_F_Uint64{x} + return true, err + case 8: // union.F_Float + if wire != proto.WireFixed32 { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeFixed32() + m.Union = &Oneof_F_Float{math.Float32frombits(uint32(x))} + return true, err + case 9: // union.F_Double + if wire != proto.WireFixed64 { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeFixed64() + m.Union = &Oneof_F_Double{math.Float64frombits(x)} + return true, err + case 10: // union.F_String + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeStringBytes() + m.Union = &Oneof_F_String{x} + return true, err + case 11: // union.F_Bytes + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeRawBytes(true) + m.Union = &Oneof_F_Bytes{x} + return true, err + case 12: // union.F_Sint32 + if wire != proto.WireVarint { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeZigzag32() + m.Union = &Oneof_F_Sint32{int32(x)} + return true, err + case 13: // union.F_Sint64 + if wire != proto.WireVarint { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeZigzag64() + m.Union = &Oneof_F_Sint64{int64(x)} + return true, err + case 14: // union.F_Enum + if wire != proto.WireVarint { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeVarint() + m.Union = &Oneof_F_Enum{MyMessage_Color(x)} + return true, err + case 15: // union.F_Message + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(GoTestField) + err := b.DecodeMessage(msg) + m.Union = &Oneof_F_Message{msg} + return true, err + case 16: // union.f_group + if wire != proto.WireStartGroup { + return true, proto.ErrInternalBadWireType + } + msg := new(Oneof_F_Group) + err := b.DecodeGroup(msg) + m.Union = &Oneof_FGroup{msg} + return true, err + case 536870911: // union.F_Largest_Tag + if wire != proto.WireVarint { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeVarint() + m.Union = &Oneof_F_Largest_Tag{int32(x)} + return true, err + case 100: // tormato.value + if wire != proto.WireVarint { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeVarint() + m.Tormato = &Oneof_Value{int32(x)} + return true, err + default: + return false, nil + } +} + +func _Oneof_OneofSizer(msg proto.Message) (n int) { + m := msg.(*Oneof) + // union + switch x := m.Union.(type) { + case *Oneof_F_Bool: + n += proto.SizeVarint(1<<3 | proto.WireVarint) + n += 1 + case *Oneof_F_Int32: + n += proto.SizeVarint(2<<3 | proto.WireVarint) + n += proto.SizeVarint(uint64(x.F_Int32)) + case *Oneof_F_Int64: + n += proto.SizeVarint(3<<3 | proto.WireVarint) + n += proto.SizeVarint(uint64(x.F_Int64)) + case *Oneof_F_Fixed32: + n += proto.SizeVarint(4<<3 | proto.WireFixed32) + n += 4 + case *Oneof_F_Fixed64: + n += proto.SizeVarint(5<<3 | proto.WireFixed64) + n += 8 + case *Oneof_F_Uint32: + n += proto.SizeVarint(6<<3 | proto.WireVarint) + n += proto.SizeVarint(uint64(x.F_Uint32)) + case *Oneof_F_Uint64: + n += proto.SizeVarint(7<<3 | proto.WireVarint) + n += proto.SizeVarint(uint64(x.F_Uint64)) + case *Oneof_F_Float: + n += proto.SizeVarint(8<<3 | proto.WireFixed32) + n += 4 + case *Oneof_F_Double: + n += proto.SizeVarint(9<<3 | proto.WireFixed64) + n += 8 + case *Oneof_F_String: + n += proto.SizeVarint(10<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(len(x.F_String))) + n += len(x.F_String) + case *Oneof_F_Bytes: + n += proto.SizeVarint(11<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(len(x.F_Bytes))) + n += len(x.F_Bytes) + case *Oneof_F_Sint32: + n += proto.SizeVarint(12<<3 | proto.WireVarint) + n += proto.SizeVarint(uint64((uint32(x.F_Sint32) << 1) ^ uint32((int32(x.F_Sint32) >> 31)))) + case *Oneof_F_Sint64: + n += proto.SizeVarint(13<<3 | proto.WireVarint) + n += proto.SizeVarint(uint64(uint64(x.F_Sint64<<1) ^ uint64((int64(x.F_Sint64) >> 63)))) + case *Oneof_F_Enum: + n += proto.SizeVarint(14<<3 | proto.WireVarint) + n += proto.SizeVarint(uint64(x.F_Enum)) + case *Oneof_F_Message: + s := proto.Size(x.F_Message) + n += proto.SizeVarint(15<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *Oneof_FGroup: + n += proto.SizeVarint(16<<3 | proto.WireStartGroup) + n += proto.Size(x.FGroup) + n += proto.SizeVarint(16<<3 | proto.WireEndGroup) + case *Oneof_F_Largest_Tag: + n += proto.SizeVarint(536870911<<3 | proto.WireVarint) + n += proto.SizeVarint(uint64(x.F_Largest_Tag)) + case nil: + default: + panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) + } + // tormato + switch x := m.Tormato.(type) { + case *Oneof_Value: + n += proto.SizeVarint(100<<3 | proto.WireVarint) + n += proto.SizeVarint(uint64(x.Value)) + case nil: + default: + panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) + } + return n +} + +type Oneof_F_Group struct { + X *int32 `protobuf:"varint,17,opt,name=x" json:"x,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *Oneof_F_Group) Reset() { *m = Oneof_F_Group{} } +func (m *Oneof_F_Group) String() string { return proto.CompactTextString(m) } +func (*Oneof_F_Group) ProtoMessage() {} +func (*Oneof_F_Group) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{29, 0} } + +func (m *Oneof_F_Group) GetX() int32 { + if m != nil && m.X != nil { + return *m.X + } + return 0 +} + +type Communique struct { + MakeMeCry *bool `protobuf:"varint,1,opt,name=make_me_cry,json=makeMeCry" json:"make_me_cry,omitempty"` + // This is a oneof, called "union". + // + // Types that are valid to be assigned to Union: + // *Communique_Number + // *Communique_Name + // *Communique_Data + // *Communique_TempC + // *Communique_Col + // *Communique_Msg + Union isCommunique_Union `protobuf_oneof:"union"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *Communique) Reset() { *m = Communique{} } +func (m *Communique) String() string { return proto.CompactTextString(m) } +func (*Communique) ProtoMessage() {} +func (*Communique) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{30} } + +type isCommunique_Union interface { + isCommunique_Union() +} + +type Communique_Number struct { + Number int32 `protobuf:"varint,5,opt,name=number,oneof"` +} +type Communique_Name struct { + Name string `protobuf:"bytes,6,opt,name=name,oneof"` +} +type Communique_Data struct { + Data []byte `protobuf:"bytes,7,opt,name=data,oneof"` +} +type Communique_TempC struct { + TempC float64 `protobuf:"fixed64,8,opt,name=temp_c,json=tempC,oneof"` +} +type Communique_Col struct { + Col MyMessage_Color `protobuf:"varint,9,opt,name=col,enum=testdata.MyMessage_Color,oneof"` +} +type Communique_Msg struct { + Msg *Strings `protobuf:"bytes,10,opt,name=msg,oneof"` +} + +func (*Communique_Number) isCommunique_Union() {} +func (*Communique_Name) isCommunique_Union() {} +func (*Communique_Data) isCommunique_Union() {} +func (*Communique_TempC) isCommunique_Union() {} +func (*Communique_Col) isCommunique_Union() {} +func (*Communique_Msg) isCommunique_Union() {} + +func (m *Communique) GetUnion() isCommunique_Union { + if m != nil { + return m.Union + } + return nil +} + +func (m *Communique) GetMakeMeCry() bool { + if m != nil && m.MakeMeCry != nil { + return *m.MakeMeCry + } + return false +} + +func (m *Communique) GetNumber() int32 { + if x, ok := m.GetUnion().(*Communique_Number); ok { + return x.Number + } + return 0 +} + +func (m *Communique) GetName() string { + if x, ok := m.GetUnion().(*Communique_Name); ok { + return x.Name + } + return "" +} + +func (m *Communique) GetData() []byte { + if x, ok := m.GetUnion().(*Communique_Data); ok { + return x.Data + } + return nil +} + +func (m *Communique) GetTempC() float64 { + if x, ok := m.GetUnion().(*Communique_TempC); ok { + return x.TempC + } + return 0 +} + +func (m *Communique) GetCol() MyMessage_Color { + if x, ok := m.GetUnion().(*Communique_Col); ok { + return x.Col + } + return MyMessage_RED +} + +func (m *Communique) GetMsg() *Strings { + if x, ok := m.GetUnion().(*Communique_Msg); ok { + return x.Msg + } + return nil +} + +// XXX_OneofFuncs is for the internal use of the proto package. +func (*Communique) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { + return _Communique_OneofMarshaler, _Communique_OneofUnmarshaler, _Communique_OneofSizer, []interface{}{ + (*Communique_Number)(nil), + (*Communique_Name)(nil), + (*Communique_Data)(nil), + (*Communique_TempC)(nil), + (*Communique_Col)(nil), + (*Communique_Msg)(nil), + } +} + +func _Communique_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { + m := msg.(*Communique) + // union + switch x := m.Union.(type) { + case *Communique_Number: + b.EncodeVarint(5<<3 | proto.WireVarint) + b.EncodeVarint(uint64(x.Number)) + case *Communique_Name: + b.EncodeVarint(6<<3 | proto.WireBytes) + b.EncodeStringBytes(x.Name) + case *Communique_Data: + b.EncodeVarint(7<<3 | proto.WireBytes) + b.EncodeRawBytes(x.Data) + case *Communique_TempC: + b.EncodeVarint(8<<3 | proto.WireFixed64) + b.EncodeFixed64(math.Float64bits(x.TempC)) + case *Communique_Col: + b.EncodeVarint(9<<3 | proto.WireVarint) + b.EncodeVarint(uint64(x.Col)) + case *Communique_Msg: + b.EncodeVarint(10<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.Msg); err != nil { + return err + } + case nil: + default: + return fmt.Errorf("Communique.Union has unexpected type %T", x) + } + return nil +} + +func _Communique_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { + m := msg.(*Communique) + switch tag { + case 5: // union.number + if wire != proto.WireVarint { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeVarint() + m.Union = &Communique_Number{int32(x)} + return true, err + case 6: // union.name + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeStringBytes() + m.Union = &Communique_Name{x} + return true, err + case 7: // union.data + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeRawBytes(true) + m.Union = &Communique_Data{x} + return true, err + case 8: // union.temp_c + if wire != proto.WireFixed64 { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeFixed64() + m.Union = &Communique_TempC{math.Float64frombits(x)} + return true, err + case 9: // union.col + if wire != proto.WireVarint { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeVarint() + m.Union = &Communique_Col{MyMessage_Color(x)} + return true, err + case 10: // union.msg + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(Strings) + err := b.DecodeMessage(msg) + m.Union = &Communique_Msg{msg} + return true, err + default: + return false, nil + } +} + +func _Communique_OneofSizer(msg proto.Message) (n int) { + m := msg.(*Communique) + // union + switch x := m.Union.(type) { + case *Communique_Number: + n += proto.SizeVarint(5<<3 | proto.WireVarint) + n += proto.SizeVarint(uint64(x.Number)) + case *Communique_Name: + n += proto.SizeVarint(6<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(len(x.Name))) + n += len(x.Name) + case *Communique_Data: + n += proto.SizeVarint(7<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(len(x.Data))) + n += len(x.Data) + case *Communique_TempC: + n += proto.SizeVarint(8<<3 | proto.WireFixed64) + n += 8 + case *Communique_Col: + n += proto.SizeVarint(9<<3 | proto.WireVarint) + n += proto.SizeVarint(uint64(x.Col)) + case *Communique_Msg: + s := proto.Size(x.Msg) + n += proto.SizeVarint(10<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case nil: + default: + panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) + } + return n +} + +var E_Greeting = &proto.ExtensionDesc{ + ExtendedType: (*MyMessage)(nil), + ExtensionType: ([]string)(nil), + Field: 106, + Name: "testdata.greeting", + Tag: "bytes,106,rep,name=greeting", + Filename: "test.proto", +} + +var E_Complex = &proto.ExtensionDesc{ + ExtendedType: (*OtherMessage)(nil), + ExtensionType: (*ComplexExtension)(nil), + Field: 200, + Name: "testdata.complex", + Tag: "bytes,200,opt,name=complex", + Filename: "test.proto", +} + +var E_RComplex = &proto.ExtensionDesc{ + ExtendedType: (*OtherMessage)(nil), + ExtensionType: ([]*ComplexExtension)(nil), + Field: 201, + Name: "testdata.r_complex", + Tag: "bytes,201,rep,name=r_complex,json=rComplex", + Filename: "test.proto", +} + +var E_NoDefaultDouble = &proto.ExtensionDesc{ + ExtendedType: (*DefaultsMessage)(nil), + ExtensionType: (*float64)(nil), + Field: 101, + Name: "testdata.no_default_double", + Tag: "fixed64,101,opt,name=no_default_double,json=noDefaultDouble", + Filename: "test.proto", +} + +var E_NoDefaultFloat = &proto.ExtensionDesc{ + ExtendedType: (*DefaultsMessage)(nil), + ExtensionType: (*float32)(nil), + Field: 102, + Name: "testdata.no_default_float", + Tag: "fixed32,102,opt,name=no_default_float,json=noDefaultFloat", + Filename: "test.proto", +} + +var E_NoDefaultInt32 = &proto.ExtensionDesc{ + ExtendedType: (*DefaultsMessage)(nil), + ExtensionType: (*int32)(nil), + Field: 103, + Name: "testdata.no_default_int32", + Tag: "varint,103,opt,name=no_default_int32,json=noDefaultInt32", + Filename: "test.proto", +} + +var E_NoDefaultInt64 = &proto.ExtensionDesc{ + ExtendedType: (*DefaultsMessage)(nil), + ExtensionType: (*int64)(nil), + Field: 104, + Name: "testdata.no_default_int64", + Tag: "varint,104,opt,name=no_default_int64,json=noDefaultInt64", + Filename: "test.proto", +} + +var E_NoDefaultUint32 = &proto.ExtensionDesc{ + ExtendedType: (*DefaultsMessage)(nil), + ExtensionType: (*uint32)(nil), + Field: 105, + Name: "testdata.no_default_uint32", + Tag: "varint,105,opt,name=no_default_uint32,json=noDefaultUint32", + Filename: "test.proto", +} + +var E_NoDefaultUint64 = &proto.ExtensionDesc{ + ExtendedType: (*DefaultsMessage)(nil), + ExtensionType: (*uint64)(nil), + Field: 106, + Name: "testdata.no_default_uint64", + Tag: "varint,106,opt,name=no_default_uint64,json=noDefaultUint64", + Filename: "test.proto", +} + +var E_NoDefaultSint32 = &proto.ExtensionDesc{ + ExtendedType: (*DefaultsMessage)(nil), + ExtensionType: (*int32)(nil), + Field: 107, + Name: "testdata.no_default_sint32", + Tag: "zigzag32,107,opt,name=no_default_sint32,json=noDefaultSint32", + Filename: "test.proto", +} + +var E_NoDefaultSint64 = &proto.ExtensionDesc{ + ExtendedType: (*DefaultsMessage)(nil), + ExtensionType: (*int64)(nil), + Field: 108, + Name: "testdata.no_default_sint64", + Tag: "zigzag64,108,opt,name=no_default_sint64,json=noDefaultSint64", + Filename: "test.proto", +} + +var E_NoDefaultFixed32 = &proto.ExtensionDesc{ + ExtendedType: (*DefaultsMessage)(nil), + ExtensionType: (*uint32)(nil), + Field: 109, + Name: "testdata.no_default_fixed32", + Tag: "fixed32,109,opt,name=no_default_fixed32,json=noDefaultFixed32", + Filename: "test.proto", +} + +var E_NoDefaultFixed64 = &proto.ExtensionDesc{ + ExtendedType: (*DefaultsMessage)(nil), + ExtensionType: (*uint64)(nil), + Field: 110, + Name: "testdata.no_default_fixed64", + Tag: "fixed64,110,opt,name=no_default_fixed64,json=noDefaultFixed64", + Filename: "test.proto", +} + +var E_NoDefaultSfixed32 = &proto.ExtensionDesc{ + ExtendedType: (*DefaultsMessage)(nil), + ExtensionType: (*int32)(nil), + Field: 111, + Name: "testdata.no_default_sfixed32", + Tag: "fixed32,111,opt,name=no_default_sfixed32,json=noDefaultSfixed32", + Filename: "test.proto", +} + +var E_NoDefaultSfixed64 = &proto.ExtensionDesc{ + ExtendedType: (*DefaultsMessage)(nil), + ExtensionType: (*int64)(nil), + Field: 112, + Name: "testdata.no_default_sfixed64", + Tag: "fixed64,112,opt,name=no_default_sfixed64,json=noDefaultSfixed64", + Filename: "test.proto", +} + +var E_NoDefaultBool = &proto.ExtensionDesc{ + ExtendedType: (*DefaultsMessage)(nil), + ExtensionType: (*bool)(nil), + Field: 113, + Name: "testdata.no_default_bool", + Tag: "varint,113,opt,name=no_default_bool,json=noDefaultBool", + Filename: "test.proto", +} + +var E_NoDefaultString = &proto.ExtensionDesc{ + ExtendedType: (*DefaultsMessage)(nil), + ExtensionType: (*string)(nil), + Field: 114, + Name: "testdata.no_default_string", + Tag: "bytes,114,opt,name=no_default_string,json=noDefaultString", + Filename: "test.proto", +} + +var E_NoDefaultBytes = &proto.ExtensionDesc{ + ExtendedType: (*DefaultsMessage)(nil), + ExtensionType: ([]byte)(nil), + Field: 115, + Name: "testdata.no_default_bytes", + Tag: "bytes,115,opt,name=no_default_bytes,json=noDefaultBytes", + Filename: "test.proto", +} + +var E_NoDefaultEnum = &proto.ExtensionDesc{ + ExtendedType: (*DefaultsMessage)(nil), + ExtensionType: (*DefaultsMessage_DefaultsEnum)(nil), + Field: 116, + Name: "testdata.no_default_enum", + Tag: "varint,116,opt,name=no_default_enum,json=noDefaultEnum,enum=testdata.DefaultsMessage_DefaultsEnum", + Filename: "test.proto", +} + +var E_DefaultDouble = &proto.ExtensionDesc{ + ExtendedType: (*DefaultsMessage)(nil), + ExtensionType: (*float64)(nil), + Field: 201, + Name: "testdata.default_double", + Tag: "fixed64,201,opt,name=default_double,json=defaultDouble,def=3.1415", + Filename: "test.proto", +} + +var E_DefaultFloat = &proto.ExtensionDesc{ + ExtendedType: (*DefaultsMessage)(nil), + ExtensionType: (*float32)(nil), + Field: 202, + Name: "testdata.default_float", + Tag: "fixed32,202,opt,name=default_float,json=defaultFloat,def=3.14", + Filename: "test.proto", +} + +var E_DefaultInt32 = &proto.ExtensionDesc{ + ExtendedType: (*DefaultsMessage)(nil), + ExtensionType: (*int32)(nil), + Field: 203, + Name: "testdata.default_int32", + Tag: "varint,203,opt,name=default_int32,json=defaultInt32,def=42", + Filename: "test.proto", +} + +var E_DefaultInt64 = &proto.ExtensionDesc{ + ExtendedType: (*DefaultsMessage)(nil), + ExtensionType: (*int64)(nil), + Field: 204, + Name: "testdata.default_int64", + Tag: "varint,204,opt,name=default_int64,json=defaultInt64,def=43", + Filename: "test.proto", +} + +var E_DefaultUint32 = &proto.ExtensionDesc{ + ExtendedType: (*DefaultsMessage)(nil), + ExtensionType: (*uint32)(nil), + Field: 205, + Name: "testdata.default_uint32", + Tag: "varint,205,opt,name=default_uint32,json=defaultUint32,def=44", + Filename: "test.proto", +} + +var E_DefaultUint64 = &proto.ExtensionDesc{ + ExtendedType: (*DefaultsMessage)(nil), + ExtensionType: (*uint64)(nil), + Field: 206, + Name: "testdata.default_uint64", + Tag: "varint,206,opt,name=default_uint64,json=defaultUint64,def=45", + Filename: "test.proto", +} + +var E_DefaultSint32 = &proto.ExtensionDesc{ + ExtendedType: (*DefaultsMessage)(nil), + ExtensionType: (*int32)(nil), + Field: 207, + Name: "testdata.default_sint32", + Tag: "zigzag32,207,opt,name=default_sint32,json=defaultSint32,def=46", + Filename: "test.proto", +} + +var E_DefaultSint64 = &proto.ExtensionDesc{ + ExtendedType: (*DefaultsMessage)(nil), + ExtensionType: (*int64)(nil), + Field: 208, + Name: "testdata.default_sint64", + Tag: "zigzag64,208,opt,name=default_sint64,json=defaultSint64,def=47", + Filename: "test.proto", +} + +var E_DefaultFixed32 = &proto.ExtensionDesc{ + ExtendedType: (*DefaultsMessage)(nil), + ExtensionType: (*uint32)(nil), + Field: 209, + Name: "testdata.default_fixed32", + Tag: "fixed32,209,opt,name=default_fixed32,json=defaultFixed32,def=48", + Filename: "test.proto", +} + +var E_DefaultFixed64 = &proto.ExtensionDesc{ + ExtendedType: (*DefaultsMessage)(nil), + ExtensionType: (*uint64)(nil), + Field: 210, + Name: "testdata.default_fixed64", + Tag: "fixed64,210,opt,name=default_fixed64,json=defaultFixed64,def=49", + Filename: "test.proto", +} + +var E_DefaultSfixed32 = &proto.ExtensionDesc{ + ExtendedType: (*DefaultsMessage)(nil), + ExtensionType: (*int32)(nil), + Field: 211, + Name: "testdata.default_sfixed32", + Tag: "fixed32,211,opt,name=default_sfixed32,json=defaultSfixed32,def=50", + Filename: "test.proto", +} + +var E_DefaultSfixed64 = &proto.ExtensionDesc{ + ExtendedType: (*DefaultsMessage)(nil), + ExtensionType: (*int64)(nil), + Field: 212, + Name: "testdata.default_sfixed64", + Tag: "fixed64,212,opt,name=default_sfixed64,json=defaultSfixed64,def=51", + Filename: "test.proto", +} + +var E_DefaultBool = &proto.ExtensionDesc{ + ExtendedType: (*DefaultsMessage)(nil), + ExtensionType: (*bool)(nil), + Field: 213, + Name: "testdata.default_bool", + Tag: "varint,213,opt,name=default_bool,json=defaultBool,def=1", + Filename: "test.proto", +} + +var E_DefaultString = &proto.ExtensionDesc{ + ExtendedType: (*DefaultsMessage)(nil), + ExtensionType: (*string)(nil), + Field: 214, + Name: "testdata.default_string", + Tag: "bytes,214,opt,name=default_string,json=defaultString,def=Hello, string", + Filename: "test.proto", +} + +var E_DefaultBytes = &proto.ExtensionDesc{ + ExtendedType: (*DefaultsMessage)(nil), + ExtensionType: ([]byte)(nil), + Field: 215, + Name: "testdata.default_bytes", + Tag: "bytes,215,opt,name=default_bytes,json=defaultBytes,def=Hello, bytes", + Filename: "test.proto", +} + +var E_DefaultEnum = &proto.ExtensionDesc{ + ExtendedType: (*DefaultsMessage)(nil), + ExtensionType: (*DefaultsMessage_DefaultsEnum)(nil), + Field: 216, + Name: "testdata.default_enum", + Tag: "varint,216,opt,name=default_enum,json=defaultEnum,enum=testdata.DefaultsMessage_DefaultsEnum,def=1", + Filename: "test.proto", +} + +var E_X201 = &proto.ExtensionDesc{ + ExtendedType: (*MyMessageSet)(nil), + ExtensionType: (*Empty)(nil), + Field: 201, + Name: "testdata.x201", + Tag: "bytes,201,opt,name=x201", + Filename: "test.proto", +} + +var E_X202 = &proto.ExtensionDesc{ + ExtendedType: (*MyMessageSet)(nil), + ExtensionType: (*Empty)(nil), + Field: 202, + Name: "testdata.x202", + Tag: "bytes,202,opt,name=x202", + Filename: "test.proto", +} + +var E_X203 = &proto.ExtensionDesc{ + ExtendedType: (*MyMessageSet)(nil), + ExtensionType: (*Empty)(nil), + Field: 203, + Name: "testdata.x203", + Tag: "bytes,203,opt,name=x203", + Filename: "test.proto", +} + +var E_X204 = &proto.ExtensionDesc{ + ExtendedType: (*MyMessageSet)(nil), + ExtensionType: (*Empty)(nil), + Field: 204, + Name: "testdata.x204", + Tag: "bytes,204,opt,name=x204", + Filename: "test.proto", +} + +var E_X205 = &proto.ExtensionDesc{ + ExtendedType: (*MyMessageSet)(nil), + ExtensionType: (*Empty)(nil), + Field: 205, + Name: "testdata.x205", + Tag: "bytes,205,opt,name=x205", + Filename: "test.proto", +} + +var E_X206 = &proto.ExtensionDesc{ + ExtendedType: (*MyMessageSet)(nil), + ExtensionType: (*Empty)(nil), + Field: 206, + Name: "testdata.x206", + Tag: "bytes,206,opt,name=x206", + Filename: "test.proto", +} + +var E_X207 = &proto.ExtensionDesc{ + ExtendedType: (*MyMessageSet)(nil), + ExtensionType: (*Empty)(nil), + Field: 207, + Name: "testdata.x207", + Tag: "bytes,207,opt,name=x207", + Filename: "test.proto", +} + +var E_X208 = &proto.ExtensionDesc{ + ExtendedType: (*MyMessageSet)(nil), + ExtensionType: (*Empty)(nil), + Field: 208, + Name: "testdata.x208", + Tag: "bytes,208,opt,name=x208", + Filename: "test.proto", +} + +var E_X209 = &proto.ExtensionDesc{ + ExtendedType: (*MyMessageSet)(nil), + ExtensionType: (*Empty)(nil), + Field: 209, + Name: "testdata.x209", + Tag: "bytes,209,opt,name=x209", + Filename: "test.proto", +} + +var E_X210 = &proto.ExtensionDesc{ + ExtendedType: (*MyMessageSet)(nil), + ExtensionType: (*Empty)(nil), + Field: 210, + Name: "testdata.x210", + Tag: "bytes,210,opt,name=x210", + Filename: "test.proto", +} + +var E_X211 = &proto.ExtensionDesc{ + ExtendedType: (*MyMessageSet)(nil), + ExtensionType: (*Empty)(nil), + Field: 211, + Name: "testdata.x211", + Tag: "bytes,211,opt,name=x211", + Filename: "test.proto", +} + +var E_X212 = &proto.ExtensionDesc{ + ExtendedType: (*MyMessageSet)(nil), + ExtensionType: (*Empty)(nil), + Field: 212, + Name: "testdata.x212", + Tag: "bytes,212,opt,name=x212", + Filename: "test.proto", +} + +var E_X213 = &proto.ExtensionDesc{ + ExtendedType: (*MyMessageSet)(nil), + ExtensionType: (*Empty)(nil), + Field: 213, + Name: "testdata.x213", + Tag: "bytes,213,opt,name=x213", + Filename: "test.proto", +} + +var E_X214 = &proto.ExtensionDesc{ + ExtendedType: (*MyMessageSet)(nil), + ExtensionType: (*Empty)(nil), + Field: 214, + Name: "testdata.x214", + Tag: "bytes,214,opt,name=x214", + Filename: "test.proto", +} + +var E_X215 = &proto.ExtensionDesc{ + ExtendedType: (*MyMessageSet)(nil), + ExtensionType: (*Empty)(nil), + Field: 215, + Name: "testdata.x215", + Tag: "bytes,215,opt,name=x215", + Filename: "test.proto", +} + +var E_X216 = &proto.ExtensionDesc{ + ExtendedType: (*MyMessageSet)(nil), + ExtensionType: (*Empty)(nil), + Field: 216, + Name: "testdata.x216", + Tag: "bytes,216,opt,name=x216", + Filename: "test.proto", +} + +var E_X217 = &proto.ExtensionDesc{ + ExtendedType: (*MyMessageSet)(nil), + ExtensionType: (*Empty)(nil), + Field: 217, + Name: "testdata.x217", + Tag: "bytes,217,opt,name=x217", + Filename: "test.proto", +} + +var E_X218 = &proto.ExtensionDesc{ + ExtendedType: (*MyMessageSet)(nil), + ExtensionType: (*Empty)(nil), + Field: 218, + Name: "testdata.x218", + Tag: "bytes,218,opt,name=x218", + Filename: "test.proto", +} + +var E_X219 = &proto.ExtensionDesc{ + ExtendedType: (*MyMessageSet)(nil), + ExtensionType: (*Empty)(nil), + Field: 219, + Name: "testdata.x219", + Tag: "bytes,219,opt,name=x219", + Filename: "test.proto", +} + +var E_X220 = &proto.ExtensionDesc{ + ExtendedType: (*MyMessageSet)(nil), + ExtensionType: (*Empty)(nil), + Field: 220, + Name: "testdata.x220", + Tag: "bytes,220,opt,name=x220", + Filename: "test.proto", +} + +var E_X221 = &proto.ExtensionDesc{ + ExtendedType: (*MyMessageSet)(nil), + ExtensionType: (*Empty)(nil), + Field: 221, + Name: "testdata.x221", + Tag: "bytes,221,opt,name=x221", + Filename: "test.proto", +} + +var E_X222 = &proto.ExtensionDesc{ + ExtendedType: (*MyMessageSet)(nil), + ExtensionType: (*Empty)(nil), + Field: 222, + Name: "testdata.x222", + Tag: "bytes,222,opt,name=x222", + Filename: "test.proto", +} + +var E_X223 = &proto.ExtensionDesc{ + ExtendedType: (*MyMessageSet)(nil), + ExtensionType: (*Empty)(nil), + Field: 223, + Name: "testdata.x223", + Tag: "bytes,223,opt,name=x223", + Filename: "test.proto", +} + +var E_X224 = &proto.ExtensionDesc{ + ExtendedType: (*MyMessageSet)(nil), + ExtensionType: (*Empty)(nil), + Field: 224, + Name: "testdata.x224", + Tag: "bytes,224,opt,name=x224", + Filename: "test.proto", +} + +var E_X225 = &proto.ExtensionDesc{ + ExtendedType: (*MyMessageSet)(nil), + ExtensionType: (*Empty)(nil), + Field: 225, + Name: "testdata.x225", + Tag: "bytes,225,opt,name=x225", + Filename: "test.proto", +} + +var E_X226 = &proto.ExtensionDesc{ + ExtendedType: (*MyMessageSet)(nil), + ExtensionType: (*Empty)(nil), + Field: 226, + Name: "testdata.x226", + Tag: "bytes,226,opt,name=x226", + Filename: "test.proto", +} + +var E_X227 = &proto.ExtensionDesc{ + ExtendedType: (*MyMessageSet)(nil), + ExtensionType: (*Empty)(nil), + Field: 227, + Name: "testdata.x227", + Tag: "bytes,227,opt,name=x227", + Filename: "test.proto", +} + +var E_X228 = &proto.ExtensionDesc{ + ExtendedType: (*MyMessageSet)(nil), + ExtensionType: (*Empty)(nil), + Field: 228, + Name: "testdata.x228", + Tag: "bytes,228,opt,name=x228", + Filename: "test.proto", +} + +var E_X229 = &proto.ExtensionDesc{ + ExtendedType: (*MyMessageSet)(nil), + ExtensionType: (*Empty)(nil), + Field: 229, + Name: "testdata.x229", + Tag: "bytes,229,opt,name=x229", + Filename: "test.proto", +} + +var E_X230 = &proto.ExtensionDesc{ + ExtendedType: (*MyMessageSet)(nil), + ExtensionType: (*Empty)(nil), + Field: 230, + Name: "testdata.x230", + Tag: "bytes,230,opt,name=x230", + Filename: "test.proto", +} + +var E_X231 = &proto.ExtensionDesc{ + ExtendedType: (*MyMessageSet)(nil), + ExtensionType: (*Empty)(nil), + Field: 231, + Name: "testdata.x231", + Tag: "bytes,231,opt,name=x231", + Filename: "test.proto", +} + +var E_X232 = &proto.ExtensionDesc{ + ExtendedType: (*MyMessageSet)(nil), + ExtensionType: (*Empty)(nil), + Field: 232, + Name: "testdata.x232", + Tag: "bytes,232,opt,name=x232", + Filename: "test.proto", +} + +var E_X233 = &proto.ExtensionDesc{ + ExtendedType: (*MyMessageSet)(nil), + ExtensionType: (*Empty)(nil), + Field: 233, + Name: "testdata.x233", + Tag: "bytes,233,opt,name=x233", + Filename: "test.proto", +} + +var E_X234 = &proto.ExtensionDesc{ + ExtendedType: (*MyMessageSet)(nil), + ExtensionType: (*Empty)(nil), + Field: 234, + Name: "testdata.x234", + Tag: "bytes,234,opt,name=x234", + Filename: "test.proto", +} + +var E_X235 = &proto.ExtensionDesc{ + ExtendedType: (*MyMessageSet)(nil), + ExtensionType: (*Empty)(nil), + Field: 235, + Name: "testdata.x235", + Tag: "bytes,235,opt,name=x235", + Filename: "test.proto", +} + +var E_X236 = &proto.ExtensionDesc{ + ExtendedType: (*MyMessageSet)(nil), + ExtensionType: (*Empty)(nil), + Field: 236, + Name: "testdata.x236", + Tag: "bytes,236,opt,name=x236", + Filename: "test.proto", +} + +var E_X237 = &proto.ExtensionDesc{ + ExtendedType: (*MyMessageSet)(nil), + ExtensionType: (*Empty)(nil), + Field: 237, + Name: "testdata.x237", + Tag: "bytes,237,opt,name=x237", + Filename: "test.proto", +} + +var E_X238 = &proto.ExtensionDesc{ + ExtendedType: (*MyMessageSet)(nil), + ExtensionType: (*Empty)(nil), + Field: 238, + Name: "testdata.x238", + Tag: "bytes,238,opt,name=x238", + Filename: "test.proto", +} + +var E_X239 = &proto.ExtensionDesc{ + ExtendedType: (*MyMessageSet)(nil), + ExtensionType: (*Empty)(nil), + Field: 239, + Name: "testdata.x239", + Tag: "bytes,239,opt,name=x239", + Filename: "test.proto", +} + +var E_X240 = &proto.ExtensionDesc{ + ExtendedType: (*MyMessageSet)(nil), + ExtensionType: (*Empty)(nil), + Field: 240, + Name: "testdata.x240", + Tag: "bytes,240,opt,name=x240", + Filename: "test.proto", +} + +var E_X241 = &proto.ExtensionDesc{ + ExtendedType: (*MyMessageSet)(nil), + ExtensionType: (*Empty)(nil), + Field: 241, + Name: "testdata.x241", + Tag: "bytes,241,opt,name=x241", + Filename: "test.proto", +} + +var E_X242 = &proto.ExtensionDesc{ + ExtendedType: (*MyMessageSet)(nil), + ExtensionType: (*Empty)(nil), + Field: 242, + Name: "testdata.x242", + Tag: "bytes,242,opt,name=x242", + Filename: "test.proto", +} + +var E_X243 = &proto.ExtensionDesc{ + ExtendedType: (*MyMessageSet)(nil), + ExtensionType: (*Empty)(nil), + Field: 243, + Name: "testdata.x243", + Tag: "bytes,243,opt,name=x243", + Filename: "test.proto", +} + +var E_X244 = &proto.ExtensionDesc{ + ExtendedType: (*MyMessageSet)(nil), + ExtensionType: (*Empty)(nil), + Field: 244, + Name: "testdata.x244", + Tag: "bytes,244,opt,name=x244", + Filename: "test.proto", +} + +var E_X245 = &proto.ExtensionDesc{ + ExtendedType: (*MyMessageSet)(nil), + ExtensionType: (*Empty)(nil), + Field: 245, + Name: "testdata.x245", + Tag: "bytes,245,opt,name=x245", + Filename: "test.proto", +} + +var E_X246 = &proto.ExtensionDesc{ + ExtendedType: (*MyMessageSet)(nil), + ExtensionType: (*Empty)(nil), + Field: 246, + Name: "testdata.x246", + Tag: "bytes,246,opt,name=x246", + Filename: "test.proto", +} + +var E_X247 = &proto.ExtensionDesc{ + ExtendedType: (*MyMessageSet)(nil), + ExtensionType: (*Empty)(nil), + Field: 247, + Name: "testdata.x247", + Tag: "bytes,247,opt,name=x247", + Filename: "test.proto", +} + +var E_X248 = &proto.ExtensionDesc{ + ExtendedType: (*MyMessageSet)(nil), + ExtensionType: (*Empty)(nil), + Field: 248, + Name: "testdata.x248", + Tag: "bytes,248,opt,name=x248", + Filename: "test.proto", +} + +var E_X249 = &proto.ExtensionDesc{ + ExtendedType: (*MyMessageSet)(nil), + ExtensionType: (*Empty)(nil), + Field: 249, + Name: "testdata.x249", + Tag: "bytes,249,opt,name=x249", + Filename: "test.proto", +} + +var E_X250 = &proto.ExtensionDesc{ + ExtendedType: (*MyMessageSet)(nil), + ExtensionType: (*Empty)(nil), + Field: 250, + Name: "testdata.x250", + Tag: "bytes,250,opt,name=x250", + Filename: "test.proto", +} + +func init() { + proto.RegisterType((*GoEnum)(nil), "testdata.GoEnum") + proto.RegisterType((*GoTestField)(nil), "testdata.GoTestField") + proto.RegisterType((*GoTest)(nil), "testdata.GoTest") + proto.RegisterType((*GoTest_RequiredGroup)(nil), "testdata.GoTest.RequiredGroup") + proto.RegisterType((*GoTest_RepeatedGroup)(nil), "testdata.GoTest.RepeatedGroup") + proto.RegisterType((*GoTest_OptionalGroup)(nil), "testdata.GoTest.OptionalGroup") + proto.RegisterType((*GoTestRequiredGroupField)(nil), "testdata.GoTestRequiredGroupField") + proto.RegisterType((*GoTestRequiredGroupField_Group)(nil), "testdata.GoTestRequiredGroupField.Group") + proto.RegisterType((*GoSkipTest)(nil), "testdata.GoSkipTest") + proto.RegisterType((*GoSkipTest_SkipGroup)(nil), "testdata.GoSkipTest.SkipGroup") + proto.RegisterType((*NonPackedTest)(nil), "testdata.NonPackedTest") + proto.RegisterType((*PackedTest)(nil), "testdata.PackedTest") + proto.RegisterType((*MaxTag)(nil), "testdata.MaxTag") + proto.RegisterType((*OldMessage)(nil), "testdata.OldMessage") + proto.RegisterType((*OldMessage_Nested)(nil), "testdata.OldMessage.Nested") + proto.RegisterType((*NewMessage)(nil), "testdata.NewMessage") + proto.RegisterType((*NewMessage_Nested)(nil), "testdata.NewMessage.Nested") + proto.RegisterType((*InnerMessage)(nil), "testdata.InnerMessage") + proto.RegisterType((*OtherMessage)(nil), "testdata.OtherMessage") + proto.RegisterType((*RequiredInnerMessage)(nil), "testdata.RequiredInnerMessage") + proto.RegisterType((*MyMessage)(nil), "testdata.MyMessage") + proto.RegisterType((*MyMessage_SomeGroup)(nil), "testdata.MyMessage.SomeGroup") + proto.RegisterType((*Ext)(nil), "testdata.Ext") + proto.RegisterType((*ComplexExtension)(nil), "testdata.ComplexExtension") + proto.RegisterType((*DefaultsMessage)(nil), "testdata.DefaultsMessage") + proto.RegisterType((*MyMessageSet)(nil), "testdata.MyMessageSet") + proto.RegisterType((*Empty)(nil), "testdata.Empty") + proto.RegisterType((*MessageList)(nil), "testdata.MessageList") + proto.RegisterType((*MessageList_Message)(nil), "testdata.MessageList.Message") + proto.RegisterType((*Strings)(nil), "testdata.Strings") + proto.RegisterType((*Defaults)(nil), "testdata.Defaults") + proto.RegisterType((*SubDefaults)(nil), "testdata.SubDefaults") + proto.RegisterType((*RepeatedEnum)(nil), "testdata.RepeatedEnum") + proto.RegisterType((*MoreRepeated)(nil), "testdata.MoreRepeated") + proto.RegisterType((*GroupOld)(nil), "testdata.GroupOld") + proto.RegisterType((*GroupOld_G)(nil), "testdata.GroupOld.G") + proto.RegisterType((*GroupNew)(nil), "testdata.GroupNew") + proto.RegisterType((*GroupNew_G)(nil), "testdata.GroupNew.G") + proto.RegisterType((*FloatingPoint)(nil), "testdata.FloatingPoint") + proto.RegisterType((*MessageWithMap)(nil), "testdata.MessageWithMap") + proto.RegisterType((*Oneof)(nil), "testdata.Oneof") + proto.RegisterType((*Oneof_F_Group)(nil), "testdata.Oneof.F_Group") + proto.RegisterType((*Communique)(nil), "testdata.Communique") + proto.RegisterEnum("testdata.FOO", FOO_name, FOO_value) + proto.RegisterEnum("testdata.GoTest_KIND", GoTest_KIND_name, GoTest_KIND_value) + proto.RegisterEnum("testdata.MyMessage_Color", MyMessage_Color_name, MyMessage_Color_value) + proto.RegisterEnum("testdata.DefaultsMessage_DefaultsEnum", DefaultsMessage_DefaultsEnum_name, DefaultsMessage_DefaultsEnum_value) + proto.RegisterEnum("testdata.Defaults_Color", Defaults_Color_name, Defaults_Color_value) + proto.RegisterEnum("testdata.RepeatedEnum_Color", RepeatedEnum_Color_name, RepeatedEnum_Color_value) + proto.RegisterExtension(E_Ext_More) + proto.RegisterExtension(E_Ext_Text) + proto.RegisterExtension(E_Ext_Number) + proto.RegisterExtension(E_Greeting) + proto.RegisterExtension(E_Complex) + proto.RegisterExtension(E_RComplex) + proto.RegisterExtension(E_NoDefaultDouble) + proto.RegisterExtension(E_NoDefaultFloat) + proto.RegisterExtension(E_NoDefaultInt32) + proto.RegisterExtension(E_NoDefaultInt64) + proto.RegisterExtension(E_NoDefaultUint32) + proto.RegisterExtension(E_NoDefaultUint64) + proto.RegisterExtension(E_NoDefaultSint32) + proto.RegisterExtension(E_NoDefaultSint64) + proto.RegisterExtension(E_NoDefaultFixed32) + proto.RegisterExtension(E_NoDefaultFixed64) + proto.RegisterExtension(E_NoDefaultSfixed32) + proto.RegisterExtension(E_NoDefaultSfixed64) + proto.RegisterExtension(E_NoDefaultBool) + proto.RegisterExtension(E_NoDefaultString) + proto.RegisterExtension(E_NoDefaultBytes) + proto.RegisterExtension(E_NoDefaultEnum) + proto.RegisterExtension(E_DefaultDouble) + proto.RegisterExtension(E_DefaultFloat) + proto.RegisterExtension(E_DefaultInt32) + proto.RegisterExtension(E_DefaultInt64) + proto.RegisterExtension(E_DefaultUint32) + proto.RegisterExtension(E_DefaultUint64) + proto.RegisterExtension(E_DefaultSint32) + proto.RegisterExtension(E_DefaultSint64) + proto.RegisterExtension(E_DefaultFixed32) + proto.RegisterExtension(E_DefaultFixed64) + proto.RegisterExtension(E_DefaultSfixed32) + proto.RegisterExtension(E_DefaultSfixed64) + proto.RegisterExtension(E_DefaultBool) + proto.RegisterExtension(E_DefaultString) + proto.RegisterExtension(E_DefaultBytes) + proto.RegisterExtension(E_DefaultEnum) + proto.RegisterExtension(E_X201) + proto.RegisterExtension(E_X202) + proto.RegisterExtension(E_X203) + proto.RegisterExtension(E_X204) + proto.RegisterExtension(E_X205) + proto.RegisterExtension(E_X206) + proto.RegisterExtension(E_X207) + proto.RegisterExtension(E_X208) + proto.RegisterExtension(E_X209) + proto.RegisterExtension(E_X210) + proto.RegisterExtension(E_X211) + proto.RegisterExtension(E_X212) + proto.RegisterExtension(E_X213) + proto.RegisterExtension(E_X214) + proto.RegisterExtension(E_X215) + proto.RegisterExtension(E_X216) + proto.RegisterExtension(E_X217) + proto.RegisterExtension(E_X218) + proto.RegisterExtension(E_X219) + proto.RegisterExtension(E_X220) + proto.RegisterExtension(E_X221) + proto.RegisterExtension(E_X222) + proto.RegisterExtension(E_X223) + proto.RegisterExtension(E_X224) + proto.RegisterExtension(E_X225) + proto.RegisterExtension(E_X226) + proto.RegisterExtension(E_X227) + proto.RegisterExtension(E_X228) + proto.RegisterExtension(E_X229) + proto.RegisterExtension(E_X230) + proto.RegisterExtension(E_X231) + proto.RegisterExtension(E_X232) + proto.RegisterExtension(E_X233) + proto.RegisterExtension(E_X234) + proto.RegisterExtension(E_X235) + proto.RegisterExtension(E_X236) + proto.RegisterExtension(E_X237) + proto.RegisterExtension(E_X238) + proto.RegisterExtension(E_X239) + proto.RegisterExtension(E_X240) + proto.RegisterExtension(E_X241) + proto.RegisterExtension(E_X242) + proto.RegisterExtension(E_X243) + proto.RegisterExtension(E_X244) + proto.RegisterExtension(E_X245) + proto.RegisterExtension(E_X246) + proto.RegisterExtension(E_X247) + proto.RegisterExtension(E_X248) + proto.RegisterExtension(E_X249) + proto.RegisterExtension(E_X250) +} + +func init() { proto.RegisterFile("test.proto", fileDescriptor0) } + +var fileDescriptor0 = []byte{ + // 4453 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x5a, 0xc9, 0x77, 0xdb, 0x48, + 0x7a, 0x37, 0xc0, 0xfd, 0x23, 0x25, 0x42, 0x65, 0xb5, 0x9b, 0x96, 0xbc, 0xc0, 0x9c, 0xe9, 0x6e, + 0x7a, 0xd3, 0x48, 0x20, 0x44, 0xdb, 0x74, 0xa7, 0xdf, 0xf3, 0x42, 0xca, 0x7a, 0x63, 0x89, 0x0a, + 0xa4, 0xee, 0x7e, 0xd3, 0x39, 0xf0, 0x51, 0x22, 0x44, 0xb3, 0x4d, 0x02, 0x34, 0x09, 0xc5, 0x52, + 0x72, 0xe9, 0x4b, 0x72, 0xcd, 0x76, 0xc9, 0x35, 0xa7, 0x9c, 0x92, 0xbc, 0x97, 0x7f, 0x22, 0xe9, + 0xee, 0x59, 0x7b, 0xd6, 0xac, 0x93, 0x7d, 0x99, 0xec, 0xdb, 0x4c, 0x92, 0x4b, 0xcf, 0xab, 0xaf, + 0x0a, 0x40, 0x01, 0x24, 0x20, 0xf9, 0x24, 0x56, 0xd5, 0xef, 0xf7, 0xd5, 0xf6, 0xab, 0xef, 0xab, + 0xaf, 0x20, 0x00, 0xc7, 0x9c, 0x38, 0x2b, 0xa3, 0xb1, 0xed, 0xd8, 0x24, 0x4b, 0x7f, 0x77, 0x3b, + 0x4e, 0xa7, 0x7c, 0x1d, 0xd2, 0x1b, 0x76, 0xc3, 0x3a, 0x1a, 0x92, 0xab, 0x90, 0x38, 0xb4, 0xed, + 0x92, 0xa4, 0xca, 0x95, 0x79, 0x6d, 0x6e, 0xc5, 0x45, 0xac, 0x34, 0x5b, 0x2d, 0x83, 0xb6, 0x94, + 0xef, 0x40, 0x7e, 0xc3, 0xde, 0x33, 0x27, 0x4e, 0xb3, 0x6f, 0x0e, 0xba, 0x64, 0x11, 0x52, 0x4f, + 0x3b, 0xfb, 0xe6, 0x00, 0x19, 0x39, 0x83, 0x15, 0x08, 0x81, 0xe4, 0xde, 0xc9, 0xc8, 0x2c, 0xc9, + 0x58, 0x89, 0xbf, 0xcb, 0xbf, 0x72, 0x85, 0x76, 0x42, 0x99, 0xe4, 0x3a, 0x24, 0xbf, 0xdc, 0xb7, + 0xba, 0xbc, 0x97, 0xd7, 0xfc, 0x5e, 0x58, 0xfb, 0xca, 0x97, 0x37, 0xb7, 0x1f, 0x1b, 0x08, 0xa1, + 0xf6, 0xf7, 0x3a, 0xfb, 0x03, 0x6a, 0x4a, 0xa2, 0xf6, 0xb1, 0x40, 0x6b, 0x77, 0x3a, 0xe3, 0xce, + 0xb0, 0x94, 0x50, 0xa5, 0x4a, 0xca, 0x60, 0x05, 0x72, 0x1f, 0xe6, 0x0c, 0xf3, 0xc5, 0x51, 0x7f, + 0x6c, 0x76, 0x71, 0x70, 0xa5, 0xa4, 0x2a, 0x57, 0xf2, 0xd3, 0xf6, 0xb1, 0xd1, 0x08, 0x62, 0x19, + 0x79, 0x64, 0x76, 0x1c, 0x97, 0x9c, 0x52, 0x13, 0xb1, 0x64, 0x01, 0x4b, 0xc9, 0xad, 0x91, 0xd3, + 0xb7, 0xad, 0xce, 0x80, 0x91, 0xd3, 0xaa, 0x14, 0x43, 0x0e, 0x60, 0xc9, 0x9b, 0x50, 0x6c, 0xb6, + 0x1f, 0xda, 0xf6, 0xa0, 0x3d, 0xe6, 0x23, 0x2a, 0x81, 0x2a, 0x57, 0xb2, 0xc6, 0x5c, 0x93, 0xd6, + 0xba, 0xc3, 0x24, 0x15, 0x50, 0x9a, 0xed, 0x4d, 0xcb, 0xa9, 0x6a, 0x3e, 0x30, 0xaf, 0xca, 0x95, + 0x94, 0x31, 0xdf, 0xc4, 0xea, 0x29, 0x64, 0x4d, 0xf7, 0x91, 0x05, 0x55, 0xae, 0x24, 0x18, 0xb2, + 0xa6, 0x7b, 0xc8, 0x5b, 0x40, 0x9a, 0xed, 0x66, 0xff, 0xd8, 0xec, 0x8a, 0x56, 0xe7, 0x54, 0xb9, + 0x92, 0x31, 0x94, 0x26, 0x6f, 0x98, 0x81, 0x16, 0x2d, 0xcf, 0xab, 0x72, 0x25, 0xed, 0xa2, 0x05, + 0xdb, 0x37, 0x60, 0xa1, 0xd9, 0x7e, 0xb7, 0x1f, 0x1c, 0x70, 0x51, 0x95, 0x2b, 0x73, 0x46, 0xb1, + 0xc9, 0xea, 0xa7, 0xb1, 0xa2, 0x61, 0x45, 0x95, 0x2b, 0x49, 0x8e, 0x15, 0xec, 0xe2, 0xec, 0x9a, + 0x03, 0xbb, 0xe3, 0xf8, 0xd0, 0x05, 0x55, 0xae, 0xc8, 0xc6, 0x7c, 0x13, 0xab, 0x83, 0x56, 0x1f, + 0xdb, 0x47, 0xfb, 0x03, 0xd3, 0x87, 0x12, 0x55, 0xae, 0x48, 0x46, 0xb1, 0xc9, 0xea, 0x83, 0xd8, + 0x5d, 0x67, 0xdc, 0xb7, 0x7a, 0x3e, 0xf6, 0x3c, 0xea, 0xb7, 0xd8, 0x64, 0xf5, 0xc1, 0x11, 0x3c, + 0x3c, 0x71, 0xcc, 0x89, 0x0f, 0x35, 0x55, 0xb9, 0x52, 0x30, 0xe6, 0x9b, 0x58, 0x1d, 0xb2, 0x1a, + 0x5a, 0x83, 0x43, 0x55, 0xae, 0x2c, 0x50, 0xab, 0x33, 0xd6, 0x60, 0x37, 0xb4, 0x06, 0x3d, 0x55, + 0xae, 0x10, 0x8e, 0x15, 0xd6, 0x40, 0xd4, 0x0c, 0x13, 0x62, 0x69, 0x51, 0x4d, 0x08, 0x9a, 0x61, + 0x95, 0x41, 0xcd, 0x70, 0xe0, 0x6b, 0x6a, 0x42, 0xd4, 0x4c, 0x08, 0x89, 0x9d, 0x73, 0xe4, 0x05, + 0x35, 0x21, 0x6a, 0x86, 0x23, 0x43, 0x9a, 0xe1, 0xd8, 0xd7, 0xd5, 0x44, 0x50, 0x33, 0x53, 0x68, + 0xd1, 0x72, 0x49, 0x4d, 0x04, 0x35, 0xc3, 0xd1, 0x41, 0xcd, 0x70, 0xf0, 0x45, 0x35, 0x11, 0xd0, + 0x4c, 0x18, 0x2b, 0x1a, 0x5e, 0x52, 0x13, 0x01, 0xcd, 0x88, 0xb3, 0x73, 0x35, 0xc3, 0xa1, 0xcb, + 0x6a, 0x42, 0xd4, 0x8c, 0x68, 0xd5, 0xd3, 0x0c, 0x87, 0x5e, 0x52, 0x13, 0x01, 0xcd, 0x88, 0x58, + 0x4f, 0x33, 0x1c, 0x7b, 0x59, 0x4d, 0x04, 0x34, 0xc3, 0xb1, 0xd7, 0x45, 0xcd, 0x70, 0xe8, 0xc7, + 0x92, 0x9a, 0x10, 0x45, 0xc3, 0xa1, 0x37, 0x03, 0xa2, 0xe1, 0xd8, 0x4f, 0x28, 0x56, 0x54, 0x4d, + 0x18, 0x2c, 0xae, 0xc2, 0xa7, 0x14, 0x2c, 0xca, 0x86, 0x83, 0x7d, 0xd9, 0xd8, 0xdc, 0x05, 0x95, + 0xae, 0xa8, 0x92, 0x27, 0x1b, 0xd7, 0x2f, 0x89, 0xb2, 0xf1, 0x80, 0x57, 0xd1, 0xd5, 0x72, 0xd9, + 0x4c, 0x21, 0x6b, 0xba, 0x8f, 0x54, 0x55, 0xc9, 0x97, 0x8d, 0x87, 0x0c, 0xc8, 0xc6, 0xc3, 0x5e, + 0x53, 0x25, 0x51, 0x36, 0x33, 0xd0, 0xa2, 0xe5, 0xb2, 0x2a, 0x89, 0xb2, 0xf1, 0xd0, 0xa2, 0x6c, + 0x3c, 0xf0, 0x17, 0x54, 0x49, 0x90, 0xcd, 0x34, 0x56, 0x34, 0xfc, 0x45, 0x55, 0x12, 0x64, 0x13, + 0x9c, 0x1d, 0x93, 0x8d, 0x07, 0x7d, 0x43, 0x95, 0x7c, 0xd9, 0x04, 0xad, 0x72, 0xd9, 0x78, 0xd0, + 0x37, 0x55, 0x49, 0x90, 0x4d, 0x10, 0xcb, 0x65, 0xe3, 0x61, 0xdf, 0xc2, 0xf8, 0xe6, 0xca, 0xc6, + 0xc3, 0x0a, 0xb2, 0xf1, 0xa0, 0xbf, 0x43, 0x63, 0xa1, 0x27, 0x1b, 0x0f, 0x2a, 0xca, 0xc6, 0xc3, + 0xfe, 0x2e, 0xc5, 0xfa, 0xb2, 0x99, 0x06, 0x8b, 0xab, 0xf0, 0x7b, 0x14, 0xec, 0xcb, 0xc6, 0x03, + 0xaf, 0xe0, 0x20, 0xa8, 0x6c, 0xba, 0xe6, 0x61, 0xe7, 0x68, 0x40, 0x25, 0x56, 0xa1, 0xba, 0xa9, + 0x27, 0x9d, 0xf1, 0x91, 0x49, 0x47, 0x62, 0xdb, 0x83, 0xc7, 0x6e, 0x1b, 0x59, 0xa1, 0xc6, 0x99, + 0x7c, 0x7c, 0xc2, 0x75, 0xaa, 0x9f, 0xba, 0x5c, 0xd5, 0x8c, 0x22, 0xd3, 0xd0, 0x34, 0xbe, 0xa6, + 0x0b, 0xf8, 0x1b, 0x54, 0x45, 0x75, 0xb9, 0xa6, 0x33, 0x7c, 0x4d, 0xf7, 0xf1, 0x55, 0x38, 0xef, + 0x4b, 0xc9, 0x67, 0xdc, 0xa4, 0x5a, 0xaa, 0x27, 0xaa, 0xda, 0xaa, 0xb1, 0xe0, 0x0a, 0x6a, 0x16, + 0x29, 0xd0, 0xcd, 0x2d, 0x2a, 0xa9, 0x7a, 0xa2, 0xa6, 0x7b, 0x24, 0xb1, 0x27, 0x8d, 0xca, 0x90, + 0x0b, 0xcb, 0xe7, 0xdc, 0xa6, 0xca, 0xaa, 0x27, 0xab, 0xda, 0xea, 0xaa, 0xa1, 0x70, 0x7d, 0xcd, + 0xe0, 0x04, 0xfa, 0x59, 0xa1, 0x0a, 0xab, 0x27, 0x6b, 0xba, 0xc7, 0x09, 0xf6, 0xb3, 0xe0, 0x0a, + 0xcd, 0xa7, 0x7c, 0x89, 0x2a, 0xad, 0x9e, 0xae, 0xae, 0xe9, 0x6b, 0xeb, 0xf7, 0x8c, 0x22, 0x53, + 0x9c, 0xcf, 0xd1, 0x69, 0x3f, 0x5c, 0x72, 0x3e, 0x69, 0x95, 0x6a, 0xae, 0x9e, 0xd6, 0xee, 0xac, + 0xdd, 0xd5, 0xee, 0x1a, 0x0a, 0xd7, 0x9e, 0xcf, 0x7a, 0x87, 0xb2, 0xb8, 0xf8, 0x7c, 0xd6, 0x1a, + 0x55, 0x5f, 0x5d, 0x79, 0x66, 0x0e, 0x06, 0xf6, 0x2d, 0xb5, 0xfc, 0xd2, 0x1e, 0x0f, 0xba, 0xd7, + 0xca, 0x60, 0x28, 0x5c, 0x8f, 0x62, 0xaf, 0x0b, 0xae, 0x20, 0x7d, 0xfa, 0xaf, 0xd1, 0x7b, 0x58, + 0xa1, 0x9e, 0x79, 0xd8, 0xef, 0x59, 0xf6, 0xc4, 0x34, 0x8a, 0x4c, 0x9a, 0xa1, 0x35, 0xd9, 0x0d, + 0xaf, 0xe3, 0xaf, 0x53, 0xda, 0x42, 0x3d, 0x71, 0xbb, 0xaa, 0xd1, 0x9e, 0x66, 0xad, 0xe3, 0x6e, + 0x78, 0x1d, 0x7f, 0x83, 0x72, 0x48, 0x3d, 0x71, 0xbb, 0xa6, 0x73, 0x8e, 0xb8, 0x8e, 0x77, 0xe0, + 0x42, 0x28, 0x2e, 0xb6, 0x47, 0x9d, 0x83, 0xe7, 0x66, 0xb7, 0xa4, 0xd1, 0xf0, 0xf8, 0x50, 0x56, + 0x24, 0xe3, 0x7c, 0x20, 0x44, 0xee, 0x60, 0x33, 0xb9, 0x07, 0xaf, 0x87, 0x03, 0xa5, 0xcb, 0xac, + 0xd2, 0x78, 0x89, 0xcc, 0xc5, 0x60, 0xcc, 0x0c, 0x51, 0x05, 0x07, 0xec, 0x52, 0x75, 0x1a, 0x40, + 0x7d, 0xaa, 0xef, 0x89, 0x39, 0xf5, 0x67, 0xe0, 0xe2, 0x74, 0x28, 0x75, 0xc9, 0xeb, 0x34, 0xa2, + 0x22, 0xf9, 0x42, 0x38, 0xaa, 0x4e, 0xd1, 0x67, 0xf4, 0x5d, 0xa3, 0x21, 0x56, 0xa4, 0x4f, 0xf5, + 0x7e, 0x1f, 0x4a, 0x53, 0xc1, 0xd6, 0x65, 0xdf, 0xa1, 0x31, 0x17, 0xd9, 0xaf, 0x85, 0xe2, 0x6e, + 0x98, 0x3c, 0xa3, 0xeb, 0xbb, 0x34, 0x08, 0x0b, 0xe4, 0xa9, 0x9e, 0x71, 0xc9, 0x82, 0xe1, 0xd8, + 0xe5, 0xde, 0xa3, 0x51, 0x99, 0x2f, 0x59, 0x20, 0x32, 0x8b, 0xfd, 0x86, 0xe2, 0xb3, 0xcb, 0xad, + 0xd3, 0x30, 0xcd, 0xfb, 0x0d, 0x86, 0x6a, 0x4e, 0x7e, 0x9b, 0x92, 0x77, 0x67, 0xcf, 0xf8, 0xc7, + 0x09, 0x1a, 0x60, 0x39, 0x7b, 0x77, 0xd6, 0x94, 0x3d, 0xf6, 0x8c, 0x29, 0xff, 0x84, 0xb2, 0x89, + 0xc0, 0x9e, 0x9a, 0xf3, 0x63, 0x98, 0x73, 0x6f, 0x75, 0xbd, 0xb1, 0x7d, 0x34, 0x2a, 0x35, 0x55, + 0xb9, 0x02, 0xda, 0x95, 0xa9, 0xec, 0xc7, 0xbd, 0xe4, 0x6d, 0x50, 0x94, 0x11, 0x24, 0x31, 0x2b, + 0xcc, 0x2e, 0xb3, 0xb2, 0xa3, 0x26, 0x22, 0xac, 0x30, 0x94, 0x67, 0x45, 0x20, 0x51, 0x2b, 0xae, + 0xd3, 0x67, 0x56, 0x3e, 0x50, 0xa5, 0x99, 0x56, 0xdc, 0x10, 0xc0, 0xad, 0x04, 0x48, 0x4b, 0xeb, + 0x7e, 0xbe, 0x85, 0xed, 0xe4, 0x8b, 0xe1, 0x04, 0x6c, 0x03, 0xef, 0xcf, 0xc1, 0x4a, 0x46, 0x13, + 0x06, 0x37, 0x4d, 0xfb, 0xd9, 0x08, 0x5a, 0x60, 0x34, 0xd3, 0xb4, 0x9f, 0x9b, 0x41, 0x2b, 0xff, + 0xa6, 0x04, 0x49, 0x9a, 0x4f, 0x92, 0x2c, 0x24, 0xdf, 0x6b, 0x6d, 0x3e, 0x56, 0xce, 0xd1, 0x5f, + 0x0f, 0x5b, 0xad, 0xa7, 0x8a, 0x44, 0x72, 0x90, 0x7a, 0xf8, 0x95, 0xbd, 0xc6, 0xae, 0x22, 0x93, + 0x22, 0xe4, 0x9b, 0x9b, 0xdb, 0x1b, 0x0d, 0x63, 0xc7, 0xd8, 0xdc, 0xde, 0x53, 0x12, 0xb4, 0xad, + 0xf9, 0xb4, 0xf5, 0x60, 0x4f, 0x49, 0x92, 0x0c, 0x24, 0x68, 0x5d, 0x8a, 0x00, 0xa4, 0x77, 0xf7, + 0x8c, 0xcd, 0xed, 0x0d, 0x25, 0x4d, 0xad, 0xec, 0x6d, 0x6e, 0x35, 0x94, 0x0c, 0x45, 0xee, 0xbd, + 0xbb, 0xf3, 0xb4, 0xa1, 0x64, 0xe9, 0xcf, 0x07, 0x86, 0xf1, 0xe0, 0x2b, 0x4a, 0x8e, 0x92, 0xb6, + 0x1e, 0xec, 0x28, 0x80, 0xcd, 0x0f, 0x1e, 0x3e, 0x6d, 0x28, 0x79, 0x52, 0x80, 0x6c, 0xf3, 0xdd, + 0xed, 0x47, 0x7b, 0x9b, 0xad, 0x6d, 0xa5, 0x50, 0x3e, 0x81, 0x12, 0x5b, 0xe6, 0xc0, 0x2a, 0xb2, + 0xa4, 0xf0, 0x1d, 0x48, 0xb1, 0x9d, 0x91, 0x50, 0x25, 0x95, 0xf0, 0xce, 0x4c, 0x53, 0x56, 0xd8, + 0x1e, 0x31, 0xda, 0xd2, 0x65, 0x48, 0xb1, 0x55, 0x5a, 0x84, 0x14, 0x5b, 0x1d, 0x19, 0x53, 0x45, + 0x56, 0x28, 0xff, 0x96, 0x0c, 0xb0, 0x61, 0xef, 0x3e, 0xef, 0x8f, 0x30, 0x21, 0xbf, 0x0c, 0x30, + 0x79, 0xde, 0x1f, 0xb5, 0x51, 0xf5, 0x3c, 0xa9, 0xcc, 0xd1, 0x1a, 0xf4, 0x77, 0xe4, 0x1a, 0x14, + 0xb0, 0xf9, 0x90, 0x79, 0x21, 0xcc, 0x25, 0x33, 0x46, 0x9e, 0xd6, 0x71, 0xc7, 0x14, 0x84, 0xd4, + 0x74, 0x4c, 0x21, 0xd3, 0x02, 0xa4, 0xa6, 0x93, 0xab, 0x80, 0xc5, 0xf6, 0x04, 0x23, 0x0a, 0xa6, + 0x8d, 0x39, 0x03, 0xfb, 0x65, 0x31, 0x86, 0xbc, 0x0d, 0xd8, 0x27, 0x9b, 0x77, 0x71, 0xfa, 0x74, + 0xb8, 0xc3, 0x5d, 0xa1, 0x3f, 0xd8, 0x6c, 0x7d, 0xc2, 0x52, 0x0b, 0x72, 0x5e, 0x3d, 0xed, 0x0b, + 0x6b, 0xf9, 0x8c, 0x14, 0x9c, 0x11, 0x60, 0x95, 0x37, 0x25, 0x06, 0xe0, 0xa3, 0x59, 0xc0, 0xd1, + 0x30, 0x12, 0x1b, 0x4e, 0xf9, 0x32, 0xcc, 0x6d, 0xdb, 0x16, 0x3b, 0xbd, 0xb8, 0x4a, 0x05, 0x90, + 0x3a, 0x25, 0x09, 0xb3, 0x27, 0xa9, 0x53, 0xbe, 0x02, 0x20, 0xb4, 0x29, 0x20, 0xed, 0xb3, 0x36, + 0xf4, 0x01, 0xd2, 0x7e, 0xf9, 0x26, 0xa4, 0xb7, 0x3a, 0xc7, 0x7b, 0x9d, 0x1e, 0xb9, 0x06, 0x30, + 0xe8, 0x4c, 0x9c, 0xf6, 0x21, 0xee, 0xc3, 0xe7, 0x9f, 0x7f, 0xfe, 0xb9, 0x84, 0x97, 0xbd, 0x1c, + 0xad, 0x65, 0xfb, 0xf1, 0x02, 0xa0, 0x35, 0xe8, 0x6e, 0x99, 0x93, 0x49, 0xa7, 0x67, 0x92, 0x2a, + 0xa4, 0x2d, 0x73, 0x42, 0xa3, 0x9d, 0x84, 0xef, 0x08, 0xcb, 0xfe, 0x2a, 0xf8, 0xa8, 0x95, 0x6d, + 0x84, 0x18, 0x1c, 0x4a, 0x14, 0x48, 0x58, 0x47, 0x43, 0x7c, 0x27, 0x49, 0x19, 0xf4, 0xe7, 0xd2, + 0x25, 0x48, 0x33, 0x0c, 0x21, 0x90, 0xb4, 0x3a, 0x43, 0xb3, 0xc4, 0xfa, 0xc5, 0xdf, 0xe5, 0x5f, + 0x95, 0x00, 0xb6, 0xcd, 0x97, 0x67, 0xe8, 0xd3, 0x47, 0xc5, 0xf4, 0x99, 0x60, 0x7d, 0xde, 0x8f, + 0xeb, 0x93, 0xea, 0xec, 0xd0, 0xb6, 0xbb, 0x6d, 0xb6, 0xc5, 0xec, 0x49, 0x27, 0x47, 0x6b, 0x70, + 0xd7, 0xca, 0x1f, 0x40, 0x61, 0xd3, 0xb2, 0xcc, 0xb1, 0x3b, 0x26, 0x02, 0xc9, 0x67, 0xf6, 0xc4, + 0xe1, 0x6f, 0x4b, 0xf8, 0x9b, 0x94, 0x20, 0x39, 0xb2, 0xc7, 0x0e, 0x9b, 0x67, 0x3d, 0xa9, 0xaf, + 0xae, 0xae, 0x1a, 0x58, 0x43, 0x2e, 0x41, 0xee, 0xc0, 0xb6, 0x2c, 0xf3, 0x80, 0x4e, 0x22, 0x81, + 0x69, 0x8d, 0x5f, 0x51, 0xfe, 0x65, 0x09, 0x0a, 0x2d, 0xe7, 0x99, 0x6f, 0x5c, 0x81, 0xc4, 0x73, + 0xf3, 0x04, 0x87, 0x97, 0x30, 0xe8, 0x4f, 0x7a, 0x54, 0x7e, 0xbe, 0x33, 0x38, 0x62, 0x6f, 0x4d, + 0x05, 0x83, 0x15, 0xc8, 0x05, 0x48, 0xbf, 0x34, 0xfb, 0xbd, 0x67, 0x0e, 0xda, 0x94, 0x0d, 0x5e, + 0x22, 0xb7, 0x20, 0xd5, 0xa7, 0x83, 0x2d, 0x25, 0x71, 0xbd, 0x2e, 0xf8, 0xeb, 0x25, 0xce, 0xc1, + 0x60, 0xa0, 0x1b, 0xd9, 0x6c, 0x57, 0xf9, 0xe8, 0xa3, 0x8f, 0x3e, 0x92, 0xcb, 0x87, 0xb0, 0xe8, + 0x1e, 0xde, 0xc0, 0x64, 0xb7, 0xa1, 0x34, 0x30, 0xed, 0xf6, 0x61, 0xdf, 0xea, 0x0c, 0x06, 0x27, + 0xed, 0x97, 0xb6, 0xd5, 0xee, 0x58, 0x6d, 0x7b, 0x72, 0xd0, 0x19, 0xe3, 0x02, 0x44, 0x77, 0xb1, + 0x38, 0x30, 0xed, 0x26, 0xa3, 0xbd, 0x6f, 0x5b, 0x0f, 0xac, 0x16, 0xe5, 0x94, 0xff, 0x20, 0x09, + 0xb9, 0xad, 0x13, 0xd7, 0xfa, 0x22, 0xa4, 0x0e, 0xec, 0x23, 0x8b, 0xad, 0x65, 0xca, 0x60, 0x05, + 0x6f, 0x8f, 0x64, 0x61, 0x8f, 0x16, 0x21, 0xf5, 0xe2, 0xc8, 0x76, 0x4c, 0x9c, 0x6e, 0xce, 0x60, + 0x05, 0xba, 0x5a, 0x23, 0xd3, 0x29, 0x25, 0x31, 0xb9, 0xa5, 0x3f, 0xfd, 0xf9, 0xa7, 0xce, 0x30, + 0x7f, 0xb2, 0x02, 0x69, 0x9b, 0xae, 0xfe, 0xa4, 0x94, 0xc6, 0x77, 0x35, 0x01, 0x2e, 0xee, 0x8a, + 0xc1, 0x51, 0x64, 0x13, 0x16, 0x5e, 0x9a, 0xed, 0xe1, 0xd1, 0xc4, 0x69, 0xf7, 0xec, 0x76, 0xd7, + 0x34, 0x47, 0xe6, 0xb8, 0x34, 0x87, 0x3d, 0x09, 0x3e, 0x61, 0xd6, 0x42, 0x1a, 0xf3, 0x2f, 0xcd, + 0xad, 0xa3, 0x89, 0xb3, 0x61, 0x3f, 0x46, 0x16, 0xa9, 0x42, 0x6e, 0x6c, 0x52, 0x4f, 0x40, 0x07, + 0x5b, 0x08, 0xf7, 0x1e, 0xa0, 0x66, 0xc7, 0xe6, 0x08, 0x2b, 0xc8, 0x3a, 0x64, 0xf7, 0xfb, 0xcf, + 0xcd, 0xc9, 0x33, 0xb3, 0x5b, 0xca, 0xa8, 0x52, 0x65, 0x5e, 0xbb, 0xe8, 0x73, 0xbc, 0x65, 0x5d, + 0x79, 0x64, 0x0f, 0xec, 0xb1, 0xe1, 0x41, 0xc9, 0x7d, 0xc8, 0x4d, 0xec, 0xa1, 0xc9, 0xf4, 0x9d, + 0xc5, 0xa0, 0x7a, 0x79, 0x16, 0x6f, 0xd7, 0x1e, 0x9a, 0xae, 0x07, 0x73, 0xf1, 0x64, 0x99, 0x0d, + 0x74, 0x9f, 0x5e, 0x9d, 0x4b, 0x80, 0x4f, 0x03, 0x74, 0x40, 0x78, 0x95, 0x26, 0x4b, 0x74, 0x40, + 0xbd, 0x43, 0x7a, 0x23, 0x2a, 0xe5, 0x31, 0xaf, 0xf4, 0xca, 0x4b, 0xb7, 0x20, 0xe7, 0x19, 0xf4, + 0x5d, 0x1f, 0x73, 0x37, 0x39, 0xf4, 0x07, 0xcc, 0xf5, 0x31, 0x5f, 0xf3, 0x06, 0xa4, 0x70, 0xd8, + 0x34, 0x42, 0x19, 0x0d, 0x1a, 0x10, 0x73, 0x90, 0xda, 0x30, 0x1a, 0x8d, 0x6d, 0x45, 0xc2, 0xd8, + 0xf8, 0xf4, 0xdd, 0x86, 0x22, 0x0b, 0x8a, 0xfd, 0x6d, 0x09, 0x12, 0x8d, 0x63, 0x54, 0x0b, 0x9d, + 0x86, 0x7b, 0xa2, 0xe9, 0x6f, 0xad, 0x06, 0xc9, 0xa1, 0x3d, 0x36, 0xc9, 0xf9, 0x19, 0xb3, 0x2c, + 0xf5, 0x70, 0xbf, 0x84, 0x57, 0xe4, 0xc6, 0xb1, 0x63, 0x20, 0x5e, 0x7b, 0x0b, 0x92, 0x8e, 0x79, + 0xec, 0xcc, 0xe6, 0x3d, 0x63, 0x1d, 0x50, 0x80, 0x76, 0x13, 0xd2, 0xd6, 0xd1, 0x70, 0xdf, 0x1c, + 0xcf, 0x86, 0xf6, 0x71, 0x7a, 0x1c, 0x52, 0x7e, 0x0f, 0x94, 0x47, 0xf6, 0x70, 0x34, 0x30, 0x8f, + 0x1b, 0xc7, 0x8e, 0x69, 0x4d, 0xfa, 0xb6, 0x45, 0xf5, 0x7c, 0xd8, 0x1f, 0xa3, 0x17, 0xc1, 0xb7, + 0x62, 0x2c, 0xd0, 0x53, 0x3d, 0x31, 0x0f, 0x6c, 0xab, 0xcb, 0x1d, 0x26, 0x2f, 0x51, 0xb4, 0xf3, + 0xac, 0x3f, 0xa6, 0x0e, 0x84, 0xfa, 0x79, 0x56, 0x28, 0x6f, 0x40, 0x91, 0xe7, 0x18, 0x13, 0xde, + 0x71, 0xf9, 0x06, 0x14, 0xdc, 0x2a, 0x7c, 0x38, 0xcf, 0x42, 0xf2, 0x83, 0x86, 0xd1, 0x52, 0xce, + 0xd1, 0x65, 0x6d, 0x6d, 0x37, 0x14, 0x89, 0xfe, 0xd8, 0x7b, 0xbf, 0x15, 0x58, 0xca, 0x4b, 0x50, + 0xf0, 0xc6, 0xbe, 0x6b, 0x3a, 0xd8, 0x42, 0x03, 0x42, 0xa6, 0x2e, 0x67, 0xa5, 0x72, 0x06, 0x52, + 0x8d, 0xe1, 0xc8, 0x39, 0x29, 0xff, 0x22, 0xe4, 0x39, 0xe8, 0x69, 0x7f, 0xe2, 0x90, 0x3b, 0x90, + 0x19, 0xf2, 0xf9, 0x4a, 0x78, 0xdd, 0x13, 0x35, 0xe5, 0xe3, 0xdc, 0xdf, 0x86, 0x8b, 0x5e, 0xaa, + 0x42, 0x46, 0xf0, 0xa5, 0xfc, 0xa8, 0xcb, 0xe2, 0x51, 0x67, 0x4e, 0x21, 0x21, 0x38, 0x85, 0xf2, + 0x16, 0x64, 0x58, 0x04, 0x9c, 0x60, 0x54, 0x67, 0xa9, 0x22, 0x13, 0x13, 0xdb, 0xf9, 0x3c, 0xab, + 0x63, 0x17, 0x95, 0xab, 0x90, 0x47, 0xc1, 0x72, 0x04, 0x73, 0x9d, 0x80, 0x55, 0x4c, 0x6e, 0xbf, + 0x9f, 0x82, 0xac, 0xbb, 0x52, 0x64, 0x19, 0xd2, 0x2c, 0x3f, 0x43, 0x53, 0xee, 0xfb, 0x41, 0x0a, + 0x33, 0x32, 0xb2, 0x0c, 0x19, 0x9e, 0x83, 0x71, 0xef, 0x2e, 0x57, 0x35, 0x23, 0xcd, 0x72, 0x2e, + 0xaf, 0xb1, 0xa6, 0xa3, 0x63, 0x62, 0x2f, 0x03, 0x69, 0x96, 0x55, 0x11, 0x15, 0x72, 0x5e, 0x1e, + 0x85, 0xfe, 0x98, 0x3f, 0x03, 0x64, 0xdd, 0xc4, 0x49, 0x40, 0xd4, 0x74, 0xf4, 0x58, 0x3c, 0xe7, + 0xcf, 0x36, 0xfd, 0xeb, 0x49, 0xd6, 0xcd, 0x86, 0xf0, 0xf9, 0xde, 0x4d, 0xf0, 0x33, 0x3c, 0xff, + 0xf1, 0x01, 0x35, 0x1d, 0x5d, 0x82, 0x9b, 0xcd, 0x67, 0x78, 0x8e, 0x43, 0xae, 0xd2, 0x21, 0x62, + 0xce, 0x82, 0x47, 0xdf, 0x4f, 0xdd, 0xd3, 0x2c, 0x93, 0x21, 0xd7, 0xa8, 0x05, 0x96, 0x98, 0xe0, + 0xb9, 0xf4, 0xf3, 0xf4, 0x0c, 0xcf, 0x57, 0xc8, 0x4d, 0x0a, 0x61, 0xcb, 0x5f, 0x82, 0x88, 0xa4, + 0x3c, 0xc3, 0x93, 0x72, 0xa2, 0xd2, 0x0e, 0xd1, 0x3d, 0xa0, 0x4b, 0x10, 0x12, 0xf0, 0x34, 0x4b, + 0xc0, 0xc9, 0x15, 0x34, 0xc7, 0x26, 0x55, 0xf0, 0x93, 0xed, 0x0c, 0x4f, 0x70, 0xfc, 0x76, 0xbc, + 0xb2, 0x79, 0x89, 0x75, 0x86, 0xa7, 0x30, 0xa4, 0x46, 0xf7, 0x8b, 0xea, 0xbb, 0x34, 0x8f, 0x4e, + 0xb0, 0xe4, 0x0b, 0xcf, 0xdd, 0x53, 0xe6, 0x03, 0xeb, 0xcc, 0x83, 0x18, 0xa9, 0x26, 0x9e, 0x86, + 0x25, 0xca, 0xdb, 0xe9, 0x5b, 0x87, 0xa5, 0x22, 0xae, 0x44, 0xa2, 0x6f, 0x1d, 0x1a, 0xa9, 0x26, + 0xad, 0x61, 0x1a, 0xd8, 0xa6, 0x6d, 0x0a, 0xb6, 0x25, 0x6f, 0xb3, 0x46, 0x5a, 0x45, 0x4a, 0x90, + 0x6a, 0xb6, 0xb7, 0x3b, 0x56, 0x69, 0x81, 0xf1, 0xac, 0x8e, 0x65, 0x24, 0x9b, 0xdb, 0x1d, 0x8b, + 0xbc, 0x05, 0x89, 0xc9, 0xd1, 0x7e, 0x89, 0x84, 0xbf, 0xac, 0xec, 0x1e, 0xed, 0xbb, 0x43, 0x31, + 0x28, 0x82, 0x2c, 0x43, 0x76, 0xe2, 0x8c, 0xdb, 0xbf, 0x60, 0x8e, 0xed, 0xd2, 0x79, 0x5c, 0xc2, + 0x73, 0x46, 0x66, 0xe2, 0x8c, 0x3f, 0x30, 0xc7, 0xf6, 0x19, 0x9d, 0x5f, 0xf9, 0x0a, 0xe4, 0x05, + 0xbb, 0xa4, 0x08, 0x92, 0xc5, 0x6e, 0x0a, 0x75, 0xe9, 0x8e, 0x21, 0x59, 0xe5, 0x3d, 0x28, 0xb8, + 0x39, 0x0c, 0xce, 0x57, 0xa3, 0x27, 0x69, 0x60, 0x8f, 0xf1, 0x7c, 0xce, 0x6b, 0x97, 0xc4, 0x10, + 0xe5, 0xc3, 0x78, 0xb8, 0x60, 0xd0, 0xb2, 0x12, 0x1a, 0x8a, 0x54, 0xfe, 0xa1, 0x04, 0x85, 0x2d, + 0x7b, 0xec, 0x3f, 0x30, 0x2f, 0x42, 0x6a, 0xdf, 0xb6, 0x07, 0x13, 0x34, 0x9b, 0x35, 0x58, 0x81, + 0xbc, 0x01, 0x05, 0xfc, 0xe1, 0xe6, 0x9e, 0xb2, 0xf7, 0xb4, 0x91, 0xc7, 0x7a, 0x9e, 0x70, 0x12, + 0x48, 0xf6, 0x2d, 0x67, 0xc2, 0x3d, 0x19, 0xfe, 0x26, 0x5f, 0x80, 0x3c, 0xfd, 0xeb, 0x32, 0x93, + 0xde, 0x85, 0x15, 0x68, 0x35, 0x27, 0xbe, 0x05, 0x73, 0xb8, 0xfb, 0x1e, 0x2c, 0xe3, 0x3d, 0x63, + 0x14, 0x58, 0x03, 0x07, 0x96, 0x20, 0xc3, 0x5c, 0xc1, 0x04, 0xbf, 0x96, 0xe5, 0x0c, 0xb7, 0x48, + 0xdd, 0x2b, 0x66, 0x02, 0x2c, 0xdc, 0x67, 0x0c, 0x5e, 0x2a, 0x3f, 0x80, 0x2c, 0x46, 0xa9, 0xd6, + 0xa0, 0x4b, 0xca, 0x20, 0xf5, 0x4a, 0x26, 0xc6, 0xc8, 0x45, 0xe1, 0x9a, 0xcf, 0x9b, 0x57, 0x36, + 0x0c, 0xa9, 0xb7, 0xb4, 0x00, 0xd2, 0x06, 0xbd, 0x77, 0x1f, 0x73, 0x37, 0x2d, 0x1d, 0x97, 0x5b, + 0xdc, 0xc4, 0xb6, 0xf9, 0x32, 0xce, 0xc4, 0xb6, 0xf9, 0x92, 0x99, 0xb8, 0x3a, 0x65, 0x82, 0x96, + 0x4e, 0xf8, 0xa7, 0x43, 0xe9, 0xa4, 0x5c, 0x85, 0x39, 0x3c, 0x9e, 0x7d, 0xab, 0xb7, 0x63, 0xf7, + 0x2d, 0xbc, 0xe7, 0x1f, 0xe2, 0x3d, 0x49, 0x32, 0xa4, 0x43, 0xba, 0x07, 0xe6, 0x71, 0xe7, 0x80, + 0xdd, 0x38, 0xb3, 0x06, 0x2b, 0x94, 0x3f, 0x4b, 0xc2, 0x3c, 0x77, 0xad, 0xef, 0xf7, 0x9d, 0x67, + 0x5b, 0x9d, 0x11, 0x79, 0x0a, 0x05, 0xea, 0x55, 0xdb, 0xc3, 0xce, 0x68, 0x44, 0x8f, 0xaf, 0x84, + 0x57, 0x8d, 0xeb, 0x53, 0xae, 0x9a, 0xe3, 0x57, 0xb6, 0x3b, 0x43, 0x73, 0x8b, 0x61, 0x1b, 0x96, + 0x33, 0x3e, 0x31, 0xf2, 0x96, 0x5f, 0x43, 0x36, 0x21, 0x3f, 0x9c, 0xf4, 0x3c, 0x63, 0x32, 0x1a, + 0xab, 0x44, 0x1a, 0xdb, 0x9a, 0xf4, 0x02, 0xb6, 0x60, 0xe8, 0x55, 0xd0, 0x81, 0x51, 0x7f, 0xec, + 0xd9, 0x4a, 0x9c, 0x32, 0x30, 0xea, 0x3a, 0x82, 0x03, 0xdb, 0xf7, 0x6b, 0xc8, 0x63, 0x00, 0x7a, + 0xbc, 0x1c, 0x9b, 0xa6, 0x4e, 0xa8, 0xa0, 0xbc, 0xf6, 0x66, 0xa4, 0xad, 0x5d, 0x67, 0xbc, 0x67, + 0xef, 0x3a, 0x63, 0x66, 0x88, 0x1e, 0x4c, 0x2c, 0x2e, 0xbd, 0x03, 0x4a, 0x78, 0xfe, 0xe2, 0x8d, + 0x3c, 0x35, 0xe3, 0x46, 0x9e, 0xe3, 0x37, 0xf2, 0xba, 0x7c, 0x57, 0x5a, 0x7a, 0x0f, 0x8a, 0xa1, + 0x29, 0x8b, 0x74, 0xc2, 0xe8, 0xb7, 0x45, 0x7a, 0x5e, 0x7b, 0x5d, 0xf8, 0x9c, 0x2d, 0x6e, 0xb8, + 0x68, 0xf7, 0x1d, 0x50, 0xc2, 0xd3, 0x17, 0x0d, 0x67, 0x63, 0x32, 0x05, 0xe4, 0xdf, 0x87, 0xb9, + 0xc0, 0x94, 0x45, 0x72, 0xee, 0x94, 0x49, 0x95, 0x7f, 0x29, 0x05, 0xa9, 0x96, 0x65, 0xda, 0x87, + 0xe4, 0xf5, 0x60, 0x9c, 0x7c, 0x72, 0xce, 0x8d, 0x91, 0x17, 0x43, 0x31, 0xf2, 0xc9, 0x39, 0x2f, + 0x42, 0x5e, 0x0c, 0x45, 0x48, 0xb7, 0xa9, 0xa6, 0x93, 0xcb, 0x53, 0xf1, 0xf1, 0xc9, 0x39, 0x21, + 0x38, 0x5e, 0x9e, 0x0a, 0x8e, 0x7e, 0x73, 0x4d, 0xa7, 0x0e, 0x35, 0x18, 0x19, 0x9f, 0x9c, 0xf3, + 0xa3, 0xe2, 0x72, 0x38, 0x2a, 0x7a, 0x8d, 0x35, 0x9d, 0x0d, 0x49, 0x88, 0x88, 0x38, 0x24, 0x16, + 0x0b, 0x97, 0xc3, 0xb1, 0x10, 0x79, 0x3c, 0x0a, 0x2e, 0x87, 0xa3, 0x20, 0x36, 0xf2, 0xa8, 0x77, + 0x31, 0x14, 0xf5, 0xd0, 0x28, 0x0b, 0x77, 0xcb, 0xe1, 0x70, 0xc7, 0x78, 0xc2, 0x48, 0xc5, 0x58, + 0xe7, 0x35, 0xd6, 0x74, 0xa2, 0x85, 0x02, 0x5d, 0xf4, 0x6d, 0x1f, 0xf7, 0x02, 0x9d, 0xbe, 0x4e, + 0x97, 0xcd, 0xbd, 0x88, 0x16, 0x63, 0xbe, 0xf8, 0xe3, 0x6a, 0xba, 0x17, 0x31, 0x0d, 0x32, 0x87, + 0x3c, 0x01, 0x56, 0xd0, 0x73, 0x09, 0xb2, 0xc4, 0xcd, 0x5f, 0x69, 0xb6, 0xd1, 0x83, 0xd1, 0x79, + 0x1d, 0xb2, 0x3b, 0x7d, 0x05, 0xe6, 0x9a, 0xed, 0xa7, 0x9d, 0x71, 0xcf, 0x9c, 0x38, 0xed, 0xbd, + 0x4e, 0xcf, 0x7b, 0x44, 0xa0, 0xfb, 0x9f, 0x6f, 0xf2, 0x96, 0xbd, 0x4e, 0x8f, 0x5c, 0x70, 0xc5, + 0xd5, 0xc5, 0x56, 0x89, 0xcb, 0x6b, 0xe9, 0x75, 0xba, 0x68, 0xcc, 0x18, 0xfa, 0xc2, 0x05, 0xee, + 0x0b, 0x1f, 0x66, 0x20, 0x75, 0x64, 0xf5, 0x6d, 0xeb, 0x61, 0x0e, 0x32, 0x8e, 0x3d, 0x1e, 0x76, + 0x1c, 0xbb, 0xfc, 0x23, 0x09, 0xe0, 0x91, 0x3d, 0x1c, 0x1e, 0x59, 0xfd, 0x17, 0x47, 0x26, 0xb9, + 0x02, 0xf9, 0x61, 0xe7, 0xb9, 0xd9, 0x1e, 0x9a, 0xed, 0x83, 0xb1, 0x7b, 0x0e, 0x72, 0xb4, 0x6a, + 0xcb, 0x7c, 0x34, 0x3e, 0x21, 0x25, 0xf7, 0x8a, 0x8e, 0xda, 0x41, 0x49, 0xf2, 0x2b, 0xfb, 0x22, + 0xbf, 0x74, 0xa6, 0xf9, 0x1e, 0xba, 0xd7, 0x4e, 0x96, 0x47, 0x64, 0xf8, 0xee, 0x61, 0x89, 0x4a, + 0xde, 0x31, 0x87, 0xa3, 0xf6, 0x01, 0x4a, 0x85, 0xca, 0x21, 0x45, 0xcb, 0x8f, 0xc8, 0x6d, 0x48, + 0x1c, 0xd8, 0x03, 0x14, 0xc9, 0x29, 0xfb, 0x42, 0x71, 0xe4, 0x0d, 0x48, 0x0c, 0x27, 0x4c, 0x36, + 0x79, 0x6d, 0x41, 0xb8, 0x27, 0xb0, 0xd0, 0x44, 0x61, 0xc3, 0x49, 0xcf, 0x9b, 0xf7, 0x8d, 0x22, + 0x24, 0x9a, 0xad, 0x16, 0x8d, 0xfd, 0xcd, 0x56, 0x6b, 0x4d, 0x91, 0xea, 0x5f, 0x82, 0x6c, 0x6f, + 0x6c, 0x9a, 0xd4, 0x3d, 0xcc, 0xce, 0x39, 0x3e, 0xc4, 0x58, 0xe7, 0x81, 0xea, 0x5b, 0x90, 0x39, + 0x60, 0x59, 0x07, 0x89, 0x48, 0x6b, 0x4b, 0x7f, 0xc8, 0x1e, 0x55, 0x96, 0xfc, 0xe6, 0x70, 0x9e, + 0x62, 0xb8, 0x36, 0xea, 0x3b, 0x90, 0x1b, 0xb7, 0x4f, 0x33, 0xf8, 0x31, 0x8b, 0x2e, 0x71, 0x06, + 0xb3, 0x63, 0x5e, 0x55, 0x6f, 0xc0, 0x82, 0x65, 0xbb, 0xdf, 0x50, 0xda, 0x5d, 0x76, 0xc6, 0x2e, + 0x4e, 0x5f, 0xe5, 0x5c, 0xe3, 0x26, 0xfb, 0x6e, 0x69, 0xd9, 0xbc, 0x81, 0x9d, 0xca, 0xfa, 0x23, + 0x50, 0x04, 0x33, 0x98, 0x7a, 0xc6, 0x59, 0x39, 0x64, 0x1f, 0x4a, 0x3d, 0x2b, 0x78, 0xee, 0x43, + 0x46, 0xd8, 0xc9, 0x8c, 0x31, 0xd2, 0x63, 0x5f, 0x9d, 0x3d, 0x23, 0xe8, 0xea, 0xa6, 0x8d, 0x50, + 0x5f, 0x13, 0x6d, 0xe4, 0x19, 0xfb, 0x20, 0x2d, 0x1a, 0xa9, 0xe9, 0xa1, 0x55, 0x39, 0x3a, 0x75, + 0x28, 0x7d, 0xf6, 0x3d, 0xd9, 0xb3, 0xc2, 0x1c, 0xe0, 0x0c, 0x33, 0xf1, 0x83, 0xf9, 0x90, 0x7d, + 0x6a, 0x0e, 0x98, 0x99, 0x1a, 0xcd, 0xe4, 0xd4, 0xd1, 0x3c, 0x67, 0xdf, 0x75, 0x3d, 0x33, 0xbb, + 0xb3, 0x46, 0x33, 0x39, 0x75, 0x34, 0x03, 0xf6, 0xc5, 0x37, 0x60, 0xa6, 0xa6, 0xd7, 0x37, 0x80, + 0x88, 0x5b, 0xcd, 0xe3, 0x44, 0x8c, 0x9d, 0x21, 0xfb, 0x8e, 0xef, 0x6f, 0x36, 0xa3, 0xcc, 0x32, + 0x14, 0x3f, 0x20, 0x8b, 0x7d, 0xe2, 0x0f, 0x1a, 0xaa, 0xe9, 0xf5, 0x4d, 0x38, 0x2f, 0x4e, 0xec, + 0x0c, 0x43, 0xb2, 0x55, 0xa9, 0x52, 0x34, 0x16, 0xfc, 0xa9, 0x71, 0xce, 0x4c, 0x53, 0xf1, 0x83, + 0x1a, 0xa9, 0x52, 0x45, 0x99, 0x32, 0x55, 0xd3, 0xeb, 0x0f, 0xa0, 0x28, 0x98, 0xda, 0xc7, 0x08, + 0x1d, 0x6d, 0xe6, 0x05, 0xfb, 0x5f, 0x0b, 0xcf, 0x0c, 0x8d, 0xe8, 0xe1, 0x1d, 0xe3, 0x31, 0x2e, + 0xda, 0xc8, 0x98, 0xfd, 0xa3, 0x80, 0x3f, 0x16, 0x64, 0x84, 0x8e, 0x04, 0xe6, 0xdf, 0x71, 0x56, + 0x26, 0xec, 0x5f, 0x08, 0xfc, 0xa1, 0x50, 0x42, 0xbd, 0x1f, 0x98, 0x8e, 0x49, 0x83, 0x5c, 0x8c, + 0x0d, 0x07, 0x3d, 0xf2, 0x9b, 0x91, 0x80, 0x15, 0xf1, 0x81, 0x44, 0x98, 0x36, 0x2d, 0xd6, 0x37, + 0x61, 0xfe, 0xec, 0x0e, 0xe9, 0x63, 0x89, 0x65, 0xcb, 0xd5, 0x15, 0x9a, 0x50, 0x1b, 0x73, 0xdd, + 0x80, 0x5f, 0x6a, 0xc0, 0xdc, 0x99, 0x9d, 0xd2, 0x27, 0x12, 0xcb, 0x39, 0xa9, 0x25, 0xa3, 0xd0, + 0x0d, 0x7a, 0xa6, 0xb9, 0x33, 0xbb, 0xa5, 0x4f, 0x25, 0xf6, 0x40, 0xa1, 0x6b, 0x9e, 0x11, 0xd7, + 0x33, 0xcd, 0x9d, 0xd9, 0x2d, 0x7d, 0x95, 0x65, 0x94, 0xb2, 0x5e, 0x15, 0x8d, 0xa0, 0x2f, 0x98, + 0x3f, 0xbb, 0x5b, 0xfa, 0x9a, 0x84, 0x8f, 0x15, 0xb2, 0xae, 0x7b, 0xeb, 0xe2, 0x79, 0xa6, 0xf9, + 0xb3, 0xbb, 0xa5, 0xaf, 0x4b, 0xf8, 0xa4, 0x21, 0xeb, 0xeb, 0x01, 0x33, 0xc1, 0xd1, 0x9c, 0xee, + 0x96, 0xbe, 0x21, 0xe1, 0x2b, 0x83, 0xac, 0xd7, 0x3c, 0x33, 0xbb, 0x53, 0xa3, 0x39, 0xdd, 0x2d, + 0x7d, 0x13, 0x6f, 0xf1, 0x75, 0x59, 0xbf, 0x13, 0x30, 0x83, 0x9e, 0xa9, 0xf8, 0x0a, 0x6e, 0xe9, + 0x5b, 0x12, 0x3e, 0x06, 0xc9, 0xfa, 0x5d, 0xc3, 0xed, 0xdd, 0xf7, 0x4c, 0xc5, 0x57, 0x70, 0x4b, + 0x9f, 0x49, 0xf8, 0x66, 0x24, 0xeb, 0xf7, 0x82, 0x86, 0xd0, 0x33, 0x29, 0xaf, 0xe2, 0x96, 0xbe, + 0x4d, 0x2d, 0x15, 0xeb, 0xf2, 0xfa, 0xaa, 0xe1, 0x0e, 0x40, 0xf0, 0x4c, 0xca, 0xab, 0xb8, 0xa5, + 0xef, 0x50, 0x53, 0x4a, 0x5d, 0x5e, 0x5f, 0x0b, 0x99, 0xaa, 0xe9, 0xf5, 0x47, 0x50, 0x38, 0xab, + 0x5b, 0xfa, 0xae, 0xf8, 0x16, 0x97, 0xef, 0x0a, 0xbe, 0x69, 0x47, 0xd8, 0xb3, 0x53, 0x1d, 0xd3, + 0xf7, 0x30, 0xc7, 0xa9, 0xcf, 0x3d, 0x61, 0xef, 0x55, 0x8c, 0xe0, 0x6f, 0x1f, 0x73, 0x53, 0x5b, + 0xfe, 0xf9, 0x38, 0xd5, 0x47, 0x7d, 0x5f, 0xc2, 0x47, 0xad, 0x02, 0x37, 0x88, 0x78, 0xef, 0xa4, + 0x30, 0x87, 0xf5, 0xa1, 0x3f, 0xcb, 0xd3, 0xbc, 0xd5, 0x0f, 0xa4, 0x57, 0x71, 0x57, 0xf5, 0x44, + 0x6b, 0xbb, 0xe1, 0x2d, 0x06, 0xd6, 0xbc, 0x0d, 0xc9, 0x63, 0x6d, 0x75, 0x4d, 0xbc, 0x92, 0x89, + 0x6f, 0xb9, 0xcc, 0x49, 0xe5, 0xb5, 0xa2, 0xf0, 0xdc, 0x3d, 0x1c, 0x39, 0x27, 0x06, 0xb2, 0x38, + 0x5b, 0x8b, 0x64, 0x7f, 0x12, 0xc3, 0xd6, 0x38, 0xbb, 0x1a, 0xc9, 0xfe, 0x34, 0x86, 0x5d, 0xe5, + 0x6c, 0x3d, 0x92, 0xfd, 0xd5, 0x18, 0xb6, 0xce, 0xd9, 0xeb, 0x91, 0xec, 0xaf, 0xc5, 0xb0, 0xd7, + 0x39, 0xbb, 0x16, 0xc9, 0xfe, 0x7a, 0x0c, 0xbb, 0xc6, 0xd9, 0x77, 0x22, 0xd9, 0xdf, 0x88, 0x61, + 0xdf, 0xe1, 0xec, 0xbb, 0x91, 0xec, 0x6f, 0xc6, 0xb0, 0xef, 0x72, 0xf6, 0xbd, 0x48, 0xf6, 0xb7, + 0x62, 0xd8, 0xf7, 0x18, 0x7b, 0x6d, 0x35, 0x92, 0xfd, 0x59, 0x34, 0x7b, 0x6d, 0x95, 0xb3, 0xa3, + 0xb5, 0xf6, 0xed, 0x18, 0x36, 0xd7, 0xda, 0x5a, 0xb4, 0xd6, 0xbe, 0x13, 0xc3, 0xe6, 0x5a, 0x5b, + 0x8b, 0xd6, 0xda, 0x77, 0x63, 0xd8, 0x5c, 0x6b, 0x6b, 0xd1, 0x5a, 0xfb, 0x5e, 0x0c, 0x9b, 0x6b, + 0x6d, 0x2d, 0x5a, 0x6b, 0xdf, 0x8f, 0x61, 0x73, 0xad, 0xad, 0x45, 0x6b, 0xed, 0x07, 0x31, 0x6c, + 0xae, 0xb5, 0xb5, 0x68, 0xad, 0xfd, 0x51, 0x0c, 0x9b, 0x6b, 0x6d, 0x2d, 0x5a, 0x6b, 0x7f, 0x1c, + 0xc3, 0xe6, 0x5a, 0x5b, 0x8b, 0xd6, 0xda, 0x9f, 0xc4, 0xb0, 0xb9, 0xd6, 0xb4, 0x68, 0xad, 0xfd, + 0x69, 0x34, 0x5b, 0xe3, 0x5a, 0xd3, 0xa2, 0xb5, 0xf6, 0x67, 0x31, 0x6c, 0xae, 0x35, 0x2d, 0x5a, + 0x6b, 0x7f, 0x1e, 0xc3, 0xe6, 0x5a, 0xd3, 0xa2, 0xb5, 0xf6, 0xc3, 0x18, 0x36, 0xd7, 0x9a, 0x16, + 0xad, 0xb5, 0xbf, 0x88, 0x61, 0x73, 0xad, 0x69, 0xd1, 0x5a, 0xfb, 0xcb, 0x18, 0x36, 0xd7, 0x9a, + 0x16, 0xad, 0xb5, 0xbf, 0x8a, 0x61, 0x73, 0xad, 0x69, 0xd1, 0x5a, 0xfb, 0xeb, 0x18, 0x36, 0xd7, + 0x9a, 0x16, 0xad, 0xb5, 0xbf, 0x89, 0x61, 0x73, 0xad, 0x69, 0xd1, 0x5a, 0xfb, 0xdb, 0x18, 0x36, + 0xd7, 0x5a, 0x35, 0x5a, 0x6b, 0x7f, 0x17, 0xcd, 0xae, 0x72, 0xad, 0x55, 0xa3, 0xb5, 0xf6, 0xf7, + 0x31, 0x6c, 0xae, 0xb5, 0x6a, 0xb4, 0xd6, 0xfe, 0x21, 0x86, 0xcd, 0xb5, 0x56, 0x8d, 0xd6, 0xda, + 0x3f, 0xc6, 0xb0, 0xb9, 0xd6, 0xaa, 0xd1, 0x5a, 0xfb, 0x51, 0x0c, 0x9b, 0x6b, 0xad, 0x1a, 0xad, + 0xb5, 0x7f, 0x8a, 0x61, 0x73, 0xad, 0x55, 0xa3, 0xb5, 0xf6, 0xcf, 0x31, 0x6c, 0xae, 0xb5, 0x6a, + 0xb4, 0xd6, 0xfe, 0x25, 0x86, 0xcd, 0xb5, 0x56, 0x8d, 0xd6, 0xda, 0xbf, 0xc6, 0xb0, 0xb9, 0xd6, + 0xaa, 0xd1, 0x5a, 0xfb, 0xb7, 0x18, 0x36, 0xd7, 0x9a, 0x1e, 0xad, 0xb5, 0x7f, 0x8f, 0x66, 0xeb, + 0x5c, 0x6b, 0x7a, 0xb4, 0xd6, 0xfe, 0x23, 0x86, 0xcd, 0xb5, 0xa6, 0x47, 0x6b, 0xed, 0x3f, 0x63, + 0xd8, 0x5c, 0x6b, 0x7a, 0xb4, 0xd6, 0xfe, 0x2b, 0x86, 0xcd, 0xb5, 0xa6, 0x47, 0x6b, 0xed, 0xbf, + 0x63, 0xd8, 0x5c, 0x6b, 0x7a, 0xb4, 0xd6, 0xfe, 0x27, 0x86, 0xcd, 0xb5, 0xa6, 0x47, 0x6b, 0xed, + 0xc7, 0x31, 0x6c, 0xae, 0x35, 0x3d, 0x5a, 0x6b, 0x3f, 0x89, 0x61, 0x73, 0xad, 0xe9, 0xd1, 0x5a, + 0xfb, 0xdf, 0x18, 0x36, 0xd7, 0x9a, 0x1e, 0xad, 0xb5, 0xff, 0x8b, 0x61, 0x73, 0xad, 0xad, 0x47, + 0x6b, 0xed, 0xff, 0xa3, 0xd9, 0xeb, 0xab, 0x3f, 0x0d, 0x00, 0x00, 0xff, 0xff, 0xaa, 0x00, 0xcd, + 0x32, 0x57, 0x39, 0x00, 0x00, +} diff --git a/vendor/github.com/golang/protobuf/proto/testdata/test.proto b/vendor/github.com/golang/protobuf/proto/testdata/test.proto new file mode 100644 index 00000000..70e3cfcd --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/testdata/test.proto @@ -0,0 +1,548 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2010 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// 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 +// OWNER 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. + +// A feature-rich test file for the protocol compiler and libraries. + +syntax = "proto2"; + +package testdata; + +enum FOO { FOO1 = 1; }; + +message GoEnum { + required FOO foo = 1; +} + +message GoTestField { + required string Label = 1; + required string Type = 2; +} + +message GoTest { + // An enum, for completeness. + enum KIND { + VOID = 0; + + // Basic types + BOOL = 1; + BYTES = 2; + FINGERPRINT = 3; + FLOAT = 4; + INT = 5; + STRING = 6; + TIME = 7; + + // Groupings + TUPLE = 8; + ARRAY = 9; + MAP = 10; + + // Table types + TABLE = 11; + + // Functions + FUNCTION = 12; // last tag + }; + + // Some typical parameters + required KIND Kind = 1; + optional string Table = 2; + optional int32 Param = 3; + + // Required, repeated and optional foreign fields. + required GoTestField RequiredField = 4; + repeated GoTestField RepeatedField = 5; + optional GoTestField OptionalField = 6; + + // Required fields of all basic types + required bool F_Bool_required = 10; + required int32 F_Int32_required = 11; + required int64 F_Int64_required = 12; + required fixed32 F_Fixed32_required = 13; + required fixed64 F_Fixed64_required = 14; + required uint32 F_Uint32_required = 15; + required uint64 F_Uint64_required = 16; + required float F_Float_required = 17; + required double F_Double_required = 18; + required string F_String_required = 19; + required bytes F_Bytes_required = 101; + required sint32 F_Sint32_required = 102; + required sint64 F_Sint64_required = 103; + + // Repeated fields of all basic types + repeated bool F_Bool_repeated = 20; + repeated int32 F_Int32_repeated = 21; + repeated int64 F_Int64_repeated = 22; + repeated fixed32 F_Fixed32_repeated = 23; + repeated fixed64 F_Fixed64_repeated = 24; + repeated uint32 F_Uint32_repeated = 25; + repeated uint64 F_Uint64_repeated = 26; + repeated float F_Float_repeated = 27; + repeated double F_Double_repeated = 28; + repeated string F_String_repeated = 29; + repeated bytes F_Bytes_repeated = 201; + repeated sint32 F_Sint32_repeated = 202; + repeated sint64 F_Sint64_repeated = 203; + + // Optional fields of all basic types + optional bool F_Bool_optional = 30; + optional int32 F_Int32_optional = 31; + optional int64 F_Int64_optional = 32; + optional fixed32 F_Fixed32_optional = 33; + optional fixed64 F_Fixed64_optional = 34; + optional uint32 F_Uint32_optional = 35; + optional uint64 F_Uint64_optional = 36; + optional float F_Float_optional = 37; + optional double F_Double_optional = 38; + optional string F_String_optional = 39; + optional bytes F_Bytes_optional = 301; + optional sint32 F_Sint32_optional = 302; + optional sint64 F_Sint64_optional = 303; + + // Default-valued fields of all basic types + optional bool F_Bool_defaulted = 40 [default=true]; + optional int32 F_Int32_defaulted = 41 [default=32]; + optional int64 F_Int64_defaulted = 42 [default=64]; + optional fixed32 F_Fixed32_defaulted = 43 [default=320]; + optional fixed64 F_Fixed64_defaulted = 44 [default=640]; + optional uint32 F_Uint32_defaulted = 45 [default=3200]; + optional uint64 F_Uint64_defaulted = 46 [default=6400]; + optional float F_Float_defaulted = 47 [default=314159.]; + optional double F_Double_defaulted = 48 [default=271828.]; + optional string F_String_defaulted = 49 [default="hello, \"world!\"\n"]; + optional bytes F_Bytes_defaulted = 401 [default="Bignose"]; + optional sint32 F_Sint32_defaulted = 402 [default = -32]; + optional sint64 F_Sint64_defaulted = 403 [default = -64]; + + // Packed repeated fields (no string or bytes). + repeated bool F_Bool_repeated_packed = 50 [packed=true]; + repeated int32 F_Int32_repeated_packed = 51 [packed=true]; + repeated int64 F_Int64_repeated_packed = 52 [packed=true]; + repeated fixed32 F_Fixed32_repeated_packed = 53 [packed=true]; + repeated fixed64 F_Fixed64_repeated_packed = 54 [packed=true]; + repeated uint32 F_Uint32_repeated_packed = 55 [packed=true]; + repeated uint64 F_Uint64_repeated_packed = 56 [packed=true]; + repeated float F_Float_repeated_packed = 57 [packed=true]; + repeated double F_Double_repeated_packed = 58 [packed=true]; + repeated sint32 F_Sint32_repeated_packed = 502 [packed=true]; + repeated sint64 F_Sint64_repeated_packed = 503 [packed=true]; + + // Required, repeated, and optional groups. + required group RequiredGroup = 70 { + required string RequiredField = 71; + }; + + repeated group RepeatedGroup = 80 { + required string RequiredField = 81; + }; + + optional group OptionalGroup = 90 { + required string RequiredField = 91; + }; +} + +// For testing a group containing a required field. +message GoTestRequiredGroupField { + required group Group = 1 { + required int32 Field = 2; + }; +} + +// For testing skipping of unrecognized fields. +// Numbers are all big, larger than tag numbers in GoTestField, +// the message used in the corresponding test. +message GoSkipTest { + required int32 skip_int32 = 11; + required fixed32 skip_fixed32 = 12; + required fixed64 skip_fixed64 = 13; + required string skip_string = 14; + required group SkipGroup = 15 { + required int32 group_int32 = 16; + required string group_string = 17; + } +} + +// For testing packed/non-packed decoder switching. +// A serialized instance of one should be deserializable as the other. +message NonPackedTest { + repeated int32 a = 1; +} + +message PackedTest { + repeated int32 b = 1 [packed=true]; +} + +message MaxTag { + // Maximum possible tag number. + optional string last_field = 536870911; +} + +message OldMessage { + message Nested { + optional string name = 1; + } + optional Nested nested = 1; + + optional int32 num = 2; +} + +// NewMessage is wire compatible with OldMessage; +// imagine it as a future version. +message NewMessage { + message Nested { + optional string name = 1; + optional string food_group = 2; + } + optional Nested nested = 1; + + // This is an int32 in OldMessage. + optional int64 num = 2; +} + +// Smaller tests for ASCII formatting. + +message InnerMessage { + required string host = 1; + optional int32 port = 2 [default=4000]; + optional bool connected = 3; +} + +message OtherMessage { + optional int64 key = 1; + optional bytes value = 2; + optional float weight = 3; + optional InnerMessage inner = 4; + + extensions 100 to max; +} + +message RequiredInnerMessage { + required InnerMessage leo_finally_won_an_oscar = 1; +} + +message MyMessage { + required int32 count = 1; + optional string name = 2; + optional string quote = 3; + repeated string pet = 4; + optional InnerMessage inner = 5; + repeated OtherMessage others = 6; + optional RequiredInnerMessage we_must_go_deeper = 13; + repeated InnerMessage rep_inner = 12; + + enum Color { + RED = 0; + GREEN = 1; + BLUE = 2; + }; + optional Color bikeshed = 7; + + optional group SomeGroup = 8 { + optional int32 group_field = 9; + } + + // This field becomes [][]byte in the generated code. + repeated bytes rep_bytes = 10; + + optional double bigfloat = 11; + + extensions 100 to max; +} + +message Ext { + extend MyMessage { + optional Ext more = 103; + optional string text = 104; + optional int32 number = 105; + } + + optional string data = 1; +} + +extend MyMessage { + repeated string greeting = 106; +} + +message ComplexExtension { + optional int32 first = 1; + optional int32 second = 2; + repeated int32 third = 3; +} + +extend OtherMessage { + optional ComplexExtension complex = 200; + repeated ComplexExtension r_complex = 201; +} + +message DefaultsMessage { + enum DefaultsEnum { + ZERO = 0; + ONE = 1; + TWO = 2; + }; + extensions 100 to max; +} + +extend DefaultsMessage { + optional double no_default_double = 101; + optional float no_default_float = 102; + optional int32 no_default_int32 = 103; + optional int64 no_default_int64 = 104; + optional uint32 no_default_uint32 = 105; + optional uint64 no_default_uint64 = 106; + optional sint32 no_default_sint32 = 107; + optional sint64 no_default_sint64 = 108; + optional fixed32 no_default_fixed32 = 109; + optional fixed64 no_default_fixed64 = 110; + optional sfixed32 no_default_sfixed32 = 111; + optional sfixed64 no_default_sfixed64 = 112; + optional bool no_default_bool = 113; + optional string no_default_string = 114; + optional bytes no_default_bytes = 115; + optional DefaultsMessage.DefaultsEnum no_default_enum = 116; + + optional double default_double = 201 [default = 3.1415]; + optional float default_float = 202 [default = 3.14]; + optional int32 default_int32 = 203 [default = 42]; + optional int64 default_int64 = 204 [default = 43]; + optional uint32 default_uint32 = 205 [default = 44]; + optional uint64 default_uint64 = 206 [default = 45]; + optional sint32 default_sint32 = 207 [default = 46]; + optional sint64 default_sint64 = 208 [default = 47]; + optional fixed32 default_fixed32 = 209 [default = 48]; + optional fixed64 default_fixed64 = 210 [default = 49]; + optional sfixed32 default_sfixed32 = 211 [default = 50]; + optional sfixed64 default_sfixed64 = 212 [default = 51]; + optional bool default_bool = 213 [default = true]; + optional string default_string = 214 [default = "Hello, string"]; + optional bytes default_bytes = 215 [default = "Hello, bytes"]; + optional DefaultsMessage.DefaultsEnum default_enum = 216 [default = ONE]; +} + +message MyMessageSet { + option message_set_wire_format = true; + extensions 100 to max; +} + +message Empty { +} + +extend MyMessageSet { + optional Empty x201 = 201; + optional Empty x202 = 202; + optional Empty x203 = 203; + optional Empty x204 = 204; + optional Empty x205 = 205; + optional Empty x206 = 206; + optional Empty x207 = 207; + optional Empty x208 = 208; + optional Empty x209 = 209; + optional Empty x210 = 210; + optional Empty x211 = 211; + optional Empty x212 = 212; + optional Empty x213 = 213; + optional Empty x214 = 214; + optional Empty x215 = 215; + optional Empty x216 = 216; + optional Empty x217 = 217; + optional Empty x218 = 218; + optional Empty x219 = 219; + optional Empty x220 = 220; + optional Empty x221 = 221; + optional Empty x222 = 222; + optional Empty x223 = 223; + optional Empty x224 = 224; + optional Empty x225 = 225; + optional Empty x226 = 226; + optional Empty x227 = 227; + optional Empty x228 = 228; + optional Empty x229 = 229; + optional Empty x230 = 230; + optional Empty x231 = 231; + optional Empty x232 = 232; + optional Empty x233 = 233; + optional Empty x234 = 234; + optional Empty x235 = 235; + optional Empty x236 = 236; + optional Empty x237 = 237; + optional Empty x238 = 238; + optional Empty x239 = 239; + optional Empty x240 = 240; + optional Empty x241 = 241; + optional Empty x242 = 242; + optional Empty x243 = 243; + optional Empty x244 = 244; + optional Empty x245 = 245; + optional Empty x246 = 246; + optional Empty x247 = 247; + optional Empty x248 = 248; + optional Empty x249 = 249; + optional Empty x250 = 250; +} + +message MessageList { + repeated group Message = 1 { + required string name = 2; + required int32 count = 3; + } +} + +message Strings { + optional string string_field = 1; + optional bytes bytes_field = 2; +} + +message Defaults { + enum Color { + RED = 0; + GREEN = 1; + BLUE = 2; + } + + // Default-valued fields of all basic types. + // Same as GoTest, but copied here to make testing easier. + optional bool F_Bool = 1 [default=true]; + optional int32 F_Int32 = 2 [default=32]; + optional int64 F_Int64 = 3 [default=64]; + optional fixed32 F_Fixed32 = 4 [default=320]; + optional fixed64 F_Fixed64 = 5 [default=640]; + optional uint32 F_Uint32 = 6 [default=3200]; + optional uint64 F_Uint64 = 7 [default=6400]; + optional float F_Float = 8 [default=314159.]; + optional double F_Double = 9 [default=271828.]; + optional string F_String = 10 [default="hello, \"world!\"\n"]; + optional bytes F_Bytes = 11 [default="Bignose"]; + optional sint32 F_Sint32 = 12 [default=-32]; + optional sint64 F_Sint64 = 13 [default=-64]; + optional Color F_Enum = 14 [default=GREEN]; + + // More fields with crazy defaults. + optional float F_Pinf = 15 [default=inf]; + optional float F_Ninf = 16 [default=-inf]; + optional float F_Nan = 17 [default=nan]; + + // Sub-message. + optional SubDefaults sub = 18; + + // Redundant but explicit defaults. + optional string str_zero = 19 [default=""]; +} + +message SubDefaults { + optional int64 n = 1 [default=7]; +} + +message RepeatedEnum { + enum Color { + RED = 1; + } + repeated Color color = 1; +} + +message MoreRepeated { + repeated bool bools = 1; + repeated bool bools_packed = 2 [packed=true]; + repeated int32 ints = 3; + repeated int32 ints_packed = 4 [packed=true]; + repeated int64 int64s_packed = 7 [packed=true]; + repeated string strings = 5; + repeated fixed32 fixeds = 6; +} + +// GroupOld and GroupNew have the same wire format. +// GroupNew has a new field inside a group. + +message GroupOld { + optional group G = 101 { + optional int32 x = 2; + } +} + +message GroupNew { + optional group G = 101 { + optional int32 x = 2; + optional int32 y = 3; + } +} + +message FloatingPoint { + required double f = 1; + optional bool exact = 2; +} + +message MessageWithMap { + map name_mapping = 1; + map msg_mapping = 2; + map byte_mapping = 3; + map str_to_str = 4; +} + +message Oneof { + oneof union { + bool F_Bool = 1; + int32 F_Int32 = 2; + int64 F_Int64 = 3; + fixed32 F_Fixed32 = 4; + fixed64 F_Fixed64 = 5; + uint32 F_Uint32 = 6; + uint64 F_Uint64 = 7; + float F_Float = 8; + double F_Double = 9; + string F_String = 10; + bytes F_Bytes = 11; + sint32 F_Sint32 = 12; + sint64 F_Sint64 = 13; + MyMessage.Color F_Enum = 14; + GoTestField F_Message = 15; + group F_Group = 16 { + optional int32 x = 17; + } + int32 F_Largest_Tag = 536870911; + } + + oneof tormato { + int32 value = 100; + } +} + +message Communique { + optional bool make_me_cry = 1; + + // This is a oneof, called "union". + oneof union { + int32 number = 5; + string name = 6; + bytes data = 7; + double temp_c = 8; + MyMessage.Color col = 9; + Strings msg = 10; + } +} diff --git a/vendor/github.com/golang/protobuf/proto/text.go b/vendor/github.com/golang/protobuf/proto/text.go new file mode 100644 index 00000000..965876bf --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/text.go @@ -0,0 +1,854 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2010 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// 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 +// OWNER 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. + +package proto + +// Functions for writing the text protocol buffer format. + +import ( + "bufio" + "bytes" + "encoding" + "errors" + "fmt" + "io" + "log" + "math" + "reflect" + "sort" + "strings" +) + +var ( + newline = []byte("\n") + spaces = []byte(" ") + gtNewline = []byte(">\n") + endBraceNewline = []byte("}\n") + backslashN = []byte{'\\', 'n'} + backslashR = []byte{'\\', 'r'} + backslashT = []byte{'\\', 't'} + backslashDQ = []byte{'\\', '"'} + backslashBS = []byte{'\\', '\\'} + posInf = []byte("inf") + negInf = []byte("-inf") + nan = []byte("nan") +) + +type writer interface { + io.Writer + WriteByte(byte) error +} + +// textWriter is an io.Writer that tracks its indentation level. +type textWriter struct { + ind int + complete bool // if the current position is a complete line + compact bool // whether to write out as a one-liner + w writer +} + +func (w *textWriter) WriteString(s string) (n int, err error) { + if !strings.Contains(s, "\n") { + if !w.compact && w.complete { + w.writeIndent() + } + w.complete = false + return io.WriteString(w.w, s) + } + // WriteString is typically called without newlines, so this + // codepath and its copy are rare. We copy to avoid + // duplicating all of Write's logic here. + return w.Write([]byte(s)) +} + +func (w *textWriter) Write(p []byte) (n int, err error) { + newlines := bytes.Count(p, newline) + if newlines == 0 { + if !w.compact && w.complete { + w.writeIndent() + } + n, err = w.w.Write(p) + w.complete = false + return n, err + } + + frags := bytes.SplitN(p, newline, newlines+1) + if w.compact { + for i, frag := range frags { + if i > 0 { + if err := w.w.WriteByte(' '); err != nil { + return n, err + } + n++ + } + nn, err := w.w.Write(frag) + n += nn + if err != nil { + return n, err + } + } + return n, nil + } + + for i, frag := range frags { + if w.complete { + w.writeIndent() + } + nn, err := w.w.Write(frag) + n += nn + if err != nil { + return n, err + } + if i+1 < len(frags) { + if err := w.w.WriteByte('\n'); err != nil { + return n, err + } + n++ + } + } + w.complete = len(frags[len(frags)-1]) == 0 + return n, nil +} + +func (w *textWriter) WriteByte(c byte) error { + if w.compact && c == '\n' { + c = ' ' + } + if !w.compact && w.complete { + w.writeIndent() + } + err := w.w.WriteByte(c) + w.complete = c == '\n' + return err +} + +func (w *textWriter) indent() { w.ind++ } + +func (w *textWriter) unindent() { + if w.ind == 0 { + log.Print("proto: textWriter unindented too far") + return + } + w.ind-- +} + +func writeName(w *textWriter, props *Properties) error { + if _, err := w.WriteString(props.OrigName); err != nil { + return err + } + if props.Wire != "group" { + return w.WriteByte(':') + } + return nil +} + +// raw is the interface satisfied by RawMessage. +type raw interface { + Bytes() []byte +} + +func requiresQuotes(u string) bool { + // When type URL contains any characters except [0-9A-Za-z./\-]*, it must be quoted. + for _, ch := range u { + switch { + case ch == '.' || ch == '/' || ch == '_': + continue + case '0' <= ch && ch <= '9': + continue + case 'A' <= ch && ch <= 'Z': + continue + case 'a' <= ch && ch <= 'z': + continue + default: + return true + } + } + return false +} + +// isAny reports whether sv is a google.protobuf.Any message +func isAny(sv reflect.Value) bool { + type wkt interface { + XXX_WellKnownType() string + } + t, ok := sv.Addr().Interface().(wkt) + return ok && t.XXX_WellKnownType() == "Any" +} + +// writeProto3Any writes an expanded google.protobuf.Any message. +// +// It returns (false, nil) if sv value can't be unmarshaled (e.g. because +// required messages are not linked in). +// +// It returns (true, error) when sv was written in expanded format or an error +// was encountered. +func (tm *TextMarshaler) writeProto3Any(w *textWriter, sv reflect.Value) (bool, error) { + turl := sv.FieldByName("TypeUrl") + val := sv.FieldByName("Value") + if !turl.IsValid() || !val.IsValid() { + return true, errors.New("proto: invalid google.protobuf.Any message") + } + + b, ok := val.Interface().([]byte) + if !ok { + return true, errors.New("proto: invalid google.protobuf.Any message") + } + + parts := strings.Split(turl.String(), "/") + mt := MessageType(parts[len(parts)-1]) + if mt == nil { + return false, nil + } + m := reflect.New(mt.Elem()) + if err := Unmarshal(b, m.Interface().(Message)); err != nil { + return false, nil + } + w.Write([]byte("[")) + u := turl.String() + if requiresQuotes(u) { + writeString(w, u) + } else { + w.Write([]byte(u)) + } + if w.compact { + w.Write([]byte("]:<")) + } else { + w.Write([]byte("]: <\n")) + w.ind++ + } + if err := tm.writeStruct(w, m.Elem()); err != nil { + return true, err + } + if w.compact { + w.Write([]byte("> ")) + } else { + w.ind-- + w.Write([]byte(">\n")) + } + return true, nil +} + +func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error { + if tm.ExpandAny && isAny(sv) { + if canExpand, err := tm.writeProto3Any(w, sv); canExpand { + return err + } + } + st := sv.Type() + sprops := GetProperties(st) + for i := 0; i < sv.NumField(); i++ { + fv := sv.Field(i) + props := sprops.Prop[i] + name := st.Field(i).Name + + if strings.HasPrefix(name, "XXX_") { + // There are two XXX_ fields: + // XXX_unrecognized []byte + // XXX_extensions map[int32]proto.Extension + // The first is handled here; + // the second is handled at the bottom of this function. + if name == "XXX_unrecognized" && !fv.IsNil() { + if err := writeUnknownStruct(w, fv.Interface().([]byte)); err != nil { + return err + } + } + continue + } + if fv.Kind() == reflect.Ptr && fv.IsNil() { + // Field not filled in. This could be an optional field or + // a required field that wasn't filled in. Either way, there + // isn't anything we can show for it. + continue + } + if fv.Kind() == reflect.Slice && fv.IsNil() { + // Repeated field that is empty, or a bytes field that is unused. + continue + } + + if props.Repeated && fv.Kind() == reflect.Slice { + // Repeated field. + for j := 0; j < fv.Len(); j++ { + if err := writeName(w, props); err != nil { + return err + } + if !w.compact { + if err := w.WriteByte(' '); err != nil { + return err + } + } + v := fv.Index(j) + if v.Kind() == reflect.Ptr && v.IsNil() { + // A nil message in a repeated field is not valid, + // but we can handle that more gracefully than panicking. + if _, err := w.Write([]byte("\n")); err != nil { + return err + } + continue + } + if err := tm.writeAny(w, v, props); err != nil { + return err + } + if err := w.WriteByte('\n'); err != nil { + return err + } + } + continue + } + if fv.Kind() == reflect.Map { + // Map fields are rendered as a repeated struct with key/value fields. + keys := fv.MapKeys() + sort.Sort(mapKeys(keys)) + for _, key := range keys { + val := fv.MapIndex(key) + if err := writeName(w, props); err != nil { + return err + } + if !w.compact { + if err := w.WriteByte(' '); err != nil { + return err + } + } + // open struct + if err := w.WriteByte('<'); err != nil { + return err + } + if !w.compact { + if err := w.WriteByte('\n'); err != nil { + return err + } + } + w.indent() + // key + if _, err := w.WriteString("key:"); err != nil { + return err + } + if !w.compact { + if err := w.WriteByte(' '); err != nil { + return err + } + } + if err := tm.writeAny(w, key, props.mkeyprop); err != nil { + return err + } + if err := w.WriteByte('\n'); err != nil { + return err + } + // nil values aren't legal, but we can avoid panicking because of them. + if val.Kind() != reflect.Ptr || !val.IsNil() { + // value + if _, err := w.WriteString("value:"); err != nil { + return err + } + if !w.compact { + if err := w.WriteByte(' '); err != nil { + return err + } + } + if err := tm.writeAny(w, val, props.mvalprop); err != nil { + return err + } + if err := w.WriteByte('\n'); err != nil { + return err + } + } + // close struct + w.unindent() + if err := w.WriteByte('>'); err != nil { + return err + } + if err := w.WriteByte('\n'); err != nil { + return err + } + } + continue + } + if props.proto3 && fv.Kind() == reflect.Slice && fv.Len() == 0 { + // empty bytes field + continue + } + if fv.Kind() != reflect.Ptr && fv.Kind() != reflect.Slice { + // proto3 non-repeated scalar field; skip if zero value + if isProto3Zero(fv) { + continue + } + } + + if fv.Kind() == reflect.Interface { + // Check if it is a oneof. + if st.Field(i).Tag.Get("protobuf_oneof") != "" { + // fv is nil, or holds a pointer to generated struct. + // That generated struct has exactly one field, + // which has a protobuf struct tag. + if fv.IsNil() { + continue + } + inner := fv.Elem().Elem() // interface -> *T -> T + tag := inner.Type().Field(0).Tag.Get("protobuf") + props = new(Properties) // Overwrite the outer props var, but not its pointee. + props.Parse(tag) + // Write the value in the oneof, not the oneof itself. + fv = inner.Field(0) + + // Special case to cope with malformed messages gracefully: + // If the value in the oneof is a nil pointer, don't panic + // in writeAny. + if fv.Kind() == reflect.Ptr && fv.IsNil() { + // Use errors.New so writeAny won't render quotes. + msg := errors.New("/* nil */") + fv = reflect.ValueOf(&msg).Elem() + } + } + } + + if err := writeName(w, props); err != nil { + return err + } + if !w.compact { + if err := w.WriteByte(' '); err != nil { + return err + } + } + if b, ok := fv.Interface().(raw); ok { + if err := writeRaw(w, b.Bytes()); err != nil { + return err + } + continue + } + + // Enums have a String method, so writeAny will work fine. + if err := tm.writeAny(w, fv, props); err != nil { + return err + } + + if err := w.WriteByte('\n'); err != nil { + return err + } + } + + // Extensions (the XXX_extensions field). + pv := sv.Addr() + if _, ok := extendable(pv.Interface()); ok { + if err := tm.writeExtensions(w, pv); err != nil { + return err + } + } + + return nil +} + +// writeRaw writes an uninterpreted raw message. +func writeRaw(w *textWriter, b []byte) error { + if err := w.WriteByte('<'); err != nil { + return err + } + if !w.compact { + if err := w.WriteByte('\n'); err != nil { + return err + } + } + w.indent() + if err := writeUnknownStruct(w, b); err != nil { + return err + } + w.unindent() + if err := w.WriteByte('>'); err != nil { + return err + } + return nil +} + +// writeAny writes an arbitrary field. +func (tm *TextMarshaler) writeAny(w *textWriter, v reflect.Value, props *Properties) error { + v = reflect.Indirect(v) + + // Floats have special cases. + if v.Kind() == reflect.Float32 || v.Kind() == reflect.Float64 { + x := v.Float() + var b []byte + switch { + case math.IsInf(x, 1): + b = posInf + case math.IsInf(x, -1): + b = negInf + case math.IsNaN(x): + b = nan + } + if b != nil { + _, err := w.Write(b) + return err + } + // Other values are handled below. + } + + // We don't attempt to serialise every possible value type; only those + // that can occur in protocol buffers. + switch v.Kind() { + case reflect.Slice: + // Should only be a []byte; repeated fields are handled in writeStruct. + if err := writeString(w, string(v.Bytes())); err != nil { + return err + } + case reflect.String: + if err := writeString(w, v.String()); err != nil { + return err + } + case reflect.Struct: + // Required/optional group/message. + var bra, ket byte = '<', '>' + if props != nil && props.Wire == "group" { + bra, ket = '{', '}' + } + if err := w.WriteByte(bra); err != nil { + return err + } + if !w.compact { + if err := w.WriteByte('\n'); err != nil { + return err + } + } + w.indent() + if etm, ok := v.Interface().(encoding.TextMarshaler); ok { + text, err := etm.MarshalText() + if err != nil { + return err + } + if _, err = w.Write(text); err != nil { + return err + } + } else if err := tm.writeStruct(w, v); err != nil { + return err + } + w.unindent() + if err := w.WriteByte(ket); err != nil { + return err + } + default: + _, err := fmt.Fprint(w, v.Interface()) + return err + } + return nil +} + +// equivalent to C's isprint. +func isprint(c byte) bool { + return c >= 0x20 && c < 0x7f +} + +// writeString writes a string in the protocol buffer text format. +// It is similar to strconv.Quote except we don't use Go escape sequences, +// we treat the string as a byte sequence, and we use octal escapes. +// These differences are to maintain interoperability with the other +// languages' implementations of the text format. +func writeString(w *textWriter, s string) error { + // use WriteByte here to get any needed indent + if err := w.WriteByte('"'); err != nil { + return err + } + // Loop over the bytes, not the runes. + for i := 0; i < len(s); i++ { + var err error + // Divergence from C++: we don't escape apostrophes. + // There's no need to escape them, and the C++ parser + // copes with a naked apostrophe. + switch c := s[i]; c { + case '\n': + _, err = w.w.Write(backslashN) + case '\r': + _, err = w.w.Write(backslashR) + case '\t': + _, err = w.w.Write(backslashT) + case '"': + _, err = w.w.Write(backslashDQ) + case '\\': + _, err = w.w.Write(backslashBS) + default: + if isprint(c) { + err = w.w.WriteByte(c) + } else { + _, err = fmt.Fprintf(w.w, "\\%03o", c) + } + } + if err != nil { + return err + } + } + return w.WriteByte('"') +} + +func writeUnknownStruct(w *textWriter, data []byte) (err error) { + if !w.compact { + if _, err := fmt.Fprintf(w, "/* %d unknown bytes */\n", len(data)); err != nil { + return err + } + } + b := NewBuffer(data) + for b.index < len(b.buf) { + x, err := b.DecodeVarint() + if err != nil { + _, err := fmt.Fprintf(w, "/* %v */\n", err) + return err + } + wire, tag := x&7, x>>3 + if wire == WireEndGroup { + w.unindent() + if _, err := w.Write(endBraceNewline); err != nil { + return err + } + continue + } + if _, err := fmt.Fprint(w, tag); err != nil { + return err + } + if wire != WireStartGroup { + if err := w.WriteByte(':'); err != nil { + return err + } + } + if !w.compact || wire == WireStartGroup { + if err := w.WriteByte(' '); err != nil { + return err + } + } + switch wire { + case WireBytes: + buf, e := b.DecodeRawBytes(false) + if e == nil { + _, err = fmt.Fprintf(w, "%q", buf) + } else { + _, err = fmt.Fprintf(w, "/* %v */", e) + } + case WireFixed32: + x, err = b.DecodeFixed32() + err = writeUnknownInt(w, x, err) + case WireFixed64: + x, err = b.DecodeFixed64() + err = writeUnknownInt(w, x, err) + case WireStartGroup: + err = w.WriteByte('{') + w.indent() + case WireVarint: + x, err = b.DecodeVarint() + err = writeUnknownInt(w, x, err) + default: + _, err = fmt.Fprintf(w, "/* unknown wire type %d */", wire) + } + if err != nil { + return err + } + if err = w.WriteByte('\n'); err != nil { + return err + } + } + return nil +} + +func writeUnknownInt(w *textWriter, x uint64, err error) error { + if err == nil { + _, err = fmt.Fprint(w, x) + } else { + _, err = fmt.Fprintf(w, "/* %v */", err) + } + return err +} + +type int32Slice []int32 + +func (s int32Slice) Len() int { return len(s) } +func (s int32Slice) Less(i, j int) bool { return s[i] < s[j] } +func (s int32Slice) Swap(i, j int) { s[i], s[j] = s[j], s[i] } + +// writeExtensions writes all the extensions in pv. +// pv is assumed to be a pointer to a protocol message struct that is extendable. +func (tm *TextMarshaler) writeExtensions(w *textWriter, pv reflect.Value) error { + emap := extensionMaps[pv.Type().Elem()] + ep, _ := extendable(pv.Interface()) + + // Order the extensions by ID. + // This isn't strictly necessary, but it will give us + // canonical output, which will also make testing easier. + m, mu := ep.extensionsRead() + if m == nil { + return nil + } + mu.Lock() + ids := make([]int32, 0, len(m)) + for id := range m { + ids = append(ids, id) + } + sort.Sort(int32Slice(ids)) + mu.Unlock() + + for _, extNum := range ids { + ext := m[extNum] + var desc *ExtensionDesc + if emap != nil { + desc = emap[extNum] + } + if desc == nil { + // Unknown extension. + if err := writeUnknownStruct(w, ext.enc); err != nil { + return err + } + continue + } + + pb, err := GetExtension(ep, desc) + if err != nil { + return fmt.Errorf("failed getting extension: %v", err) + } + + // Repeated extensions will appear as a slice. + if !desc.repeated() { + if err := tm.writeExtension(w, desc.Name, pb); err != nil { + return err + } + } else { + v := reflect.ValueOf(pb) + for i := 0; i < v.Len(); i++ { + if err := tm.writeExtension(w, desc.Name, v.Index(i).Interface()); err != nil { + return err + } + } + } + } + return nil +} + +func (tm *TextMarshaler) writeExtension(w *textWriter, name string, pb interface{}) error { + if _, err := fmt.Fprintf(w, "[%s]:", name); err != nil { + return err + } + if !w.compact { + if err := w.WriteByte(' '); err != nil { + return err + } + } + if err := tm.writeAny(w, reflect.ValueOf(pb), nil); err != nil { + return err + } + if err := w.WriteByte('\n'); err != nil { + return err + } + return nil +} + +func (w *textWriter) writeIndent() { + if !w.complete { + return + } + remain := w.ind * 2 + for remain > 0 { + n := remain + if n > len(spaces) { + n = len(spaces) + } + w.w.Write(spaces[:n]) + remain -= n + } + w.complete = false +} + +// TextMarshaler is a configurable text format marshaler. +type TextMarshaler struct { + Compact bool // use compact text format (one line). + ExpandAny bool // expand google.protobuf.Any messages of known types +} + +// Marshal writes a given protocol buffer in text format. +// The only errors returned are from w. +func (tm *TextMarshaler) Marshal(w io.Writer, pb Message) error { + val := reflect.ValueOf(pb) + if pb == nil || val.IsNil() { + w.Write([]byte("")) + return nil + } + var bw *bufio.Writer + ww, ok := w.(writer) + if !ok { + bw = bufio.NewWriter(w) + ww = bw + } + aw := &textWriter{ + w: ww, + complete: true, + compact: tm.Compact, + } + + if etm, ok := pb.(encoding.TextMarshaler); ok { + text, err := etm.MarshalText() + if err != nil { + return err + } + if _, err = aw.Write(text); err != nil { + return err + } + if bw != nil { + return bw.Flush() + } + return nil + } + // Dereference the received pointer so we don't have outer < and >. + v := reflect.Indirect(val) + if err := tm.writeStruct(aw, v); err != nil { + return err + } + if bw != nil { + return bw.Flush() + } + return nil +} + +// Text is the same as Marshal, but returns the string directly. +func (tm *TextMarshaler) Text(pb Message) string { + var buf bytes.Buffer + tm.Marshal(&buf, pb) + return buf.String() +} + +var ( + defaultTextMarshaler = TextMarshaler{} + compactTextMarshaler = TextMarshaler{Compact: true} +) + +// TODO: consider removing some of the Marshal functions below. + +// MarshalText writes a given protocol buffer in text format. +// The only errors returned are from w. +func MarshalText(w io.Writer, pb Message) error { return defaultTextMarshaler.Marshal(w, pb) } + +// MarshalTextString is the same as MarshalText, but returns the string directly. +func MarshalTextString(pb Message) string { return defaultTextMarshaler.Text(pb) } + +// CompactText writes a given protocol buffer in compact text format (one line). +func CompactText(w io.Writer, pb Message) error { return compactTextMarshaler.Marshal(w, pb) } + +// CompactTextString is the same as CompactText, but returns the string directly. +func CompactTextString(pb Message) string { return compactTextMarshaler.Text(pb) } diff --git a/vendor/github.com/golang/protobuf/proto/text_parser.go b/vendor/github.com/golang/protobuf/proto/text_parser.go new file mode 100644 index 00000000..5e14513f --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/text_parser.go @@ -0,0 +1,895 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2010 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// 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 +// OWNER 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. + +package proto + +// Functions for parsing the Text protocol buffer format. +// TODO: message sets. + +import ( + "encoding" + "errors" + "fmt" + "reflect" + "strconv" + "strings" + "unicode/utf8" +) + +// Error string emitted when deserializing Any and fields are already set +const anyRepeatedlyUnpacked = "Any message unpacked multiple times, or %q already set" + +type ParseError struct { + Message string + Line int // 1-based line number + Offset int // 0-based byte offset from start of input +} + +func (p *ParseError) Error() string { + if p.Line == 1 { + // show offset only for first line + return fmt.Sprintf("line 1.%d: %v", p.Offset, p.Message) + } + return fmt.Sprintf("line %d: %v", p.Line, p.Message) +} + +type token struct { + value string + err *ParseError + line int // line number + offset int // byte number from start of input, not start of line + unquoted string // the unquoted version of value, if it was a quoted string +} + +func (t *token) String() string { + if t.err == nil { + return fmt.Sprintf("%q (line=%d, offset=%d)", t.value, t.line, t.offset) + } + return fmt.Sprintf("parse error: %v", t.err) +} + +type textParser struct { + s string // remaining input + done bool // whether the parsing is finished (success or error) + backed bool // whether back() was called + offset, line int + cur token +} + +func newTextParser(s string) *textParser { + p := new(textParser) + p.s = s + p.line = 1 + p.cur.line = 1 + return p +} + +func (p *textParser) errorf(format string, a ...interface{}) *ParseError { + pe := &ParseError{fmt.Sprintf(format, a...), p.cur.line, p.cur.offset} + p.cur.err = pe + p.done = true + return pe +} + +// Numbers and identifiers are matched by [-+._A-Za-z0-9] +func isIdentOrNumberChar(c byte) bool { + switch { + case 'A' <= c && c <= 'Z', 'a' <= c && c <= 'z': + return true + case '0' <= c && c <= '9': + return true + } + switch c { + case '-', '+', '.', '_': + return true + } + return false +} + +func isWhitespace(c byte) bool { + switch c { + case ' ', '\t', '\n', '\r': + return true + } + return false +} + +func isQuote(c byte) bool { + switch c { + case '"', '\'': + return true + } + return false +} + +func (p *textParser) skipWhitespace() { + i := 0 + for i < len(p.s) && (isWhitespace(p.s[i]) || p.s[i] == '#') { + if p.s[i] == '#' { + // comment; skip to end of line or input + for i < len(p.s) && p.s[i] != '\n' { + i++ + } + if i == len(p.s) { + break + } + } + if p.s[i] == '\n' { + p.line++ + } + i++ + } + p.offset += i + p.s = p.s[i:len(p.s)] + if len(p.s) == 0 { + p.done = true + } +} + +func (p *textParser) advance() { + // Skip whitespace + p.skipWhitespace() + if p.done { + return + } + + // Start of non-whitespace + p.cur.err = nil + p.cur.offset, p.cur.line = p.offset, p.line + p.cur.unquoted = "" + switch p.s[0] { + case '<', '>', '{', '}', ':', '[', ']', ';', ',', '/': + // Single symbol + p.cur.value, p.s = p.s[0:1], p.s[1:len(p.s)] + case '"', '\'': + // Quoted string + i := 1 + for i < len(p.s) && p.s[i] != p.s[0] && p.s[i] != '\n' { + if p.s[i] == '\\' && i+1 < len(p.s) { + // skip escaped char + i++ + } + i++ + } + if i >= len(p.s) || p.s[i] != p.s[0] { + p.errorf("unmatched quote") + return + } + unq, err := unquoteC(p.s[1:i], rune(p.s[0])) + if err != nil { + p.errorf("invalid quoted string %s: %v", p.s[0:i+1], err) + return + } + p.cur.value, p.s = p.s[0:i+1], p.s[i+1:len(p.s)] + p.cur.unquoted = unq + default: + i := 0 + for i < len(p.s) && isIdentOrNumberChar(p.s[i]) { + i++ + } + if i == 0 { + p.errorf("unexpected byte %#x", p.s[0]) + return + } + p.cur.value, p.s = p.s[0:i], p.s[i:len(p.s)] + } + p.offset += len(p.cur.value) +} + +var ( + errBadUTF8 = errors.New("proto: bad UTF-8") + errBadHex = errors.New("proto: bad hexadecimal") +) + +func unquoteC(s string, quote rune) (string, error) { + // This is based on C++'s tokenizer.cc. + // Despite its name, this is *not* parsing C syntax. + // For instance, "\0" is an invalid quoted string. + + // Avoid allocation in trivial cases. + simple := true + for _, r := range s { + if r == '\\' || r == quote { + simple = false + break + } + } + if simple { + return s, nil + } + + buf := make([]byte, 0, 3*len(s)/2) + for len(s) > 0 { + r, n := utf8.DecodeRuneInString(s) + if r == utf8.RuneError && n == 1 { + return "", errBadUTF8 + } + s = s[n:] + if r != '\\' { + if r < utf8.RuneSelf { + buf = append(buf, byte(r)) + } else { + buf = append(buf, string(r)...) + } + continue + } + + ch, tail, err := unescape(s) + if err != nil { + return "", err + } + buf = append(buf, ch...) + s = tail + } + return string(buf), nil +} + +func unescape(s string) (ch string, tail string, err error) { + r, n := utf8.DecodeRuneInString(s) + if r == utf8.RuneError && n == 1 { + return "", "", errBadUTF8 + } + s = s[n:] + switch r { + case 'a': + return "\a", s, nil + case 'b': + return "\b", s, nil + case 'f': + return "\f", s, nil + case 'n': + return "\n", s, nil + case 'r': + return "\r", s, nil + case 't': + return "\t", s, nil + case 'v': + return "\v", s, nil + case '?': + return "?", s, nil // trigraph workaround + case '\'', '"', '\\': + return string(r), s, nil + case '0', '1', '2', '3', '4', '5', '6', '7', 'x', 'X': + if len(s) < 2 { + return "", "", fmt.Errorf(`\%c requires 2 following digits`, r) + } + base := 8 + ss := s[:2] + s = s[2:] + if r == 'x' || r == 'X' { + base = 16 + } else { + ss = string(r) + ss + } + i, err := strconv.ParseUint(ss, base, 8) + if err != nil { + return "", "", err + } + return string([]byte{byte(i)}), s, nil + case 'u', 'U': + n := 4 + if r == 'U' { + n = 8 + } + if len(s) < n { + return "", "", fmt.Errorf(`\%c requires %d digits`, r, n) + } + + bs := make([]byte, n/2) + for i := 0; i < n; i += 2 { + a, ok1 := unhex(s[i]) + b, ok2 := unhex(s[i+1]) + if !ok1 || !ok2 { + return "", "", errBadHex + } + bs[i/2] = a<<4 | b + } + s = s[n:] + return string(bs), s, nil + } + return "", "", fmt.Errorf(`unknown escape \%c`, r) +} + +// Adapted from src/pkg/strconv/quote.go. +func unhex(b byte) (v byte, ok bool) { + switch { + case '0' <= b && b <= '9': + return b - '0', true + case 'a' <= b && b <= 'f': + return b - 'a' + 10, true + case 'A' <= b && b <= 'F': + return b - 'A' + 10, true + } + return 0, false +} + +// Back off the parser by one token. Can only be done between calls to next(). +// It makes the next advance() a no-op. +func (p *textParser) back() { p.backed = true } + +// Advances the parser and returns the new current token. +func (p *textParser) next() *token { + if p.backed || p.done { + p.backed = false + return &p.cur + } + p.advance() + if p.done { + p.cur.value = "" + } else if len(p.cur.value) > 0 && isQuote(p.cur.value[0]) { + // Look for multiple quoted strings separated by whitespace, + // and concatenate them. + cat := p.cur + for { + p.skipWhitespace() + if p.done || !isQuote(p.s[0]) { + break + } + p.advance() + if p.cur.err != nil { + return &p.cur + } + cat.value += " " + p.cur.value + cat.unquoted += p.cur.unquoted + } + p.done = false // parser may have seen EOF, but we want to return cat + p.cur = cat + } + return &p.cur +} + +func (p *textParser) consumeToken(s string) error { + tok := p.next() + if tok.err != nil { + return tok.err + } + if tok.value != s { + p.back() + return p.errorf("expected %q, found %q", s, tok.value) + } + return nil +} + +// Return a RequiredNotSetError indicating which required field was not set. +func (p *textParser) missingRequiredFieldError(sv reflect.Value) *RequiredNotSetError { + st := sv.Type() + sprops := GetProperties(st) + for i := 0; i < st.NumField(); i++ { + if !isNil(sv.Field(i)) { + continue + } + + props := sprops.Prop[i] + if props.Required { + return &RequiredNotSetError{fmt.Sprintf("%v.%v", st, props.OrigName)} + } + } + return &RequiredNotSetError{fmt.Sprintf("%v.", st)} // should not happen +} + +// Returns the index in the struct for the named field, as well as the parsed tag properties. +func structFieldByName(sprops *StructProperties, name string) (int, *Properties, bool) { + i, ok := sprops.decoderOrigNames[name] + if ok { + return i, sprops.Prop[i], true + } + return -1, nil, false +} + +// Consume a ':' from the input stream (if the next token is a colon), +// returning an error if a colon is needed but not present. +func (p *textParser) checkForColon(props *Properties, typ reflect.Type) *ParseError { + tok := p.next() + if tok.err != nil { + return tok.err + } + if tok.value != ":" { + // Colon is optional when the field is a group or message. + needColon := true + switch props.Wire { + case "group": + needColon = false + case "bytes": + // A "bytes" field is either a message, a string, or a repeated field; + // those three become *T, *string and []T respectively, so we can check for + // this field being a pointer to a non-string. + if typ.Kind() == reflect.Ptr { + // *T or *string + if typ.Elem().Kind() == reflect.String { + break + } + } else if typ.Kind() == reflect.Slice { + // []T or []*T + if typ.Elem().Kind() != reflect.Ptr { + break + } + } else if typ.Kind() == reflect.String { + // The proto3 exception is for a string field, + // which requires a colon. + break + } + needColon = false + } + if needColon { + return p.errorf("expected ':', found %q", tok.value) + } + p.back() + } + return nil +} + +func (p *textParser) readStruct(sv reflect.Value, terminator string) error { + st := sv.Type() + sprops := GetProperties(st) + reqCount := sprops.reqCount + var reqFieldErr error + fieldSet := make(map[string]bool) + // A struct is a sequence of "name: value", terminated by one of + // '>' or '}', or the end of the input. A name may also be + // "[extension]" or "[type/url]". + // + // The whole struct can also be an expanded Any message, like: + // [type/url] < ... struct contents ... > + for { + tok := p.next() + if tok.err != nil { + return tok.err + } + if tok.value == terminator { + break + } + if tok.value == "[" { + // Looks like an extension or an Any. + // + // TODO: Check whether we need to handle + // namespace rooted names (e.g. ".something.Foo"). + extName, err := p.consumeExtName() + if err != nil { + return err + } + + if s := strings.LastIndex(extName, "/"); s >= 0 { + // If it contains a slash, it's an Any type URL. + messageName := extName[s+1:] + mt := MessageType(messageName) + if mt == nil { + return p.errorf("unrecognized message %q in google.protobuf.Any", messageName) + } + tok = p.next() + if tok.err != nil { + return tok.err + } + // consume an optional colon + if tok.value == ":" { + tok = p.next() + if tok.err != nil { + return tok.err + } + } + var terminator string + switch tok.value { + case "<": + terminator = ">" + case "{": + terminator = "}" + default: + return p.errorf("expected '{' or '<', found %q", tok.value) + } + v := reflect.New(mt.Elem()) + if pe := p.readStruct(v.Elem(), terminator); pe != nil { + return pe + } + b, err := Marshal(v.Interface().(Message)) + if err != nil { + return p.errorf("failed to marshal message of type %q: %v", messageName, err) + } + if fieldSet["type_url"] { + return p.errorf(anyRepeatedlyUnpacked, "type_url") + } + if fieldSet["value"] { + return p.errorf(anyRepeatedlyUnpacked, "value") + } + sv.FieldByName("TypeUrl").SetString(extName) + sv.FieldByName("Value").SetBytes(b) + fieldSet["type_url"] = true + fieldSet["value"] = true + continue + } + + var desc *ExtensionDesc + // This could be faster, but it's functional. + // TODO: Do something smarter than a linear scan. + for _, d := range RegisteredExtensions(reflect.New(st).Interface().(Message)) { + if d.Name == extName { + desc = d + break + } + } + if desc == nil { + return p.errorf("unrecognized extension %q", extName) + } + + props := &Properties{} + props.Parse(desc.Tag) + + typ := reflect.TypeOf(desc.ExtensionType) + if err := p.checkForColon(props, typ); err != nil { + return err + } + + rep := desc.repeated() + + // Read the extension structure, and set it in + // the value we're constructing. + var ext reflect.Value + if !rep { + ext = reflect.New(typ).Elem() + } else { + ext = reflect.New(typ.Elem()).Elem() + } + if err := p.readAny(ext, props); err != nil { + if _, ok := err.(*RequiredNotSetError); !ok { + return err + } + reqFieldErr = err + } + ep := sv.Addr().Interface().(Message) + if !rep { + SetExtension(ep, desc, ext.Interface()) + } else { + old, err := GetExtension(ep, desc) + var sl reflect.Value + if err == nil { + sl = reflect.ValueOf(old) // existing slice + } else { + sl = reflect.MakeSlice(typ, 0, 1) + } + sl = reflect.Append(sl, ext) + SetExtension(ep, desc, sl.Interface()) + } + if err := p.consumeOptionalSeparator(); err != nil { + return err + } + continue + } + + // This is a normal, non-extension field. + name := tok.value + var dst reflect.Value + fi, props, ok := structFieldByName(sprops, name) + if ok { + dst = sv.Field(fi) + } else if oop, ok := sprops.OneofTypes[name]; ok { + // It is a oneof. + props = oop.Prop + nv := reflect.New(oop.Type.Elem()) + dst = nv.Elem().Field(0) + field := sv.Field(oop.Field) + if !field.IsNil() { + return p.errorf("field '%s' would overwrite already parsed oneof '%s'", name, sv.Type().Field(oop.Field).Name) + } + field.Set(nv) + } + if !dst.IsValid() { + return p.errorf("unknown field name %q in %v", name, st) + } + + if dst.Kind() == reflect.Map { + // Consume any colon. + if err := p.checkForColon(props, dst.Type()); err != nil { + return err + } + + // Construct the map if it doesn't already exist. + if dst.IsNil() { + dst.Set(reflect.MakeMap(dst.Type())) + } + key := reflect.New(dst.Type().Key()).Elem() + val := reflect.New(dst.Type().Elem()).Elem() + + // The map entry should be this sequence of tokens: + // < key : KEY value : VALUE > + // However, implementations may omit key or value, and technically + // we should support them in any order. See b/28924776 for a time + // this went wrong. + + tok := p.next() + var terminator string + switch tok.value { + case "<": + terminator = ">" + case "{": + terminator = "}" + default: + return p.errorf("expected '{' or '<', found %q", tok.value) + } + for { + tok := p.next() + if tok.err != nil { + return tok.err + } + if tok.value == terminator { + break + } + switch tok.value { + case "key": + if err := p.consumeToken(":"); err != nil { + return err + } + if err := p.readAny(key, props.mkeyprop); err != nil { + return err + } + if err := p.consumeOptionalSeparator(); err != nil { + return err + } + case "value": + if err := p.checkForColon(props.mvalprop, dst.Type().Elem()); err != nil { + return err + } + if err := p.readAny(val, props.mvalprop); err != nil { + return err + } + if err := p.consumeOptionalSeparator(); err != nil { + return err + } + default: + p.back() + return p.errorf(`expected "key", "value", or %q, found %q`, terminator, tok.value) + } + } + + dst.SetMapIndex(key, val) + continue + } + + // Check that it's not already set if it's not a repeated field. + if !props.Repeated && fieldSet[name] { + return p.errorf("non-repeated field %q was repeated", name) + } + + if err := p.checkForColon(props, dst.Type()); err != nil { + return err + } + + // Parse into the field. + fieldSet[name] = true + if err := p.readAny(dst, props); err != nil { + if _, ok := err.(*RequiredNotSetError); !ok { + return err + } + reqFieldErr = err + } + if props.Required { + reqCount-- + } + + if err := p.consumeOptionalSeparator(); err != nil { + return err + } + + } + + if reqCount > 0 { + return p.missingRequiredFieldError(sv) + } + return reqFieldErr +} + +// consumeExtName consumes extension name or expanded Any type URL and the +// following ']'. It returns the name or URL consumed. +func (p *textParser) consumeExtName() (string, error) { + tok := p.next() + if tok.err != nil { + return "", tok.err + } + + // If extension name or type url is quoted, it's a single token. + if len(tok.value) > 2 && isQuote(tok.value[0]) && tok.value[len(tok.value)-1] == tok.value[0] { + name, err := unquoteC(tok.value[1:len(tok.value)-1], rune(tok.value[0])) + if err != nil { + return "", err + } + return name, p.consumeToken("]") + } + + // Consume everything up to "]" + var parts []string + for tok.value != "]" { + parts = append(parts, tok.value) + tok = p.next() + if tok.err != nil { + return "", p.errorf("unrecognized type_url or extension name: %s", tok.err) + } + } + return strings.Join(parts, ""), nil +} + +// consumeOptionalSeparator consumes an optional semicolon or comma. +// It is used in readStruct to provide backward compatibility. +func (p *textParser) consumeOptionalSeparator() error { + tok := p.next() + if tok.err != nil { + return tok.err + } + if tok.value != ";" && tok.value != "," { + p.back() + } + return nil +} + +func (p *textParser) readAny(v reflect.Value, props *Properties) error { + tok := p.next() + if tok.err != nil { + return tok.err + } + if tok.value == "" { + return p.errorf("unexpected EOF") + } + + switch fv := v; fv.Kind() { + case reflect.Slice: + at := v.Type() + if at.Elem().Kind() == reflect.Uint8 { + // Special case for []byte + if tok.value[0] != '"' && tok.value[0] != '\'' { + // Deliberately written out here, as the error after + // this switch statement would write "invalid []byte: ...", + // which is not as user-friendly. + return p.errorf("invalid string: %v", tok.value) + } + bytes := []byte(tok.unquoted) + fv.Set(reflect.ValueOf(bytes)) + return nil + } + // Repeated field. + if tok.value == "[" { + // Repeated field with list notation, like [1,2,3]. + for { + fv.Set(reflect.Append(fv, reflect.New(at.Elem()).Elem())) + err := p.readAny(fv.Index(fv.Len()-1), props) + if err != nil { + return err + } + tok := p.next() + if tok.err != nil { + return tok.err + } + if tok.value == "]" { + break + } + if tok.value != "," { + return p.errorf("Expected ']' or ',' found %q", tok.value) + } + } + return nil + } + // One value of the repeated field. + p.back() + fv.Set(reflect.Append(fv, reflect.New(at.Elem()).Elem())) + return p.readAny(fv.Index(fv.Len()-1), props) + case reflect.Bool: + // true/1/t/True or false/f/0/False. + switch tok.value { + case "true", "1", "t", "True": + fv.SetBool(true) + return nil + case "false", "0", "f", "False": + fv.SetBool(false) + return nil + } + case reflect.Float32, reflect.Float64: + v := tok.value + // Ignore 'f' for compatibility with output generated by C++, but don't + // remove 'f' when the value is "-inf" or "inf". + if strings.HasSuffix(v, "f") && tok.value != "-inf" && tok.value != "inf" { + v = v[:len(v)-1] + } + if f, err := strconv.ParseFloat(v, fv.Type().Bits()); err == nil { + fv.SetFloat(f) + return nil + } + case reflect.Int32: + if x, err := strconv.ParseInt(tok.value, 0, 32); err == nil { + fv.SetInt(x) + return nil + } + + if len(props.Enum) == 0 { + break + } + m, ok := enumValueMaps[props.Enum] + if !ok { + break + } + x, ok := m[tok.value] + if !ok { + break + } + fv.SetInt(int64(x)) + return nil + case reflect.Int64: + if x, err := strconv.ParseInt(tok.value, 0, 64); err == nil { + fv.SetInt(x) + return nil + } + + case reflect.Ptr: + // A basic field (indirected through pointer), or a repeated message/group + p.back() + fv.Set(reflect.New(fv.Type().Elem())) + return p.readAny(fv.Elem(), props) + case reflect.String: + if tok.value[0] == '"' || tok.value[0] == '\'' { + fv.SetString(tok.unquoted) + return nil + } + case reflect.Struct: + var terminator string + switch tok.value { + case "{": + terminator = "}" + case "<": + terminator = ">" + default: + return p.errorf("expected '{' or '<', found %q", tok.value) + } + // TODO: Handle nested messages which implement encoding.TextUnmarshaler. + return p.readStruct(fv, terminator) + case reflect.Uint32: + if x, err := strconv.ParseUint(tok.value, 0, 32); err == nil { + fv.SetUint(x) + return nil + } + case reflect.Uint64: + if x, err := strconv.ParseUint(tok.value, 0, 64); err == nil { + fv.SetUint(x) + return nil + } + } + return p.errorf("invalid %v: %v", v.Type(), tok.value) +} + +// UnmarshalText reads a protocol buffer in Text format. UnmarshalText resets pb +// before starting to unmarshal, so any existing data in pb is always removed. +// If a required field is not set and no other error occurs, +// UnmarshalText returns *RequiredNotSetError. +func UnmarshalText(s string, pb Message) error { + if um, ok := pb.(encoding.TextUnmarshaler); ok { + err := um.UnmarshalText([]byte(s)) + return err + } + pb.Reset() + v := reflect.ValueOf(pb) + if pe := newTextParser(s).readStruct(v.Elem(), ""); pe != nil { + return pe + } + return nil +} diff --git a/vendor/github.com/golang/protobuf/proto/text_parser_test.go b/vendor/github.com/golang/protobuf/proto/text_parser_test.go new file mode 100644 index 00000000..8f7cb4d2 --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/text_parser_test.go @@ -0,0 +1,673 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2010 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// 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 +// OWNER 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. + +package proto_test + +import ( + "math" + "reflect" + "testing" + + . "github.com/golang/protobuf/proto" + proto3pb "github.com/golang/protobuf/proto/proto3_proto" + . "github.com/golang/protobuf/proto/testdata" +) + +type UnmarshalTextTest struct { + in string + err string // if "", no error expected + out *MyMessage +} + +func buildExtStructTest(text string) UnmarshalTextTest { + msg := &MyMessage{ + Count: Int32(42), + } + SetExtension(msg, E_Ext_More, &Ext{ + Data: String("Hello, world!"), + }) + return UnmarshalTextTest{in: text, out: msg} +} + +func buildExtDataTest(text string) UnmarshalTextTest { + msg := &MyMessage{ + Count: Int32(42), + } + SetExtension(msg, E_Ext_Text, String("Hello, world!")) + SetExtension(msg, E_Ext_Number, Int32(1729)) + return UnmarshalTextTest{in: text, out: msg} +} + +func buildExtRepStringTest(text string) UnmarshalTextTest { + msg := &MyMessage{ + Count: Int32(42), + } + if err := SetExtension(msg, E_Greeting, []string{"bula", "hola"}); err != nil { + panic(err) + } + return UnmarshalTextTest{in: text, out: msg} +} + +var unMarshalTextTests = []UnmarshalTextTest{ + // Basic + { + in: " count:42\n name:\"Dave\" ", + out: &MyMessage{ + Count: Int32(42), + Name: String("Dave"), + }, + }, + + // Empty quoted string + { + in: `count:42 name:""`, + out: &MyMessage{ + Count: Int32(42), + Name: String(""), + }, + }, + + // Quoted string concatenation with double quotes + { + in: `count:42 name: "My name is "` + "\n" + `"elsewhere"`, + out: &MyMessage{ + Count: Int32(42), + Name: String("My name is elsewhere"), + }, + }, + + // Quoted string concatenation with single quotes + { + in: "count:42 name: 'My name is '\n'elsewhere'", + out: &MyMessage{ + Count: Int32(42), + Name: String("My name is elsewhere"), + }, + }, + + // Quoted string concatenations with mixed quotes + { + in: "count:42 name: 'My name is '\n\"elsewhere\"", + out: &MyMessage{ + Count: Int32(42), + Name: String("My name is elsewhere"), + }, + }, + { + in: "count:42 name: \"My name is \"\n'elsewhere'", + out: &MyMessage{ + Count: Int32(42), + Name: String("My name is elsewhere"), + }, + }, + + // Quoted string with escaped apostrophe + { + in: `count:42 name: "HOLIDAY - New Year\'s Day"`, + out: &MyMessage{ + Count: Int32(42), + Name: String("HOLIDAY - New Year's Day"), + }, + }, + + // Quoted string with single quote + { + in: `count:42 name: 'Roger "The Ramster" Ramjet'`, + out: &MyMessage{ + Count: Int32(42), + Name: String(`Roger "The Ramster" Ramjet`), + }, + }, + + // Quoted string with all the accepted special characters from the C++ test + { + in: `count:42 name: ` + "\"\\\"A string with \\' characters \\n and \\r newlines and \\t tabs and \\001 slashes \\\\ and multiple spaces\"", + out: &MyMessage{ + Count: Int32(42), + Name: String("\"A string with ' characters \n and \r newlines and \t tabs and \001 slashes \\ and multiple spaces"), + }, + }, + + // Quoted string with quoted backslash + { + in: `count:42 name: "\\'xyz"`, + out: &MyMessage{ + Count: Int32(42), + Name: String(`\'xyz`), + }, + }, + + // Quoted string with UTF-8 bytes. + { + in: "count:42 name: '\303\277\302\201\xAB'", + out: &MyMessage{ + Count: Int32(42), + Name: String("\303\277\302\201\xAB"), + }, + }, + + // Bad quoted string + { + in: `inner: < host: "\0" >` + "\n", + err: `line 1.15: invalid quoted string "\0": \0 requires 2 following digits`, + }, + + // Number too large for int64 + { + in: "count: 1 others { key: 123456789012345678901 }", + err: "line 1.23: invalid int64: 123456789012345678901", + }, + + // Number too large for int32 + { + in: "count: 1234567890123", + err: "line 1.7: invalid int32: 1234567890123", + }, + + // Number in hexadecimal + { + in: "count: 0x2beef", + out: &MyMessage{ + Count: Int32(0x2beef), + }, + }, + + // Number in octal + { + in: "count: 024601", + out: &MyMessage{ + Count: Int32(024601), + }, + }, + + // Floating point number with "f" suffix + { + in: "count: 4 others:< weight: 17.0f >", + out: &MyMessage{ + Count: Int32(4), + Others: []*OtherMessage{ + { + Weight: Float32(17), + }, + }, + }, + }, + + // Floating point positive infinity + { + in: "count: 4 bigfloat: inf", + out: &MyMessage{ + Count: Int32(4), + Bigfloat: Float64(math.Inf(1)), + }, + }, + + // Floating point negative infinity + { + in: "count: 4 bigfloat: -inf", + out: &MyMessage{ + Count: Int32(4), + Bigfloat: Float64(math.Inf(-1)), + }, + }, + + // Number too large for float32 + { + in: "others:< weight: 12345678901234567890123456789012345678901234567890 >", + err: "line 1.17: invalid float32: 12345678901234567890123456789012345678901234567890", + }, + + // Number posing as a quoted string + { + in: `inner: < host: 12 >` + "\n", + err: `line 1.15: invalid string: 12`, + }, + + // Quoted string posing as int32 + { + in: `count: "12"`, + err: `line 1.7: invalid int32: "12"`, + }, + + // Quoted string posing a float32 + { + in: `others:< weight: "17.4" >`, + err: `line 1.17: invalid float32: "17.4"`, + }, + + // Enum + { + in: `count:42 bikeshed: BLUE`, + out: &MyMessage{ + Count: Int32(42), + Bikeshed: MyMessage_BLUE.Enum(), + }, + }, + + // Repeated field + { + in: `count:42 pet: "horsey" pet:"bunny"`, + out: &MyMessage{ + Count: Int32(42), + Pet: []string{"horsey", "bunny"}, + }, + }, + + // Repeated field with list notation + { + in: `count:42 pet: ["horsey", "bunny"]`, + out: &MyMessage{ + Count: Int32(42), + Pet: []string{"horsey", "bunny"}, + }, + }, + + // Repeated message with/without colon and <>/{} + { + in: `count:42 others:{} others{} others:<> others:{}`, + out: &MyMessage{ + Count: Int32(42), + Others: []*OtherMessage{ + {}, + {}, + {}, + {}, + }, + }, + }, + + // Missing colon for inner message + { + in: `count:42 inner < host: "cauchy.syd" >`, + out: &MyMessage{ + Count: Int32(42), + Inner: &InnerMessage{ + Host: String("cauchy.syd"), + }, + }, + }, + + // Missing colon for string field + { + in: `name "Dave"`, + err: `line 1.5: expected ':', found "\"Dave\""`, + }, + + // Missing colon for int32 field + { + in: `count 42`, + err: `line 1.6: expected ':', found "42"`, + }, + + // Missing required field + { + in: `name: "Pawel"`, + err: `proto: required field "testdata.MyMessage.count" not set`, + out: &MyMessage{ + Name: String("Pawel"), + }, + }, + + // Missing required field in a required submessage + { + in: `count: 42 we_must_go_deeper < leo_finally_won_an_oscar <> >`, + err: `proto: required field "testdata.InnerMessage.host" not set`, + out: &MyMessage{ + Count: Int32(42), + WeMustGoDeeper: &RequiredInnerMessage{LeoFinallyWonAnOscar: &InnerMessage{}}, + }, + }, + + // Repeated non-repeated field + { + in: `name: "Rob" name: "Russ"`, + err: `line 1.12: non-repeated field "name" was repeated`, + }, + + // Group + { + in: `count: 17 SomeGroup { group_field: 12 }`, + out: &MyMessage{ + Count: Int32(17), + Somegroup: &MyMessage_SomeGroup{ + GroupField: Int32(12), + }, + }, + }, + + // Semicolon between fields + { + in: `count:3;name:"Calvin"`, + out: &MyMessage{ + Count: Int32(3), + Name: String("Calvin"), + }, + }, + // Comma between fields + { + in: `count:4,name:"Ezekiel"`, + out: &MyMessage{ + Count: Int32(4), + Name: String("Ezekiel"), + }, + }, + + // Boolean false + { + in: `count:42 inner { host: "example.com" connected: false }`, + out: &MyMessage{ + Count: Int32(42), + Inner: &InnerMessage{ + Host: String("example.com"), + Connected: Bool(false), + }, + }, + }, + // Boolean true + { + in: `count:42 inner { host: "example.com" connected: true }`, + out: &MyMessage{ + Count: Int32(42), + Inner: &InnerMessage{ + Host: String("example.com"), + Connected: Bool(true), + }, + }, + }, + // Boolean 0 + { + in: `count:42 inner { host: "example.com" connected: 0 }`, + out: &MyMessage{ + Count: Int32(42), + Inner: &InnerMessage{ + Host: String("example.com"), + Connected: Bool(false), + }, + }, + }, + // Boolean 1 + { + in: `count:42 inner { host: "example.com" connected: 1 }`, + out: &MyMessage{ + Count: Int32(42), + Inner: &InnerMessage{ + Host: String("example.com"), + Connected: Bool(true), + }, + }, + }, + // Boolean f + { + in: `count:42 inner { host: "example.com" connected: f }`, + out: &MyMessage{ + Count: Int32(42), + Inner: &InnerMessage{ + Host: String("example.com"), + Connected: Bool(false), + }, + }, + }, + // Boolean t + { + in: `count:42 inner { host: "example.com" connected: t }`, + out: &MyMessage{ + Count: Int32(42), + Inner: &InnerMessage{ + Host: String("example.com"), + Connected: Bool(true), + }, + }, + }, + // Boolean False + { + in: `count:42 inner { host: "example.com" connected: False }`, + out: &MyMessage{ + Count: Int32(42), + Inner: &InnerMessage{ + Host: String("example.com"), + Connected: Bool(false), + }, + }, + }, + // Boolean True + { + in: `count:42 inner { host: "example.com" connected: True }`, + out: &MyMessage{ + Count: Int32(42), + Inner: &InnerMessage{ + Host: String("example.com"), + Connected: Bool(true), + }, + }, + }, + + // Extension + buildExtStructTest(`count: 42 [testdata.Ext.more]:`), + buildExtStructTest(`count: 42 [testdata.Ext.more] {data:"Hello, world!"}`), + buildExtDataTest(`count: 42 [testdata.Ext.text]:"Hello, world!" [testdata.Ext.number]:1729`), + buildExtRepStringTest(`count: 42 [testdata.greeting]:"bula" [testdata.greeting]:"hola"`), + + // Big all-in-one + { + in: "count:42 # Meaning\n" + + `name:"Dave" ` + + `quote:"\"I didn't want to go.\"" ` + + `pet:"bunny" ` + + `pet:"kitty" ` + + `pet:"horsey" ` + + `inner:<` + + ` host:"footrest.syd" ` + + ` port:7001 ` + + ` connected:true ` + + `> ` + + `others:<` + + ` key:3735928559 ` + + ` value:"\x01A\a\f" ` + + `> ` + + `others:<` + + " weight:58.9 # Atomic weight of Co\n" + + ` inner:<` + + ` host:"lesha.mtv" ` + + ` port:8002 ` + + ` >` + + `>`, + out: &MyMessage{ + Count: Int32(42), + Name: String("Dave"), + Quote: String(`"I didn't want to go."`), + Pet: []string{"bunny", "kitty", "horsey"}, + Inner: &InnerMessage{ + Host: String("footrest.syd"), + Port: Int32(7001), + Connected: Bool(true), + }, + Others: []*OtherMessage{ + { + Key: Int64(3735928559), + Value: []byte{0x1, 'A', '\a', '\f'}, + }, + { + Weight: Float32(58.9), + Inner: &InnerMessage{ + Host: String("lesha.mtv"), + Port: Int32(8002), + }, + }, + }, + }, + }, +} + +func TestUnmarshalText(t *testing.T) { + for i, test := range unMarshalTextTests { + pb := new(MyMessage) + err := UnmarshalText(test.in, pb) + if test.err == "" { + // We don't expect failure. + if err != nil { + t.Errorf("Test %d: Unexpected error: %v", i, err) + } else if !reflect.DeepEqual(pb, test.out) { + t.Errorf("Test %d: Incorrect populated \nHave: %v\nWant: %v", + i, pb, test.out) + } + } else { + // We do expect failure. + if err == nil { + t.Errorf("Test %d: Didn't get expected error: %v", i, test.err) + } else if err.Error() != test.err { + t.Errorf("Test %d: Incorrect error.\nHave: %v\nWant: %v", + i, err.Error(), test.err) + } else if _, ok := err.(*RequiredNotSetError); ok && test.out != nil && !reflect.DeepEqual(pb, test.out) { + t.Errorf("Test %d: Incorrect populated \nHave: %v\nWant: %v", + i, pb, test.out) + } + } + } +} + +func TestUnmarshalTextCustomMessage(t *testing.T) { + msg := &textMessage{} + if err := UnmarshalText("custom", msg); err != nil { + t.Errorf("Unexpected error from custom unmarshal: %v", err) + } + if UnmarshalText("not custom", msg) == nil { + t.Errorf("Didn't get expected error from custom unmarshal") + } +} + +// Regression test; this caused a panic. +func TestRepeatedEnum(t *testing.T) { + pb := new(RepeatedEnum) + if err := UnmarshalText("color: RED", pb); err != nil { + t.Fatal(err) + } + exp := &RepeatedEnum{ + Color: []RepeatedEnum_Color{RepeatedEnum_RED}, + } + if !Equal(pb, exp) { + t.Errorf("Incorrect populated \nHave: %v\nWant: %v", pb, exp) + } +} + +func TestProto3TextParsing(t *testing.T) { + m := new(proto3pb.Message) + const in = `name: "Wallace" true_scotsman: true` + want := &proto3pb.Message{ + Name: "Wallace", + TrueScotsman: true, + } + if err := UnmarshalText(in, m); err != nil { + t.Fatal(err) + } + if !Equal(m, want) { + t.Errorf("\n got %v\nwant %v", m, want) + } +} + +func TestMapParsing(t *testing.T) { + m := new(MessageWithMap) + const in = `name_mapping: name_mapping:` + + `msg_mapping:,>` + // separating commas are okay + `msg_mapping>` + // no colon after "value" + `msg_mapping:>` + // omitted key + `msg_mapping:` + // omitted value + `byte_mapping:` + + `byte_mapping:<>` // omitted key and value + want := &MessageWithMap{ + NameMapping: map[int32]string{ + 1: "Beatles", + 1234: "Feist", + }, + MsgMapping: map[int64]*FloatingPoint{ + -4: {F: Float64(2.0)}, + -2: {F: Float64(4.0)}, + 0: {F: Float64(5.0)}, + 1: nil, + }, + ByteMapping: map[bool][]byte{ + false: nil, + true: []byte("so be it"), + }, + } + if err := UnmarshalText(in, m); err != nil { + t.Fatal(err) + } + if !Equal(m, want) { + t.Errorf("\n got %v\nwant %v", m, want) + } +} + +func TestOneofParsing(t *testing.T) { + const in = `name:"Shrek"` + m := new(Communique) + want := &Communique{Union: &Communique_Name{"Shrek"}} + if err := UnmarshalText(in, m); err != nil { + t.Fatal(err) + } + if !Equal(m, want) { + t.Errorf("\n got %v\nwant %v", m, want) + } + + const inOverwrite = `name:"Shrek" number:42` + m = new(Communique) + testErr := "line 1.13: field 'number' would overwrite already parsed oneof 'Union'" + if err := UnmarshalText(inOverwrite, m); err == nil { + t.Errorf("TestOneofParsing: Didn't get expected error: %v", testErr) + } else if err.Error() != testErr { + t.Errorf("TestOneofParsing: Incorrect error.\nHave: %v\nWant: %v", + err.Error(), testErr) + } + +} + +var benchInput string + +func init() { + benchInput = "count: 4\n" + for i := 0; i < 1000; i++ { + benchInput += "pet: \"fido\"\n" + } + + // Check it is valid input. + pb := new(MyMessage) + err := UnmarshalText(benchInput, pb) + if err != nil { + panic("Bad benchmark input: " + err.Error()) + } +} + +func BenchmarkUnmarshalText(b *testing.B) { + pb := new(MyMessage) + for i := 0; i < b.N; i++ { + UnmarshalText(benchInput, pb) + } + b.SetBytes(int64(len(benchInput))) +} diff --git a/vendor/github.com/golang/protobuf/proto/text_test.go b/vendor/github.com/golang/protobuf/proto/text_test.go new file mode 100644 index 00000000..3eabacac --- /dev/null +++ b/vendor/github.com/golang/protobuf/proto/text_test.go @@ -0,0 +1,474 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2010 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// 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 +// OWNER 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. + +package proto_test + +import ( + "bytes" + "errors" + "io/ioutil" + "math" + "strings" + "testing" + + "github.com/golang/protobuf/proto" + + proto3pb "github.com/golang/protobuf/proto/proto3_proto" + pb "github.com/golang/protobuf/proto/testdata" +) + +// textMessage implements the methods that allow it to marshal and unmarshal +// itself as text. +type textMessage struct { +} + +func (*textMessage) MarshalText() ([]byte, error) { + return []byte("custom"), nil +} + +func (*textMessage) UnmarshalText(bytes []byte) error { + if string(bytes) != "custom" { + return errors.New("expected 'custom'") + } + return nil +} + +func (*textMessage) Reset() {} +func (*textMessage) String() string { return "" } +func (*textMessage) ProtoMessage() {} + +func newTestMessage() *pb.MyMessage { + msg := &pb.MyMessage{ + Count: proto.Int32(42), + Name: proto.String("Dave"), + Quote: proto.String(`"I didn't want to go."`), + Pet: []string{"bunny", "kitty", "horsey"}, + Inner: &pb.InnerMessage{ + Host: proto.String("footrest.syd"), + Port: proto.Int32(7001), + Connected: proto.Bool(true), + }, + Others: []*pb.OtherMessage{ + { + Key: proto.Int64(0xdeadbeef), + Value: []byte{1, 65, 7, 12}, + }, + { + Weight: proto.Float32(6.022), + Inner: &pb.InnerMessage{ + Host: proto.String("lesha.mtv"), + Port: proto.Int32(8002), + }, + }, + }, + Bikeshed: pb.MyMessage_BLUE.Enum(), + Somegroup: &pb.MyMessage_SomeGroup{ + GroupField: proto.Int32(8), + }, + // One normally wouldn't do this. + // This is an undeclared tag 13, as a varint (wire type 0) with value 4. + XXX_unrecognized: []byte{13<<3 | 0, 4}, + } + ext := &pb.Ext{ + Data: proto.String("Big gobs for big rats"), + } + if err := proto.SetExtension(msg, pb.E_Ext_More, ext); err != nil { + panic(err) + } + greetings := []string{"adg", "easy", "cow"} + if err := proto.SetExtension(msg, pb.E_Greeting, greetings); err != nil { + panic(err) + } + + // Add an unknown extension. We marshal a pb.Ext, and fake the ID. + b, err := proto.Marshal(&pb.Ext{Data: proto.String("3G skiing")}) + if err != nil { + panic(err) + } + b = append(proto.EncodeVarint(201<<3|proto.WireBytes), b...) + proto.SetRawExtension(msg, 201, b) + + // Extensions can be plain fields, too, so let's test that. + b = append(proto.EncodeVarint(202<<3|proto.WireVarint), 19) + proto.SetRawExtension(msg, 202, b) + + return msg +} + +const text = `count: 42 +name: "Dave" +quote: "\"I didn't want to go.\"" +pet: "bunny" +pet: "kitty" +pet: "horsey" +inner: < + host: "footrest.syd" + port: 7001 + connected: true +> +others: < + key: 3735928559 + value: "\001A\007\014" +> +others: < + weight: 6.022 + inner: < + host: "lesha.mtv" + port: 8002 + > +> +bikeshed: BLUE +SomeGroup { + group_field: 8 +} +/* 2 unknown bytes */ +13: 4 +[testdata.Ext.more]: < + data: "Big gobs for big rats" +> +[testdata.greeting]: "adg" +[testdata.greeting]: "easy" +[testdata.greeting]: "cow" +/* 13 unknown bytes */ +201: "\t3G skiing" +/* 3 unknown bytes */ +202: 19 +` + +func TestMarshalText(t *testing.T) { + buf := new(bytes.Buffer) + if err := proto.MarshalText(buf, newTestMessage()); err != nil { + t.Fatalf("proto.MarshalText: %v", err) + } + s := buf.String() + if s != text { + t.Errorf("Got:\n===\n%v===\nExpected:\n===\n%v===\n", s, text) + } +} + +func TestMarshalTextCustomMessage(t *testing.T) { + buf := new(bytes.Buffer) + if err := proto.MarshalText(buf, &textMessage{}); err != nil { + t.Fatalf("proto.MarshalText: %v", err) + } + s := buf.String() + if s != "custom" { + t.Errorf("Got %q, expected %q", s, "custom") + } +} +func TestMarshalTextNil(t *testing.T) { + want := "" + tests := []proto.Message{nil, (*pb.MyMessage)(nil)} + for i, test := range tests { + buf := new(bytes.Buffer) + if err := proto.MarshalText(buf, test); err != nil { + t.Fatal(err) + } + if got := buf.String(); got != want { + t.Errorf("%d: got %q want %q", i, got, want) + } + } +} + +func TestMarshalTextUnknownEnum(t *testing.T) { + // The Color enum only specifies values 0-2. + m := &pb.MyMessage{Bikeshed: pb.MyMessage_Color(3).Enum()} + got := m.String() + const want = `bikeshed:3 ` + if got != want { + t.Errorf("\n got %q\nwant %q", got, want) + } +} + +func TestTextOneof(t *testing.T) { + tests := []struct { + m proto.Message + want string + }{ + // zero message + {&pb.Communique{}, ``}, + // scalar field + {&pb.Communique{Union: &pb.Communique_Number{4}}, `number:4`}, + // message field + {&pb.Communique{Union: &pb.Communique_Msg{ + &pb.Strings{StringField: proto.String("why hello!")}, + }}, `msg:`}, + // bad oneof (should not panic) + {&pb.Communique{Union: &pb.Communique_Msg{nil}}, `msg:/* nil */`}, + } + for _, test := range tests { + got := strings.TrimSpace(test.m.String()) + if got != test.want { + t.Errorf("\n got %s\nwant %s", got, test.want) + } + } +} + +func BenchmarkMarshalTextBuffered(b *testing.B) { + buf := new(bytes.Buffer) + m := newTestMessage() + for i := 0; i < b.N; i++ { + buf.Reset() + proto.MarshalText(buf, m) + } +} + +func BenchmarkMarshalTextUnbuffered(b *testing.B) { + w := ioutil.Discard + m := newTestMessage() + for i := 0; i < b.N; i++ { + proto.MarshalText(w, m) + } +} + +func compact(src string) string { + // s/[ \n]+/ /g; s/ $//; + dst := make([]byte, len(src)) + space, comment := false, false + j := 0 + for i := 0; i < len(src); i++ { + if strings.HasPrefix(src[i:], "/*") { + comment = true + i++ + continue + } + if comment && strings.HasPrefix(src[i:], "*/") { + comment = false + i++ + continue + } + if comment { + continue + } + c := src[i] + if c == ' ' || c == '\n' { + space = true + continue + } + if j > 0 && (dst[j-1] == ':' || dst[j-1] == '<' || dst[j-1] == '{') { + space = false + } + if c == '{' { + space = false + } + if space { + dst[j] = ' ' + j++ + space = false + } + dst[j] = c + j++ + } + if space { + dst[j] = ' ' + j++ + } + return string(dst[0:j]) +} + +var compactText = compact(text) + +func TestCompactText(t *testing.T) { + s := proto.CompactTextString(newTestMessage()) + if s != compactText { + t.Errorf("Got:\n===\n%v===\nExpected:\n===\n%v\n===\n", s, compactText) + } +} + +func TestStringEscaping(t *testing.T) { + testCases := []struct { + in *pb.Strings + out string + }{ + { + // Test data from C++ test (TextFormatTest.StringEscape). + // Single divergence: we don't escape apostrophes. + &pb.Strings{StringField: proto.String("\"A string with ' characters \n and \r newlines and \t tabs and \001 slashes \\ and multiple spaces")}, + "string_field: \"\\\"A string with ' characters \\n and \\r newlines and \\t tabs and \\001 slashes \\\\ and multiple spaces\"\n", + }, + { + // Test data from the same C++ test. + &pb.Strings{StringField: proto.String("\350\260\267\346\255\214")}, + "string_field: \"\\350\\260\\267\\346\\255\\214\"\n", + }, + { + // Some UTF-8. + &pb.Strings{StringField: proto.String("\x00\x01\xff\x81")}, + `string_field: "\000\001\377\201"` + "\n", + }, + } + + for i, tc := range testCases { + var buf bytes.Buffer + if err := proto.MarshalText(&buf, tc.in); err != nil { + t.Errorf("proto.MarsalText: %v", err) + continue + } + s := buf.String() + if s != tc.out { + t.Errorf("#%d: Got:\n%s\nExpected:\n%s\n", i, s, tc.out) + continue + } + + // Check round-trip. + pb := new(pb.Strings) + if err := proto.UnmarshalText(s, pb); err != nil { + t.Errorf("#%d: UnmarshalText: %v", i, err) + continue + } + if !proto.Equal(pb, tc.in) { + t.Errorf("#%d: Round-trip failed:\nstart: %v\n end: %v", i, tc.in, pb) + } + } +} + +// A limitedWriter accepts some output before it fails. +// This is a proxy for something like a nearly-full or imminently-failing disk, +// or a network connection that is about to die. +type limitedWriter struct { + b bytes.Buffer + limit int +} + +var outOfSpace = errors.New("proto: insufficient space") + +func (w *limitedWriter) Write(p []byte) (n int, err error) { + var avail = w.limit - w.b.Len() + if avail <= 0 { + return 0, outOfSpace + } + if len(p) <= avail { + return w.b.Write(p) + } + n, _ = w.b.Write(p[:avail]) + return n, outOfSpace +} + +func TestMarshalTextFailing(t *testing.T) { + // Try lots of different sizes to exercise more error code-paths. + for lim := 0; lim < len(text); lim++ { + buf := new(limitedWriter) + buf.limit = lim + err := proto.MarshalText(buf, newTestMessage()) + // We expect a certain error, but also some partial results in the buffer. + if err != outOfSpace { + t.Errorf("Got:\n===\n%v===\nExpected:\n===\n%v===\n", err, outOfSpace) + } + s := buf.b.String() + x := text[:buf.limit] + if s != x { + t.Errorf("Got:\n===\n%v===\nExpected:\n===\n%v===\n", s, x) + } + } +} + +func TestFloats(t *testing.T) { + tests := []struct { + f float64 + want string + }{ + {0, "0"}, + {4.7, "4.7"}, + {math.Inf(1), "inf"}, + {math.Inf(-1), "-inf"}, + {math.NaN(), "nan"}, + } + for _, test := range tests { + msg := &pb.FloatingPoint{F: &test.f} + got := strings.TrimSpace(msg.String()) + want := `f:` + test.want + if got != want { + t.Errorf("f=%f: got %q, want %q", test.f, got, want) + } + } +} + +func TestRepeatedNilText(t *testing.T) { + m := &pb.MessageList{ + Message: []*pb.MessageList_Message{ + nil, + &pb.MessageList_Message{ + Name: proto.String("Horse"), + }, + nil, + }, + } + want := `Message +Message { + name: "Horse" +} +Message +` + if s := proto.MarshalTextString(m); s != want { + t.Errorf(" got: %s\nwant: %s", s, want) + } +} + +func TestProto3Text(t *testing.T) { + tests := []struct { + m proto.Message + want string + }{ + // zero message + {&proto3pb.Message{}, ``}, + // zero message except for an empty byte slice + {&proto3pb.Message{Data: []byte{}}, ``}, + // trivial case + {&proto3pb.Message{Name: "Rob", HeightInCm: 175}, `name:"Rob" height_in_cm:175`}, + // empty map + {&pb.MessageWithMap{}, ``}, + // non-empty map; map format is the same as a repeated struct, + // and they are sorted by key (numerically for numeric keys). + { + &pb.MessageWithMap{NameMapping: map[int32]string{ + -1: "Negatory", + 7: "Lucky", + 1234: "Feist", + 6345789: "Otis", + }}, + `name_mapping: ` + + `name_mapping: ` + + `name_mapping: ` + + `name_mapping:`, + }, + // map with nil value; not well-defined, but we shouldn't crash + { + &pb.MessageWithMap{MsgMapping: map[int64]*pb.FloatingPoint{7: nil}}, + `msg_mapping:`, + }, + } + for _, test := range tests { + got := strings.TrimSpace(test.m.String()) + if got != test.want { + t.Errorf("\n got %s\nwant %s", got, test.want) + } + } +} diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/Makefile b/vendor/github.com/golang/protobuf/protoc-gen-go/Makefile new file mode 100644 index 00000000..a42cc371 --- /dev/null +++ b/vendor/github.com/golang/protobuf/protoc-gen-go/Makefile @@ -0,0 +1,33 @@ +# Go support for Protocol Buffers - Google's data interchange format +# +# Copyright 2010 The Go Authors. All rights reserved. +# https://github.com/golang/protobuf +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# 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 +# OWNER 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. + +test: + cd testdata && make test diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/descriptor/Makefile b/vendor/github.com/golang/protobuf/protoc-gen-go/descriptor/Makefile new file mode 100644 index 00000000..f706871a --- /dev/null +++ b/vendor/github.com/golang/protobuf/protoc-gen-go/descriptor/Makefile @@ -0,0 +1,37 @@ +# Go support for Protocol Buffers - Google's data interchange format +# +# Copyright 2010 The Go Authors. All rights reserved. +# https://github.com/golang/protobuf +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# 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 +# OWNER 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. + +# Not stored here, but descriptor.proto is in https://github.com/google/protobuf/ +# at src/google/protobuf/descriptor.proto +regenerate: + @echo WARNING! THIS RULE IS PROBABLY NOT RIGHT FOR YOUR INSTALLATION + cp $(HOME)/src/protobuf/include/google/protobuf/descriptor.proto . + protoc --go_out=../../../../.. -I$(HOME)/src/protobuf/include $(HOME)/src/protobuf/include/google/protobuf/descriptor.proto diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/descriptor/descriptor.pb.go b/vendor/github.com/golang/protobuf/protoc-gen-go/descriptor/descriptor.pb.go new file mode 100644 index 00000000..c6a91bca --- /dev/null +++ b/vendor/github.com/golang/protobuf/protoc-gen-go/descriptor/descriptor.pb.go @@ -0,0 +1,2215 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: google/protobuf/descriptor.proto + +/* +Package descriptor is a generated protocol buffer package. + +It is generated from these files: + google/protobuf/descriptor.proto + +It has these top-level messages: + FileDescriptorSet + FileDescriptorProto + DescriptorProto + ExtensionRangeOptions + FieldDescriptorProto + OneofDescriptorProto + EnumDescriptorProto + EnumValueDescriptorProto + ServiceDescriptorProto + MethodDescriptorProto + FileOptions + MessageOptions + FieldOptions + OneofOptions + EnumOptions + EnumValueOptions + ServiceOptions + MethodOptions + UninterpretedOption + SourceCodeInfo + GeneratedCodeInfo +*/ +package descriptor + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package + +type FieldDescriptorProto_Type int32 + +const ( + // 0 is reserved for errors. + // Order is weird for historical reasons. + FieldDescriptorProto_TYPE_DOUBLE FieldDescriptorProto_Type = 1 + FieldDescriptorProto_TYPE_FLOAT FieldDescriptorProto_Type = 2 + // Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT64 if + // negative values are likely. + FieldDescriptorProto_TYPE_INT64 FieldDescriptorProto_Type = 3 + FieldDescriptorProto_TYPE_UINT64 FieldDescriptorProto_Type = 4 + // Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT32 if + // negative values are likely. + FieldDescriptorProto_TYPE_INT32 FieldDescriptorProto_Type = 5 + FieldDescriptorProto_TYPE_FIXED64 FieldDescriptorProto_Type = 6 + FieldDescriptorProto_TYPE_FIXED32 FieldDescriptorProto_Type = 7 + FieldDescriptorProto_TYPE_BOOL FieldDescriptorProto_Type = 8 + FieldDescriptorProto_TYPE_STRING FieldDescriptorProto_Type = 9 + // Tag-delimited aggregate. + // Group type is deprecated and not supported in proto3. However, Proto3 + // implementations should still be able to parse the group wire format and + // treat group fields as unknown fields. + FieldDescriptorProto_TYPE_GROUP FieldDescriptorProto_Type = 10 + FieldDescriptorProto_TYPE_MESSAGE FieldDescriptorProto_Type = 11 + // New in version 2. + FieldDescriptorProto_TYPE_BYTES FieldDescriptorProto_Type = 12 + FieldDescriptorProto_TYPE_UINT32 FieldDescriptorProto_Type = 13 + FieldDescriptorProto_TYPE_ENUM FieldDescriptorProto_Type = 14 + FieldDescriptorProto_TYPE_SFIXED32 FieldDescriptorProto_Type = 15 + FieldDescriptorProto_TYPE_SFIXED64 FieldDescriptorProto_Type = 16 + FieldDescriptorProto_TYPE_SINT32 FieldDescriptorProto_Type = 17 + FieldDescriptorProto_TYPE_SINT64 FieldDescriptorProto_Type = 18 +) + +var FieldDescriptorProto_Type_name = map[int32]string{ + 1: "TYPE_DOUBLE", + 2: "TYPE_FLOAT", + 3: "TYPE_INT64", + 4: "TYPE_UINT64", + 5: "TYPE_INT32", + 6: "TYPE_FIXED64", + 7: "TYPE_FIXED32", + 8: "TYPE_BOOL", + 9: "TYPE_STRING", + 10: "TYPE_GROUP", + 11: "TYPE_MESSAGE", + 12: "TYPE_BYTES", + 13: "TYPE_UINT32", + 14: "TYPE_ENUM", + 15: "TYPE_SFIXED32", + 16: "TYPE_SFIXED64", + 17: "TYPE_SINT32", + 18: "TYPE_SINT64", +} +var FieldDescriptorProto_Type_value = map[string]int32{ + "TYPE_DOUBLE": 1, + "TYPE_FLOAT": 2, + "TYPE_INT64": 3, + "TYPE_UINT64": 4, + "TYPE_INT32": 5, + "TYPE_FIXED64": 6, + "TYPE_FIXED32": 7, + "TYPE_BOOL": 8, + "TYPE_STRING": 9, + "TYPE_GROUP": 10, + "TYPE_MESSAGE": 11, + "TYPE_BYTES": 12, + "TYPE_UINT32": 13, + "TYPE_ENUM": 14, + "TYPE_SFIXED32": 15, + "TYPE_SFIXED64": 16, + "TYPE_SINT32": 17, + "TYPE_SINT64": 18, +} + +func (x FieldDescriptorProto_Type) Enum() *FieldDescriptorProto_Type { + p := new(FieldDescriptorProto_Type) + *p = x + return p +} +func (x FieldDescriptorProto_Type) String() string { + return proto.EnumName(FieldDescriptorProto_Type_name, int32(x)) +} +func (x *FieldDescriptorProto_Type) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(FieldDescriptorProto_Type_value, data, "FieldDescriptorProto_Type") + if err != nil { + return err + } + *x = FieldDescriptorProto_Type(value) + return nil +} +func (FieldDescriptorProto_Type) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{4, 0} } + +type FieldDescriptorProto_Label int32 + +const ( + // 0 is reserved for errors + FieldDescriptorProto_LABEL_OPTIONAL FieldDescriptorProto_Label = 1 + FieldDescriptorProto_LABEL_REQUIRED FieldDescriptorProto_Label = 2 + FieldDescriptorProto_LABEL_REPEATED FieldDescriptorProto_Label = 3 +) + +var FieldDescriptorProto_Label_name = map[int32]string{ + 1: "LABEL_OPTIONAL", + 2: "LABEL_REQUIRED", + 3: "LABEL_REPEATED", +} +var FieldDescriptorProto_Label_value = map[string]int32{ + "LABEL_OPTIONAL": 1, + "LABEL_REQUIRED": 2, + "LABEL_REPEATED": 3, +} + +func (x FieldDescriptorProto_Label) Enum() *FieldDescriptorProto_Label { + p := new(FieldDescriptorProto_Label) + *p = x + return p +} +func (x FieldDescriptorProto_Label) String() string { + return proto.EnumName(FieldDescriptorProto_Label_name, int32(x)) +} +func (x *FieldDescriptorProto_Label) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(FieldDescriptorProto_Label_value, data, "FieldDescriptorProto_Label") + if err != nil { + return err + } + *x = FieldDescriptorProto_Label(value) + return nil +} +func (FieldDescriptorProto_Label) EnumDescriptor() ([]byte, []int) { + return fileDescriptor0, []int{4, 1} +} + +// Generated classes can be optimized for speed or code size. +type FileOptions_OptimizeMode int32 + +const ( + FileOptions_SPEED FileOptions_OptimizeMode = 1 + // etc. + FileOptions_CODE_SIZE FileOptions_OptimizeMode = 2 + FileOptions_LITE_RUNTIME FileOptions_OptimizeMode = 3 +) + +var FileOptions_OptimizeMode_name = map[int32]string{ + 1: "SPEED", + 2: "CODE_SIZE", + 3: "LITE_RUNTIME", +} +var FileOptions_OptimizeMode_value = map[string]int32{ + "SPEED": 1, + "CODE_SIZE": 2, + "LITE_RUNTIME": 3, +} + +func (x FileOptions_OptimizeMode) Enum() *FileOptions_OptimizeMode { + p := new(FileOptions_OptimizeMode) + *p = x + return p +} +func (x FileOptions_OptimizeMode) String() string { + return proto.EnumName(FileOptions_OptimizeMode_name, int32(x)) +} +func (x *FileOptions_OptimizeMode) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(FileOptions_OptimizeMode_value, data, "FileOptions_OptimizeMode") + if err != nil { + return err + } + *x = FileOptions_OptimizeMode(value) + return nil +} +func (FileOptions_OptimizeMode) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{10, 0} } + +type FieldOptions_CType int32 + +const ( + // Default mode. + FieldOptions_STRING FieldOptions_CType = 0 + FieldOptions_CORD FieldOptions_CType = 1 + FieldOptions_STRING_PIECE FieldOptions_CType = 2 +) + +var FieldOptions_CType_name = map[int32]string{ + 0: "STRING", + 1: "CORD", + 2: "STRING_PIECE", +} +var FieldOptions_CType_value = map[string]int32{ + "STRING": 0, + "CORD": 1, + "STRING_PIECE": 2, +} + +func (x FieldOptions_CType) Enum() *FieldOptions_CType { + p := new(FieldOptions_CType) + *p = x + return p +} +func (x FieldOptions_CType) String() string { + return proto.EnumName(FieldOptions_CType_name, int32(x)) +} +func (x *FieldOptions_CType) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(FieldOptions_CType_value, data, "FieldOptions_CType") + if err != nil { + return err + } + *x = FieldOptions_CType(value) + return nil +} +func (FieldOptions_CType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{12, 0} } + +type FieldOptions_JSType int32 + +const ( + // Use the default type. + FieldOptions_JS_NORMAL FieldOptions_JSType = 0 + // Use JavaScript strings. + FieldOptions_JS_STRING FieldOptions_JSType = 1 + // Use JavaScript numbers. + FieldOptions_JS_NUMBER FieldOptions_JSType = 2 +) + +var FieldOptions_JSType_name = map[int32]string{ + 0: "JS_NORMAL", + 1: "JS_STRING", + 2: "JS_NUMBER", +} +var FieldOptions_JSType_value = map[string]int32{ + "JS_NORMAL": 0, + "JS_STRING": 1, + "JS_NUMBER": 2, +} + +func (x FieldOptions_JSType) Enum() *FieldOptions_JSType { + p := new(FieldOptions_JSType) + *p = x + return p +} +func (x FieldOptions_JSType) String() string { + return proto.EnumName(FieldOptions_JSType_name, int32(x)) +} +func (x *FieldOptions_JSType) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(FieldOptions_JSType_value, data, "FieldOptions_JSType") + if err != nil { + return err + } + *x = FieldOptions_JSType(value) + return nil +} +func (FieldOptions_JSType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{12, 1} } + +// Is this method side-effect-free (or safe in HTTP parlance), or idempotent, +// or neither? HTTP based RPC implementation may choose GET verb for safe +// methods, and PUT verb for idempotent methods instead of the default POST. +type MethodOptions_IdempotencyLevel int32 + +const ( + MethodOptions_IDEMPOTENCY_UNKNOWN MethodOptions_IdempotencyLevel = 0 + MethodOptions_NO_SIDE_EFFECTS MethodOptions_IdempotencyLevel = 1 + MethodOptions_IDEMPOTENT MethodOptions_IdempotencyLevel = 2 +) + +var MethodOptions_IdempotencyLevel_name = map[int32]string{ + 0: "IDEMPOTENCY_UNKNOWN", + 1: "NO_SIDE_EFFECTS", + 2: "IDEMPOTENT", +} +var MethodOptions_IdempotencyLevel_value = map[string]int32{ + "IDEMPOTENCY_UNKNOWN": 0, + "NO_SIDE_EFFECTS": 1, + "IDEMPOTENT": 2, +} + +func (x MethodOptions_IdempotencyLevel) Enum() *MethodOptions_IdempotencyLevel { + p := new(MethodOptions_IdempotencyLevel) + *p = x + return p +} +func (x MethodOptions_IdempotencyLevel) String() string { + return proto.EnumName(MethodOptions_IdempotencyLevel_name, int32(x)) +} +func (x *MethodOptions_IdempotencyLevel) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(MethodOptions_IdempotencyLevel_value, data, "MethodOptions_IdempotencyLevel") + if err != nil { + return err + } + *x = MethodOptions_IdempotencyLevel(value) + return nil +} +func (MethodOptions_IdempotencyLevel) EnumDescriptor() ([]byte, []int) { + return fileDescriptor0, []int{17, 0} +} + +// The protocol compiler can output a FileDescriptorSet containing the .proto +// files it parses. +type FileDescriptorSet struct { + File []*FileDescriptorProto `protobuf:"bytes,1,rep,name=file" json:"file,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *FileDescriptorSet) Reset() { *m = FileDescriptorSet{} } +func (m *FileDescriptorSet) String() string { return proto.CompactTextString(m) } +func (*FileDescriptorSet) ProtoMessage() {} +func (*FileDescriptorSet) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } + +func (m *FileDescriptorSet) GetFile() []*FileDescriptorProto { + if m != nil { + return m.File + } + return nil +} + +// Describes a complete .proto file. +type FileDescriptorProto struct { + Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + Package *string `protobuf:"bytes,2,opt,name=package" json:"package,omitempty"` + // Names of files imported by this file. + Dependency []string `protobuf:"bytes,3,rep,name=dependency" json:"dependency,omitempty"` + // Indexes of the public imported files in the dependency list above. + PublicDependency []int32 `protobuf:"varint,10,rep,name=public_dependency,json=publicDependency" json:"public_dependency,omitempty"` + // Indexes of the weak imported files in the dependency list. + // For Google-internal migration only. Do not use. + WeakDependency []int32 `protobuf:"varint,11,rep,name=weak_dependency,json=weakDependency" json:"weak_dependency,omitempty"` + // All top-level definitions in this file. + MessageType []*DescriptorProto `protobuf:"bytes,4,rep,name=message_type,json=messageType" json:"message_type,omitempty"` + EnumType []*EnumDescriptorProto `protobuf:"bytes,5,rep,name=enum_type,json=enumType" json:"enum_type,omitempty"` + Service []*ServiceDescriptorProto `protobuf:"bytes,6,rep,name=service" json:"service,omitempty"` + Extension []*FieldDescriptorProto `protobuf:"bytes,7,rep,name=extension" json:"extension,omitempty"` + Options *FileOptions `protobuf:"bytes,8,opt,name=options" json:"options,omitempty"` + // This field contains optional information about the original source code. + // You may safely remove this entire field without harming runtime + // functionality of the descriptors -- the information is needed only by + // development tools. + SourceCodeInfo *SourceCodeInfo `protobuf:"bytes,9,opt,name=source_code_info,json=sourceCodeInfo" json:"source_code_info,omitempty"` + // The syntax of the proto file. + // The supported values are "proto2" and "proto3". + Syntax *string `protobuf:"bytes,12,opt,name=syntax" json:"syntax,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *FileDescriptorProto) Reset() { *m = FileDescriptorProto{} } +func (m *FileDescriptorProto) String() string { return proto.CompactTextString(m) } +func (*FileDescriptorProto) ProtoMessage() {} +func (*FileDescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } + +func (m *FileDescriptorProto) GetName() string { + if m != nil && m.Name != nil { + return *m.Name + } + return "" +} + +func (m *FileDescriptorProto) GetPackage() string { + if m != nil && m.Package != nil { + return *m.Package + } + return "" +} + +func (m *FileDescriptorProto) GetDependency() []string { + if m != nil { + return m.Dependency + } + return nil +} + +func (m *FileDescriptorProto) GetPublicDependency() []int32 { + if m != nil { + return m.PublicDependency + } + return nil +} + +func (m *FileDescriptorProto) GetWeakDependency() []int32 { + if m != nil { + return m.WeakDependency + } + return nil +} + +func (m *FileDescriptorProto) GetMessageType() []*DescriptorProto { + if m != nil { + return m.MessageType + } + return nil +} + +func (m *FileDescriptorProto) GetEnumType() []*EnumDescriptorProto { + if m != nil { + return m.EnumType + } + return nil +} + +func (m *FileDescriptorProto) GetService() []*ServiceDescriptorProto { + if m != nil { + return m.Service + } + return nil +} + +func (m *FileDescriptorProto) GetExtension() []*FieldDescriptorProto { + if m != nil { + return m.Extension + } + return nil +} + +func (m *FileDescriptorProto) GetOptions() *FileOptions { + if m != nil { + return m.Options + } + return nil +} + +func (m *FileDescriptorProto) GetSourceCodeInfo() *SourceCodeInfo { + if m != nil { + return m.SourceCodeInfo + } + return nil +} + +func (m *FileDescriptorProto) GetSyntax() string { + if m != nil && m.Syntax != nil { + return *m.Syntax + } + return "" +} + +// Describes a message type. +type DescriptorProto struct { + Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + Field []*FieldDescriptorProto `protobuf:"bytes,2,rep,name=field" json:"field,omitempty"` + Extension []*FieldDescriptorProto `protobuf:"bytes,6,rep,name=extension" json:"extension,omitempty"` + NestedType []*DescriptorProto `protobuf:"bytes,3,rep,name=nested_type,json=nestedType" json:"nested_type,omitempty"` + EnumType []*EnumDescriptorProto `protobuf:"bytes,4,rep,name=enum_type,json=enumType" json:"enum_type,omitempty"` + ExtensionRange []*DescriptorProto_ExtensionRange `protobuf:"bytes,5,rep,name=extension_range,json=extensionRange" json:"extension_range,omitempty"` + OneofDecl []*OneofDescriptorProto `protobuf:"bytes,8,rep,name=oneof_decl,json=oneofDecl" json:"oneof_decl,omitempty"` + Options *MessageOptions `protobuf:"bytes,7,opt,name=options" json:"options,omitempty"` + ReservedRange []*DescriptorProto_ReservedRange `protobuf:"bytes,9,rep,name=reserved_range,json=reservedRange" json:"reserved_range,omitempty"` + // Reserved field names, which may not be used by fields in the same message. + // A given name may only be reserved once. + ReservedName []string `protobuf:"bytes,10,rep,name=reserved_name,json=reservedName" json:"reserved_name,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *DescriptorProto) Reset() { *m = DescriptorProto{} } +func (m *DescriptorProto) String() string { return proto.CompactTextString(m) } +func (*DescriptorProto) ProtoMessage() {} +func (*DescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } + +func (m *DescriptorProto) GetName() string { + if m != nil && m.Name != nil { + return *m.Name + } + return "" +} + +func (m *DescriptorProto) GetField() []*FieldDescriptorProto { + if m != nil { + return m.Field + } + return nil +} + +func (m *DescriptorProto) GetExtension() []*FieldDescriptorProto { + if m != nil { + return m.Extension + } + return nil +} + +func (m *DescriptorProto) GetNestedType() []*DescriptorProto { + if m != nil { + return m.NestedType + } + return nil +} + +func (m *DescriptorProto) GetEnumType() []*EnumDescriptorProto { + if m != nil { + return m.EnumType + } + return nil +} + +func (m *DescriptorProto) GetExtensionRange() []*DescriptorProto_ExtensionRange { + if m != nil { + return m.ExtensionRange + } + return nil +} + +func (m *DescriptorProto) GetOneofDecl() []*OneofDescriptorProto { + if m != nil { + return m.OneofDecl + } + return nil +} + +func (m *DescriptorProto) GetOptions() *MessageOptions { + if m != nil { + return m.Options + } + return nil +} + +func (m *DescriptorProto) GetReservedRange() []*DescriptorProto_ReservedRange { + if m != nil { + return m.ReservedRange + } + return nil +} + +func (m *DescriptorProto) GetReservedName() []string { + if m != nil { + return m.ReservedName + } + return nil +} + +type DescriptorProto_ExtensionRange struct { + Start *int32 `protobuf:"varint,1,opt,name=start" json:"start,omitempty"` + End *int32 `protobuf:"varint,2,opt,name=end" json:"end,omitempty"` + Options *ExtensionRangeOptions `protobuf:"bytes,3,opt,name=options" json:"options,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *DescriptorProto_ExtensionRange) Reset() { *m = DescriptorProto_ExtensionRange{} } +func (m *DescriptorProto_ExtensionRange) String() string { return proto.CompactTextString(m) } +func (*DescriptorProto_ExtensionRange) ProtoMessage() {} +func (*DescriptorProto_ExtensionRange) Descriptor() ([]byte, []int) { + return fileDescriptor0, []int{2, 0} +} + +func (m *DescriptorProto_ExtensionRange) GetStart() int32 { + if m != nil && m.Start != nil { + return *m.Start + } + return 0 +} + +func (m *DescriptorProto_ExtensionRange) GetEnd() int32 { + if m != nil && m.End != nil { + return *m.End + } + return 0 +} + +func (m *DescriptorProto_ExtensionRange) GetOptions() *ExtensionRangeOptions { + if m != nil { + return m.Options + } + return nil +} + +// Range of reserved tag numbers. Reserved tag numbers may not be used by +// fields or extension ranges in the same message. Reserved ranges may +// not overlap. +type DescriptorProto_ReservedRange struct { + Start *int32 `protobuf:"varint,1,opt,name=start" json:"start,omitempty"` + End *int32 `protobuf:"varint,2,opt,name=end" json:"end,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *DescriptorProto_ReservedRange) Reset() { *m = DescriptorProto_ReservedRange{} } +func (m *DescriptorProto_ReservedRange) String() string { return proto.CompactTextString(m) } +func (*DescriptorProto_ReservedRange) ProtoMessage() {} +func (*DescriptorProto_ReservedRange) Descriptor() ([]byte, []int) { + return fileDescriptor0, []int{2, 1} +} + +func (m *DescriptorProto_ReservedRange) GetStart() int32 { + if m != nil && m.Start != nil { + return *m.Start + } + return 0 +} + +func (m *DescriptorProto_ReservedRange) GetEnd() int32 { + if m != nil && m.End != nil { + return *m.End + } + return 0 +} + +type ExtensionRangeOptions struct { + // The parser stores options it doesn't recognize here. See above. + UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` + proto.XXX_InternalExtensions `json:"-"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *ExtensionRangeOptions) Reset() { *m = ExtensionRangeOptions{} } +func (m *ExtensionRangeOptions) String() string { return proto.CompactTextString(m) } +func (*ExtensionRangeOptions) ProtoMessage() {} +func (*ExtensionRangeOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } + +var extRange_ExtensionRangeOptions = []proto.ExtensionRange{ + {1000, 536870911}, +} + +func (*ExtensionRangeOptions) ExtensionRangeArray() []proto.ExtensionRange { + return extRange_ExtensionRangeOptions +} + +func (m *ExtensionRangeOptions) GetUninterpretedOption() []*UninterpretedOption { + if m != nil { + return m.UninterpretedOption + } + return nil +} + +// Describes a field within a message. +type FieldDescriptorProto struct { + Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + Number *int32 `protobuf:"varint,3,opt,name=number" json:"number,omitempty"` + Label *FieldDescriptorProto_Label `protobuf:"varint,4,opt,name=label,enum=google.protobuf.FieldDescriptorProto_Label" json:"label,omitempty"` + // If type_name is set, this need not be set. If both this and type_name + // are set, this must be one of TYPE_ENUM, TYPE_MESSAGE or TYPE_GROUP. + Type *FieldDescriptorProto_Type `protobuf:"varint,5,opt,name=type,enum=google.protobuf.FieldDescriptorProto_Type" json:"type,omitempty"` + // For message and enum types, this is the name of the type. If the name + // starts with a '.', it is fully-qualified. Otherwise, C++-like scoping + // rules are used to find the type (i.e. first the nested types within this + // message are searched, then within the parent, on up to the root + // namespace). + TypeName *string `protobuf:"bytes,6,opt,name=type_name,json=typeName" json:"type_name,omitempty"` + // For extensions, this is the name of the type being extended. It is + // resolved in the same manner as type_name. + Extendee *string `protobuf:"bytes,2,opt,name=extendee" json:"extendee,omitempty"` + // For numeric types, contains the original text representation of the value. + // For booleans, "true" or "false". + // For strings, contains the default text contents (not escaped in any way). + // For bytes, contains the C escaped value. All bytes >= 128 are escaped. + // TODO(kenton): Base-64 encode? + DefaultValue *string `protobuf:"bytes,7,opt,name=default_value,json=defaultValue" json:"default_value,omitempty"` + // If set, gives the index of a oneof in the containing type's oneof_decl + // list. This field is a member of that oneof. + OneofIndex *int32 `protobuf:"varint,9,opt,name=oneof_index,json=oneofIndex" json:"oneof_index,omitempty"` + // JSON name of this field. The value is set by protocol compiler. If the + // user has set a "json_name" option on this field, that option's value + // will be used. Otherwise, it's deduced from the field's name by converting + // it to camelCase. + JsonName *string `protobuf:"bytes,10,opt,name=json_name,json=jsonName" json:"json_name,omitempty"` + Options *FieldOptions `protobuf:"bytes,8,opt,name=options" json:"options,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *FieldDescriptorProto) Reset() { *m = FieldDescriptorProto{} } +func (m *FieldDescriptorProto) String() string { return proto.CompactTextString(m) } +func (*FieldDescriptorProto) ProtoMessage() {} +func (*FieldDescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} } + +func (m *FieldDescriptorProto) GetName() string { + if m != nil && m.Name != nil { + return *m.Name + } + return "" +} + +func (m *FieldDescriptorProto) GetNumber() int32 { + if m != nil && m.Number != nil { + return *m.Number + } + return 0 +} + +func (m *FieldDescriptorProto) GetLabel() FieldDescriptorProto_Label { + if m != nil && m.Label != nil { + return *m.Label + } + return FieldDescriptorProto_LABEL_OPTIONAL +} + +func (m *FieldDescriptorProto) GetType() FieldDescriptorProto_Type { + if m != nil && m.Type != nil { + return *m.Type + } + return FieldDescriptorProto_TYPE_DOUBLE +} + +func (m *FieldDescriptorProto) GetTypeName() string { + if m != nil && m.TypeName != nil { + return *m.TypeName + } + return "" +} + +func (m *FieldDescriptorProto) GetExtendee() string { + if m != nil && m.Extendee != nil { + return *m.Extendee + } + return "" +} + +func (m *FieldDescriptorProto) GetDefaultValue() string { + if m != nil && m.DefaultValue != nil { + return *m.DefaultValue + } + return "" +} + +func (m *FieldDescriptorProto) GetOneofIndex() int32 { + if m != nil && m.OneofIndex != nil { + return *m.OneofIndex + } + return 0 +} + +func (m *FieldDescriptorProto) GetJsonName() string { + if m != nil && m.JsonName != nil { + return *m.JsonName + } + return "" +} + +func (m *FieldDescriptorProto) GetOptions() *FieldOptions { + if m != nil { + return m.Options + } + return nil +} + +// Describes a oneof. +type OneofDescriptorProto struct { + Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + Options *OneofOptions `protobuf:"bytes,2,opt,name=options" json:"options,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *OneofDescriptorProto) Reset() { *m = OneofDescriptorProto{} } +func (m *OneofDescriptorProto) String() string { return proto.CompactTextString(m) } +func (*OneofDescriptorProto) ProtoMessage() {} +func (*OneofDescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} } + +func (m *OneofDescriptorProto) GetName() string { + if m != nil && m.Name != nil { + return *m.Name + } + return "" +} + +func (m *OneofDescriptorProto) GetOptions() *OneofOptions { + if m != nil { + return m.Options + } + return nil +} + +// Describes an enum type. +type EnumDescriptorProto struct { + Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + Value []*EnumValueDescriptorProto `protobuf:"bytes,2,rep,name=value" json:"value,omitempty"` + Options *EnumOptions `protobuf:"bytes,3,opt,name=options" json:"options,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *EnumDescriptorProto) Reset() { *m = EnumDescriptorProto{} } +func (m *EnumDescriptorProto) String() string { return proto.CompactTextString(m) } +func (*EnumDescriptorProto) ProtoMessage() {} +func (*EnumDescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} } + +func (m *EnumDescriptorProto) GetName() string { + if m != nil && m.Name != nil { + return *m.Name + } + return "" +} + +func (m *EnumDescriptorProto) GetValue() []*EnumValueDescriptorProto { + if m != nil { + return m.Value + } + return nil +} + +func (m *EnumDescriptorProto) GetOptions() *EnumOptions { + if m != nil { + return m.Options + } + return nil +} + +// Describes a value within an enum. +type EnumValueDescriptorProto struct { + Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + Number *int32 `protobuf:"varint,2,opt,name=number" json:"number,omitempty"` + Options *EnumValueOptions `protobuf:"bytes,3,opt,name=options" json:"options,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *EnumValueDescriptorProto) Reset() { *m = EnumValueDescriptorProto{} } +func (m *EnumValueDescriptorProto) String() string { return proto.CompactTextString(m) } +func (*EnumValueDescriptorProto) ProtoMessage() {} +func (*EnumValueDescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} } + +func (m *EnumValueDescriptorProto) GetName() string { + if m != nil && m.Name != nil { + return *m.Name + } + return "" +} + +func (m *EnumValueDescriptorProto) GetNumber() int32 { + if m != nil && m.Number != nil { + return *m.Number + } + return 0 +} + +func (m *EnumValueDescriptorProto) GetOptions() *EnumValueOptions { + if m != nil { + return m.Options + } + return nil +} + +// Describes a service. +type ServiceDescriptorProto struct { + Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + Method []*MethodDescriptorProto `protobuf:"bytes,2,rep,name=method" json:"method,omitempty"` + Options *ServiceOptions `protobuf:"bytes,3,opt,name=options" json:"options,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *ServiceDescriptorProto) Reset() { *m = ServiceDescriptorProto{} } +func (m *ServiceDescriptorProto) String() string { return proto.CompactTextString(m) } +func (*ServiceDescriptorProto) ProtoMessage() {} +func (*ServiceDescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} } + +func (m *ServiceDescriptorProto) GetName() string { + if m != nil && m.Name != nil { + return *m.Name + } + return "" +} + +func (m *ServiceDescriptorProto) GetMethod() []*MethodDescriptorProto { + if m != nil { + return m.Method + } + return nil +} + +func (m *ServiceDescriptorProto) GetOptions() *ServiceOptions { + if m != nil { + return m.Options + } + return nil +} + +// Describes a method of a service. +type MethodDescriptorProto struct { + Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + // Input and output type names. These are resolved in the same way as + // FieldDescriptorProto.type_name, but must refer to a message type. + InputType *string `protobuf:"bytes,2,opt,name=input_type,json=inputType" json:"input_type,omitempty"` + OutputType *string `protobuf:"bytes,3,opt,name=output_type,json=outputType" json:"output_type,omitempty"` + Options *MethodOptions `protobuf:"bytes,4,opt,name=options" json:"options,omitempty"` + // Identifies if client streams multiple client messages + ClientStreaming *bool `protobuf:"varint,5,opt,name=client_streaming,json=clientStreaming,def=0" json:"client_streaming,omitempty"` + // Identifies if server streams multiple server messages + ServerStreaming *bool `protobuf:"varint,6,opt,name=server_streaming,json=serverStreaming,def=0" json:"server_streaming,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *MethodDescriptorProto) Reset() { *m = MethodDescriptorProto{} } +func (m *MethodDescriptorProto) String() string { return proto.CompactTextString(m) } +func (*MethodDescriptorProto) ProtoMessage() {} +func (*MethodDescriptorProto) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} } + +const Default_MethodDescriptorProto_ClientStreaming bool = false +const Default_MethodDescriptorProto_ServerStreaming bool = false + +func (m *MethodDescriptorProto) GetName() string { + if m != nil && m.Name != nil { + return *m.Name + } + return "" +} + +func (m *MethodDescriptorProto) GetInputType() string { + if m != nil && m.InputType != nil { + return *m.InputType + } + return "" +} + +func (m *MethodDescriptorProto) GetOutputType() string { + if m != nil && m.OutputType != nil { + return *m.OutputType + } + return "" +} + +func (m *MethodDescriptorProto) GetOptions() *MethodOptions { + if m != nil { + return m.Options + } + return nil +} + +func (m *MethodDescriptorProto) GetClientStreaming() bool { + if m != nil && m.ClientStreaming != nil { + return *m.ClientStreaming + } + return Default_MethodDescriptorProto_ClientStreaming +} + +func (m *MethodDescriptorProto) GetServerStreaming() bool { + if m != nil && m.ServerStreaming != nil { + return *m.ServerStreaming + } + return Default_MethodDescriptorProto_ServerStreaming +} + +type FileOptions struct { + // Sets the Java package where classes generated from this .proto will be + // placed. By default, the proto package is used, but this is often + // inappropriate because proto packages do not normally start with backwards + // domain names. + JavaPackage *string `protobuf:"bytes,1,opt,name=java_package,json=javaPackage" json:"java_package,omitempty"` + // If set, all the classes from the .proto file are wrapped in a single + // outer class with the given name. This applies to both Proto1 + // (equivalent to the old "--one_java_file" option) and Proto2 (where + // a .proto always translates to a single class, but you may want to + // explicitly choose the class name). + JavaOuterClassname *string `protobuf:"bytes,8,opt,name=java_outer_classname,json=javaOuterClassname" json:"java_outer_classname,omitempty"` + // If set true, then the Java code generator will generate a separate .java + // file for each top-level message, enum, and service defined in the .proto + // file. Thus, these types will *not* be nested inside the outer class + // named by java_outer_classname. However, the outer class will still be + // generated to contain the file's getDescriptor() method as well as any + // top-level extensions defined in the file. + JavaMultipleFiles *bool `protobuf:"varint,10,opt,name=java_multiple_files,json=javaMultipleFiles,def=0" json:"java_multiple_files,omitempty"` + // This option does nothing. + JavaGenerateEqualsAndHash *bool `protobuf:"varint,20,opt,name=java_generate_equals_and_hash,json=javaGenerateEqualsAndHash" json:"java_generate_equals_and_hash,omitempty"` + // If set true, then the Java2 code generator will generate code that + // throws an exception whenever an attempt is made to assign a non-UTF-8 + // byte sequence to a string field. + // Message reflection will do the same. + // However, an extension field still accepts non-UTF-8 byte sequences. + // This option has no effect on when used with the lite runtime. + JavaStringCheckUtf8 *bool `protobuf:"varint,27,opt,name=java_string_check_utf8,json=javaStringCheckUtf8,def=0" json:"java_string_check_utf8,omitempty"` + OptimizeFor *FileOptions_OptimizeMode `protobuf:"varint,9,opt,name=optimize_for,json=optimizeFor,enum=google.protobuf.FileOptions_OptimizeMode,def=1" json:"optimize_for,omitempty"` + // Sets the Go package where structs generated from this .proto will be + // placed. If omitted, the Go package will be derived from the following: + // - The basename of the package import path, if provided. + // - Otherwise, the package statement in the .proto file, if present. + // - Otherwise, the basename of the .proto file, without extension. + GoPackage *string `protobuf:"bytes,11,opt,name=go_package,json=goPackage" json:"go_package,omitempty"` + // Should generic services be generated in each language? "Generic" services + // are not specific to any particular RPC system. They are generated by the + // main code generators in each language (without additional plugins). + // Generic services were the only kind of service generation supported by + // early versions of google.protobuf. + // + // Generic services are now considered deprecated in favor of using plugins + // that generate code specific to your particular RPC system. Therefore, + // these default to false. Old code which depends on generic services should + // explicitly set them to true. + CcGenericServices *bool `protobuf:"varint,16,opt,name=cc_generic_services,json=ccGenericServices,def=0" json:"cc_generic_services,omitempty"` + JavaGenericServices *bool `protobuf:"varint,17,opt,name=java_generic_services,json=javaGenericServices,def=0" json:"java_generic_services,omitempty"` + PyGenericServices *bool `protobuf:"varint,18,opt,name=py_generic_services,json=pyGenericServices,def=0" json:"py_generic_services,omitempty"` + PhpGenericServices *bool `protobuf:"varint,42,opt,name=php_generic_services,json=phpGenericServices,def=0" json:"php_generic_services,omitempty"` + // Is this file deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for everything in the file, or it will be completely ignored; in the very + // least, this is a formalization for deprecating files. + Deprecated *bool `protobuf:"varint,23,opt,name=deprecated,def=0" json:"deprecated,omitempty"` + // Enables the use of arenas for the proto messages in this file. This applies + // only to generated classes for C++. + CcEnableArenas *bool `protobuf:"varint,31,opt,name=cc_enable_arenas,json=ccEnableArenas,def=0" json:"cc_enable_arenas,omitempty"` + // Sets the objective c class prefix which is prepended to all objective c + // generated classes from this .proto. There is no default. + ObjcClassPrefix *string `protobuf:"bytes,36,opt,name=objc_class_prefix,json=objcClassPrefix" json:"objc_class_prefix,omitempty"` + // Namespace for generated classes; defaults to the package. + CsharpNamespace *string `protobuf:"bytes,37,opt,name=csharp_namespace,json=csharpNamespace" json:"csharp_namespace,omitempty"` + // By default Swift generators will take the proto package and CamelCase it + // replacing '.' with underscore and use that to prefix the types/symbols + // defined. When this options is provided, they will use this value instead + // to prefix the types/symbols defined. + SwiftPrefix *string `protobuf:"bytes,39,opt,name=swift_prefix,json=swiftPrefix" json:"swift_prefix,omitempty"` + // Sets the php class prefix which is prepended to all php generated classes + // from this .proto. Default is empty. + PhpClassPrefix *string `protobuf:"bytes,40,opt,name=php_class_prefix,json=phpClassPrefix" json:"php_class_prefix,omitempty"` + // Use this option to change the namespace of php generated classes. Default + // is empty. When this option is empty, the package name will be used for + // determining the namespace. + PhpNamespace *string `protobuf:"bytes,41,opt,name=php_namespace,json=phpNamespace" json:"php_namespace,omitempty"` + // The parser stores options it doesn't recognize here. See above. + UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` + proto.XXX_InternalExtensions `json:"-"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *FileOptions) Reset() { *m = FileOptions{} } +func (m *FileOptions) String() string { return proto.CompactTextString(m) } +func (*FileOptions) ProtoMessage() {} +func (*FileOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} } + +var extRange_FileOptions = []proto.ExtensionRange{ + {1000, 536870911}, +} + +func (*FileOptions) ExtensionRangeArray() []proto.ExtensionRange { + return extRange_FileOptions +} + +const Default_FileOptions_JavaMultipleFiles bool = false +const Default_FileOptions_JavaStringCheckUtf8 bool = false +const Default_FileOptions_OptimizeFor FileOptions_OptimizeMode = FileOptions_SPEED +const Default_FileOptions_CcGenericServices bool = false +const Default_FileOptions_JavaGenericServices bool = false +const Default_FileOptions_PyGenericServices bool = false +const Default_FileOptions_PhpGenericServices bool = false +const Default_FileOptions_Deprecated bool = false +const Default_FileOptions_CcEnableArenas bool = false + +func (m *FileOptions) GetJavaPackage() string { + if m != nil && m.JavaPackage != nil { + return *m.JavaPackage + } + return "" +} + +func (m *FileOptions) GetJavaOuterClassname() string { + if m != nil && m.JavaOuterClassname != nil { + return *m.JavaOuterClassname + } + return "" +} + +func (m *FileOptions) GetJavaMultipleFiles() bool { + if m != nil && m.JavaMultipleFiles != nil { + return *m.JavaMultipleFiles + } + return Default_FileOptions_JavaMultipleFiles +} + +func (m *FileOptions) GetJavaGenerateEqualsAndHash() bool { + if m != nil && m.JavaGenerateEqualsAndHash != nil { + return *m.JavaGenerateEqualsAndHash + } + return false +} + +func (m *FileOptions) GetJavaStringCheckUtf8() bool { + if m != nil && m.JavaStringCheckUtf8 != nil { + return *m.JavaStringCheckUtf8 + } + return Default_FileOptions_JavaStringCheckUtf8 +} + +func (m *FileOptions) GetOptimizeFor() FileOptions_OptimizeMode { + if m != nil && m.OptimizeFor != nil { + return *m.OptimizeFor + } + return Default_FileOptions_OptimizeFor +} + +func (m *FileOptions) GetGoPackage() string { + if m != nil && m.GoPackage != nil { + return *m.GoPackage + } + return "" +} + +func (m *FileOptions) GetCcGenericServices() bool { + if m != nil && m.CcGenericServices != nil { + return *m.CcGenericServices + } + return Default_FileOptions_CcGenericServices +} + +func (m *FileOptions) GetJavaGenericServices() bool { + if m != nil && m.JavaGenericServices != nil { + return *m.JavaGenericServices + } + return Default_FileOptions_JavaGenericServices +} + +func (m *FileOptions) GetPyGenericServices() bool { + if m != nil && m.PyGenericServices != nil { + return *m.PyGenericServices + } + return Default_FileOptions_PyGenericServices +} + +func (m *FileOptions) GetPhpGenericServices() bool { + if m != nil && m.PhpGenericServices != nil { + return *m.PhpGenericServices + } + return Default_FileOptions_PhpGenericServices +} + +func (m *FileOptions) GetDeprecated() bool { + if m != nil && m.Deprecated != nil { + return *m.Deprecated + } + return Default_FileOptions_Deprecated +} + +func (m *FileOptions) GetCcEnableArenas() bool { + if m != nil && m.CcEnableArenas != nil { + return *m.CcEnableArenas + } + return Default_FileOptions_CcEnableArenas +} + +func (m *FileOptions) GetObjcClassPrefix() string { + if m != nil && m.ObjcClassPrefix != nil { + return *m.ObjcClassPrefix + } + return "" +} + +func (m *FileOptions) GetCsharpNamespace() string { + if m != nil && m.CsharpNamespace != nil { + return *m.CsharpNamespace + } + return "" +} + +func (m *FileOptions) GetSwiftPrefix() string { + if m != nil && m.SwiftPrefix != nil { + return *m.SwiftPrefix + } + return "" +} + +func (m *FileOptions) GetPhpClassPrefix() string { + if m != nil && m.PhpClassPrefix != nil { + return *m.PhpClassPrefix + } + return "" +} + +func (m *FileOptions) GetPhpNamespace() string { + if m != nil && m.PhpNamespace != nil { + return *m.PhpNamespace + } + return "" +} + +func (m *FileOptions) GetUninterpretedOption() []*UninterpretedOption { + if m != nil { + return m.UninterpretedOption + } + return nil +} + +type MessageOptions struct { + // Set true to use the old proto1 MessageSet wire format for extensions. + // This is provided for backwards-compatibility with the MessageSet wire + // format. You should not use this for any other reason: It's less + // efficient, has fewer features, and is more complicated. + // + // The message must be defined exactly as follows: + // message Foo { + // option message_set_wire_format = true; + // extensions 4 to max; + // } + // Note that the message cannot have any defined fields; MessageSets only + // have extensions. + // + // All extensions of your type must be singular messages; e.g. they cannot + // be int32s, enums, or repeated messages. + // + // Because this is an option, the above two restrictions are not enforced by + // the protocol compiler. + MessageSetWireFormat *bool `protobuf:"varint,1,opt,name=message_set_wire_format,json=messageSetWireFormat,def=0" json:"message_set_wire_format,omitempty"` + // Disables the generation of the standard "descriptor()" accessor, which can + // conflict with a field of the same name. This is meant to make migration + // from proto1 easier; new code should avoid fields named "descriptor". + NoStandardDescriptorAccessor *bool `protobuf:"varint,2,opt,name=no_standard_descriptor_accessor,json=noStandardDescriptorAccessor,def=0" json:"no_standard_descriptor_accessor,omitempty"` + // Is this message deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for the message, or it will be completely ignored; in the very least, + // this is a formalization for deprecating messages. + Deprecated *bool `protobuf:"varint,3,opt,name=deprecated,def=0" json:"deprecated,omitempty"` + // Whether the message is an automatically generated map entry type for the + // maps field. + // + // For maps fields: + // map map_field = 1; + // The parsed descriptor looks like: + // message MapFieldEntry { + // option map_entry = true; + // optional KeyType key = 1; + // optional ValueType value = 2; + // } + // repeated MapFieldEntry map_field = 1; + // + // Implementations may choose not to generate the map_entry=true message, but + // use a native map in the target language to hold the keys and values. + // The reflection APIs in such implementions still need to work as + // if the field is a repeated message field. + // + // NOTE: Do not set the option in .proto files. Always use the maps syntax + // instead. The option should only be implicitly set by the proto compiler + // parser. + MapEntry *bool `protobuf:"varint,7,opt,name=map_entry,json=mapEntry" json:"map_entry,omitempty"` + // The parser stores options it doesn't recognize here. See above. + UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` + proto.XXX_InternalExtensions `json:"-"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *MessageOptions) Reset() { *m = MessageOptions{} } +func (m *MessageOptions) String() string { return proto.CompactTextString(m) } +func (*MessageOptions) ProtoMessage() {} +func (*MessageOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} } + +var extRange_MessageOptions = []proto.ExtensionRange{ + {1000, 536870911}, +} + +func (*MessageOptions) ExtensionRangeArray() []proto.ExtensionRange { + return extRange_MessageOptions +} + +const Default_MessageOptions_MessageSetWireFormat bool = false +const Default_MessageOptions_NoStandardDescriptorAccessor bool = false +const Default_MessageOptions_Deprecated bool = false + +func (m *MessageOptions) GetMessageSetWireFormat() bool { + if m != nil && m.MessageSetWireFormat != nil { + return *m.MessageSetWireFormat + } + return Default_MessageOptions_MessageSetWireFormat +} + +func (m *MessageOptions) GetNoStandardDescriptorAccessor() bool { + if m != nil && m.NoStandardDescriptorAccessor != nil { + return *m.NoStandardDescriptorAccessor + } + return Default_MessageOptions_NoStandardDescriptorAccessor +} + +func (m *MessageOptions) GetDeprecated() bool { + if m != nil && m.Deprecated != nil { + return *m.Deprecated + } + return Default_MessageOptions_Deprecated +} + +func (m *MessageOptions) GetMapEntry() bool { + if m != nil && m.MapEntry != nil { + return *m.MapEntry + } + return false +} + +func (m *MessageOptions) GetUninterpretedOption() []*UninterpretedOption { + if m != nil { + return m.UninterpretedOption + } + return nil +} + +type FieldOptions struct { + // The ctype option instructs the C++ code generator to use a different + // representation of the field than it normally would. See the specific + // options below. This option is not yet implemented in the open source + // release -- sorry, we'll try to include it in a future version! + Ctype *FieldOptions_CType `protobuf:"varint,1,opt,name=ctype,enum=google.protobuf.FieldOptions_CType,def=0" json:"ctype,omitempty"` + // The packed option can be enabled for repeated primitive fields to enable + // a more efficient representation on the wire. Rather than repeatedly + // writing the tag and type for each element, the entire array is encoded as + // a single length-delimited blob. In proto3, only explicit setting it to + // false will avoid using packed encoding. + Packed *bool `protobuf:"varint,2,opt,name=packed" json:"packed,omitempty"` + // The jstype option determines the JavaScript type used for values of the + // field. The option is permitted only for 64 bit integral and fixed types + // (int64, uint64, sint64, fixed64, sfixed64). A field with jstype JS_STRING + // is represented as JavaScript string, which avoids loss of precision that + // can happen when a large value is converted to a floating point JavaScript. + // Specifying JS_NUMBER for the jstype causes the generated JavaScript code to + // use the JavaScript "number" type. The behavior of the default option + // JS_NORMAL is implementation dependent. + // + // This option is an enum to permit additional types to be added, e.g. + // goog.math.Integer. + Jstype *FieldOptions_JSType `protobuf:"varint,6,opt,name=jstype,enum=google.protobuf.FieldOptions_JSType,def=0" json:"jstype,omitempty"` + // Should this field be parsed lazily? Lazy applies only to message-type + // fields. It means that when the outer message is initially parsed, the + // inner message's contents will not be parsed but instead stored in encoded + // form. The inner message will actually be parsed when it is first accessed. + // + // This is only a hint. Implementations are free to choose whether to use + // eager or lazy parsing regardless of the value of this option. However, + // setting this option true suggests that the protocol author believes that + // using lazy parsing on this field is worth the additional bookkeeping + // overhead typically needed to implement it. + // + // This option does not affect the public interface of any generated code; + // all method signatures remain the same. Furthermore, thread-safety of the + // interface is not affected by this option; const methods remain safe to + // call from multiple threads concurrently, while non-const methods continue + // to require exclusive access. + // + // + // Note that implementations may choose not to check required fields within + // a lazy sub-message. That is, calling IsInitialized() on the outer message + // may return true even if the inner message has missing required fields. + // This is necessary because otherwise the inner message would have to be + // parsed in order to perform the check, defeating the purpose of lazy + // parsing. An implementation which chooses not to check required fields + // must be consistent about it. That is, for any particular sub-message, the + // implementation must either *always* check its required fields, or *never* + // check its required fields, regardless of whether or not the message has + // been parsed. + Lazy *bool `protobuf:"varint,5,opt,name=lazy,def=0" json:"lazy,omitempty"` + // Is this field deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for accessors, or it will be completely ignored; in the very least, this + // is a formalization for deprecating fields. + Deprecated *bool `protobuf:"varint,3,opt,name=deprecated,def=0" json:"deprecated,omitempty"` + // For Google-internal migration only. Do not use. + Weak *bool `protobuf:"varint,10,opt,name=weak,def=0" json:"weak,omitempty"` + // The parser stores options it doesn't recognize here. See above. + UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` + proto.XXX_InternalExtensions `json:"-"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *FieldOptions) Reset() { *m = FieldOptions{} } +func (m *FieldOptions) String() string { return proto.CompactTextString(m) } +func (*FieldOptions) ProtoMessage() {} +func (*FieldOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{12} } + +var extRange_FieldOptions = []proto.ExtensionRange{ + {1000, 536870911}, +} + +func (*FieldOptions) ExtensionRangeArray() []proto.ExtensionRange { + return extRange_FieldOptions +} + +const Default_FieldOptions_Ctype FieldOptions_CType = FieldOptions_STRING +const Default_FieldOptions_Jstype FieldOptions_JSType = FieldOptions_JS_NORMAL +const Default_FieldOptions_Lazy bool = false +const Default_FieldOptions_Deprecated bool = false +const Default_FieldOptions_Weak bool = false + +func (m *FieldOptions) GetCtype() FieldOptions_CType { + if m != nil && m.Ctype != nil { + return *m.Ctype + } + return Default_FieldOptions_Ctype +} + +func (m *FieldOptions) GetPacked() bool { + if m != nil && m.Packed != nil { + return *m.Packed + } + return false +} + +func (m *FieldOptions) GetJstype() FieldOptions_JSType { + if m != nil && m.Jstype != nil { + return *m.Jstype + } + return Default_FieldOptions_Jstype +} + +func (m *FieldOptions) GetLazy() bool { + if m != nil && m.Lazy != nil { + return *m.Lazy + } + return Default_FieldOptions_Lazy +} + +func (m *FieldOptions) GetDeprecated() bool { + if m != nil && m.Deprecated != nil { + return *m.Deprecated + } + return Default_FieldOptions_Deprecated +} + +func (m *FieldOptions) GetWeak() bool { + if m != nil && m.Weak != nil { + return *m.Weak + } + return Default_FieldOptions_Weak +} + +func (m *FieldOptions) GetUninterpretedOption() []*UninterpretedOption { + if m != nil { + return m.UninterpretedOption + } + return nil +} + +type OneofOptions struct { + // The parser stores options it doesn't recognize here. See above. + UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` + proto.XXX_InternalExtensions `json:"-"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *OneofOptions) Reset() { *m = OneofOptions{} } +func (m *OneofOptions) String() string { return proto.CompactTextString(m) } +func (*OneofOptions) ProtoMessage() {} +func (*OneofOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{13} } + +var extRange_OneofOptions = []proto.ExtensionRange{ + {1000, 536870911}, +} + +func (*OneofOptions) ExtensionRangeArray() []proto.ExtensionRange { + return extRange_OneofOptions +} + +func (m *OneofOptions) GetUninterpretedOption() []*UninterpretedOption { + if m != nil { + return m.UninterpretedOption + } + return nil +} + +type EnumOptions struct { + // Set this option to true to allow mapping different tag names to the same + // value. + AllowAlias *bool `protobuf:"varint,2,opt,name=allow_alias,json=allowAlias" json:"allow_alias,omitempty"` + // Is this enum deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for the enum, or it will be completely ignored; in the very least, this + // is a formalization for deprecating enums. + Deprecated *bool `protobuf:"varint,3,opt,name=deprecated,def=0" json:"deprecated,omitempty"` + // The parser stores options it doesn't recognize here. See above. + UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` + proto.XXX_InternalExtensions `json:"-"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *EnumOptions) Reset() { *m = EnumOptions{} } +func (m *EnumOptions) String() string { return proto.CompactTextString(m) } +func (*EnumOptions) ProtoMessage() {} +func (*EnumOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{14} } + +var extRange_EnumOptions = []proto.ExtensionRange{ + {1000, 536870911}, +} + +func (*EnumOptions) ExtensionRangeArray() []proto.ExtensionRange { + return extRange_EnumOptions +} + +const Default_EnumOptions_Deprecated bool = false + +func (m *EnumOptions) GetAllowAlias() bool { + if m != nil && m.AllowAlias != nil { + return *m.AllowAlias + } + return false +} + +func (m *EnumOptions) GetDeprecated() bool { + if m != nil && m.Deprecated != nil { + return *m.Deprecated + } + return Default_EnumOptions_Deprecated +} + +func (m *EnumOptions) GetUninterpretedOption() []*UninterpretedOption { + if m != nil { + return m.UninterpretedOption + } + return nil +} + +type EnumValueOptions struct { + // Is this enum value deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for the enum value, or it will be completely ignored; in the very least, + // this is a formalization for deprecating enum values. + Deprecated *bool `protobuf:"varint,1,opt,name=deprecated,def=0" json:"deprecated,omitempty"` + // The parser stores options it doesn't recognize here. See above. + UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` + proto.XXX_InternalExtensions `json:"-"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *EnumValueOptions) Reset() { *m = EnumValueOptions{} } +func (m *EnumValueOptions) String() string { return proto.CompactTextString(m) } +func (*EnumValueOptions) ProtoMessage() {} +func (*EnumValueOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{15} } + +var extRange_EnumValueOptions = []proto.ExtensionRange{ + {1000, 536870911}, +} + +func (*EnumValueOptions) ExtensionRangeArray() []proto.ExtensionRange { + return extRange_EnumValueOptions +} + +const Default_EnumValueOptions_Deprecated bool = false + +func (m *EnumValueOptions) GetDeprecated() bool { + if m != nil && m.Deprecated != nil { + return *m.Deprecated + } + return Default_EnumValueOptions_Deprecated +} + +func (m *EnumValueOptions) GetUninterpretedOption() []*UninterpretedOption { + if m != nil { + return m.UninterpretedOption + } + return nil +} + +type ServiceOptions struct { + // Is this service deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for the service, or it will be completely ignored; in the very least, + // this is a formalization for deprecating services. + Deprecated *bool `protobuf:"varint,33,opt,name=deprecated,def=0" json:"deprecated,omitempty"` + // The parser stores options it doesn't recognize here. See above. + UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` + proto.XXX_InternalExtensions `json:"-"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *ServiceOptions) Reset() { *m = ServiceOptions{} } +func (m *ServiceOptions) String() string { return proto.CompactTextString(m) } +func (*ServiceOptions) ProtoMessage() {} +func (*ServiceOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{16} } + +var extRange_ServiceOptions = []proto.ExtensionRange{ + {1000, 536870911}, +} + +func (*ServiceOptions) ExtensionRangeArray() []proto.ExtensionRange { + return extRange_ServiceOptions +} + +const Default_ServiceOptions_Deprecated bool = false + +func (m *ServiceOptions) GetDeprecated() bool { + if m != nil && m.Deprecated != nil { + return *m.Deprecated + } + return Default_ServiceOptions_Deprecated +} + +func (m *ServiceOptions) GetUninterpretedOption() []*UninterpretedOption { + if m != nil { + return m.UninterpretedOption + } + return nil +} + +type MethodOptions struct { + // Is this method deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for the method, or it will be completely ignored; in the very least, + // this is a formalization for deprecating methods. + Deprecated *bool `protobuf:"varint,33,opt,name=deprecated,def=0" json:"deprecated,omitempty"` + IdempotencyLevel *MethodOptions_IdempotencyLevel `protobuf:"varint,34,opt,name=idempotency_level,json=idempotencyLevel,enum=google.protobuf.MethodOptions_IdempotencyLevel,def=0" json:"idempotency_level,omitempty"` + // The parser stores options it doesn't recognize here. See above. + UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` + proto.XXX_InternalExtensions `json:"-"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *MethodOptions) Reset() { *m = MethodOptions{} } +func (m *MethodOptions) String() string { return proto.CompactTextString(m) } +func (*MethodOptions) ProtoMessage() {} +func (*MethodOptions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{17} } + +var extRange_MethodOptions = []proto.ExtensionRange{ + {1000, 536870911}, +} + +func (*MethodOptions) ExtensionRangeArray() []proto.ExtensionRange { + return extRange_MethodOptions +} + +const Default_MethodOptions_Deprecated bool = false +const Default_MethodOptions_IdempotencyLevel MethodOptions_IdempotencyLevel = MethodOptions_IDEMPOTENCY_UNKNOWN + +func (m *MethodOptions) GetDeprecated() bool { + if m != nil && m.Deprecated != nil { + return *m.Deprecated + } + return Default_MethodOptions_Deprecated +} + +func (m *MethodOptions) GetIdempotencyLevel() MethodOptions_IdempotencyLevel { + if m != nil && m.IdempotencyLevel != nil { + return *m.IdempotencyLevel + } + return Default_MethodOptions_IdempotencyLevel +} + +func (m *MethodOptions) GetUninterpretedOption() []*UninterpretedOption { + if m != nil { + return m.UninterpretedOption + } + return nil +} + +// A message representing a option the parser does not recognize. This only +// appears in options protos created by the compiler::Parser class. +// DescriptorPool resolves these when building Descriptor objects. Therefore, +// options protos in descriptor objects (e.g. returned by Descriptor::options(), +// or produced by Descriptor::CopyTo()) will never have UninterpretedOptions +// in them. +type UninterpretedOption struct { + Name []*UninterpretedOption_NamePart `protobuf:"bytes,2,rep,name=name" json:"name,omitempty"` + // The value of the uninterpreted option, in whatever type the tokenizer + // identified it as during parsing. Exactly one of these should be set. + IdentifierValue *string `protobuf:"bytes,3,opt,name=identifier_value,json=identifierValue" json:"identifier_value,omitempty"` + PositiveIntValue *uint64 `protobuf:"varint,4,opt,name=positive_int_value,json=positiveIntValue" json:"positive_int_value,omitempty"` + NegativeIntValue *int64 `protobuf:"varint,5,opt,name=negative_int_value,json=negativeIntValue" json:"negative_int_value,omitempty"` + DoubleValue *float64 `protobuf:"fixed64,6,opt,name=double_value,json=doubleValue" json:"double_value,omitempty"` + StringValue []byte `protobuf:"bytes,7,opt,name=string_value,json=stringValue" json:"string_value,omitempty"` + AggregateValue *string `protobuf:"bytes,8,opt,name=aggregate_value,json=aggregateValue" json:"aggregate_value,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *UninterpretedOption) Reset() { *m = UninterpretedOption{} } +func (m *UninterpretedOption) String() string { return proto.CompactTextString(m) } +func (*UninterpretedOption) ProtoMessage() {} +func (*UninterpretedOption) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{18} } + +func (m *UninterpretedOption) GetName() []*UninterpretedOption_NamePart { + if m != nil { + return m.Name + } + return nil +} + +func (m *UninterpretedOption) GetIdentifierValue() string { + if m != nil && m.IdentifierValue != nil { + return *m.IdentifierValue + } + return "" +} + +func (m *UninterpretedOption) GetPositiveIntValue() uint64 { + if m != nil && m.PositiveIntValue != nil { + return *m.PositiveIntValue + } + return 0 +} + +func (m *UninterpretedOption) GetNegativeIntValue() int64 { + if m != nil && m.NegativeIntValue != nil { + return *m.NegativeIntValue + } + return 0 +} + +func (m *UninterpretedOption) GetDoubleValue() float64 { + if m != nil && m.DoubleValue != nil { + return *m.DoubleValue + } + return 0 +} + +func (m *UninterpretedOption) GetStringValue() []byte { + if m != nil { + return m.StringValue + } + return nil +} + +func (m *UninterpretedOption) GetAggregateValue() string { + if m != nil && m.AggregateValue != nil { + return *m.AggregateValue + } + return "" +} + +// The name of the uninterpreted option. Each string represents a segment in +// a dot-separated name. is_extension is true iff a segment represents an +// extension (denoted with parentheses in options specs in .proto files). +// E.g.,{ ["foo", false], ["bar.baz", true], ["qux", false] } represents +// "foo.(bar.baz).qux". +type UninterpretedOption_NamePart struct { + NamePart *string `protobuf:"bytes,1,req,name=name_part,json=namePart" json:"name_part,omitempty"` + IsExtension *bool `protobuf:"varint,2,req,name=is_extension,json=isExtension" json:"is_extension,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *UninterpretedOption_NamePart) Reset() { *m = UninterpretedOption_NamePart{} } +func (m *UninterpretedOption_NamePart) String() string { return proto.CompactTextString(m) } +func (*UninterpretedOption_NamePart) ProtoMessage() {} +func (*UninterpretedOption_NamePart) Descriptor() ([]byte, []int) { + return fileDescriptor0, []int{18, 0} +} + +func (m *UninterpretedOption_NamePart) GetNamePart() string { + if m != nil && m.NamePart != nil { + return *m.NamePart + } + return "" +} + +func (m *UninterpretedOption_NamePart) GetIsExtension() bool { + if m != nil && m.IsExtension != nil { + return *m.IsExtension + } + return false +} + +// Encapsulates information about the original source file from which a +// FileDescriptorProto was generated. +type SourceCodeInfo struct { + // A Location identifies a piece of source code in a .proto file which + // corresponds to a particular definition. This information is intended + // to be useful to IDEs, code indexers, documentation generators, and similar + // tools. + // + // For example, say we have a file like: + // message Foo { + // optional string foo = 1; + // } + // Let's look at just the field definition: + // optional string foo = 1; + // ^ ^^ ^^ ^ ^^^ + // a bc de f ghi + // We have the following locations: + // span path represents + // [a,i) [ 4, 0, 2, 0 ] The whole field definition. + // [a,b) [ 4, 0, 2, 0, 4 ] The label (optional). + // [c,d) [ 4, 0, 2, 0, 5 ] The type (string). + // [e,f) [ 4, 0, 2, 0, 1 ] The name (foo). + // [g,h) [ 4, 0, 2, 0, 3 ] The number (1). + // + // Notes: + // - A location may refer to a repeated field itself (i.e. not to any + // particular index within it). This is used whenever a set of elements are + // logically enclosed in a single code segment. For example, an entire + // extend block (possibly containing multiple extension definitions) will + // have an outer location whose path refers to the "extensions" repeated + // field without an index. + // - Multiple locations may have the same path. This happens when a single + // logical declaration is spread out across multiple places. The most + // obvious example is the "extend" block again -- there may be multiple + // extend blocks in the same scope, each of which will have the same path. + // - A location's span is not always a subset of its parent's span. For + // example, the "extendee" of an extension declaration appears at the + // beginning of the "extend" block and is shared by all extensions within + // the block. + // - Just because a location's span is a subset of some other location's span + // does not mean that it is a descendent. For example, a "group" defines + // both a type and a field in a single declaration. Thus, the locations + // corresponding to the type and field and their components will overlap. + // - Code which tries to interpret locations should probably be designed to + // ignore those that it doesn't understand, as more types of locations could + // be recorded in the future. + Location []*SourceCodeInfo_Location `protobuf:"bytes,1,rep,name=location" json:"location,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *SourceCodeInfo) Reset() { *m = SourceCodeInfo{} } +func (m *SourceCodeInfo) String() string { return proto.CompactTextString(m) } +func (*SourceCodeInfo) ProtoMessage() {} +func (*SourceCodeInfo) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{19} } + +func (m *SourceCodeInfo) GetLocation() []*SourceCodeInfo_Location { + if m != nil { + return m.Location + } + return nil +} + +type SourceCodeInfo_Location struct { + // Identifies which part of the FileDescriptorProto was defined at this + // location. + // + // Each element is a field number or an index. They form a path from + // the root FileDescriptorProto to the place where the definition. For + // example, this path: + // [ 4, 3, 2, 7, 1 ] + // refers to: + // file.message_type(3) // 4, 3 + // .field(7) // 2, 7 + // .name() // 1 + // This is because FileDescriptorProto.message_type has field number 4: + // repeated DescriptorProto message_type = 4; + // and DescriptorProto.field has field number 2: + // repeated FieldDescriptorProto field = 2; + // and FieldDescriptorProto.name has field number 1: + // optional string name = 1; + // + // Thus, the above path gives the location of a field name. If we removed + // the last element: + // [ 4, 3, 2, 7 ] + // this path refers to the whole field declaration (from the beginning + // of the label to the terminating semicolon). + Path []int32 `protobuf:"varint,1,rep,packed,name=path" json:"path,omitempty"` + // Always has exactly three or four elements: start line, start column, + // end line (optional, otherwise assumed same as start line), end column. + // These are packed into a single field for efficiency. Note that line + // and column numbers are zero-based -- typically you will want to add + // 1 to each before displaying to a user. + Span []int32 `protobuf:"varint,2,rep,packed,name=span" json:"span,omitempty"` + // If this SourceCodeInfo represents a complete declaration, these are any + // comments appearing before and after the declaration which appear to be + // attached to the declaration. + // + // A series of line comments appearing on consecutive lines, with no other + // tokens appearing on those lines, will be treated as a single comment. + // + // leading_detached_comments will keep paragraphs of comments that appear + // before (but not connected to) the current element. Each paragraph, + // separated by empty lines, will be one comment element in the repeated + // field. + // + // Only the comment content is provided; comment markers (e.g. //) are + // stripped out. For block comments, leading whitespace and an asterisk + // will be stripped from the beginning of each line other than the first. + // Newlines are included in the output. + // + // Examples: + // + // optional int32 foo = 1; // Comment attached to foo. + // // Comment attached to bar. + // optional int32 bar = 2; + // + // optional string baz = 3; + // // Comment attached to baz. + // // Another line attached to baz. + // + // // Comment attached to qux. + // // + // // Another line attached to qux. + // optional double qux = 4; + // + // // Detached comment for corge. This is not leading or trailing comments + // // to qux or corge because there are blank lines separating it from + // // both. + // + // // Detached comment for corge paragraph 2. + // + // optional string corge = 5; + // /* Block comment attached + // * to corge. Leading asterisks + // * will be removed. */ + // /* Block comment attached to + // * grault. */ + // optional int32 grault = 6; + // + // // ignored detached comments. + LeadingComments *string `protobuf:"bytes,3,opt,name=leading_comments,json=leadingComments" json:"leading_comments,omitempty"` + TrailingComments *string `protobuf:"bytes,4,opt,name=trailing_comments,json=trailingComments" json:"trailing_comments,omitempty"` + LeadingDetachedComments []string `protobuf:"bytes,6,rep,name=leading_detached_comments,json=leadingDetachedComments" json:"leading_detached_comments,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *SourceCodeInfo_Location) Reset() { *m = SourceCodeInfo_Location{} } +func (m *SourceCodeInfo_Location) String() string { return proto.CompactTextString(m) } +func (*SourceCodeInfo_Location) ProtoMessage() {} +func (*SourceCodeInfo_Location) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{19, 0} } + +func (m *SourceCodeInfo_Location) GetPath() []int32 { + if m != nil { + return m.Path + } + return nil +} + +func (m *SourceCodeInfo_Location) GetSpan() []int32 { + if m != nil { + return m.Span + } + return nil +} + +func (m *SourceCodeInfo_Location) GetLeadingComments() string { + if m != nil && m.LeadingComments != nil { + return *m.LeadingComments + } + return "" +} + +func (m *SourceCodeInfo_Location) GetTrailingComments() string { + if m != nil && m.TrailingComments != nil { + return *m.TrailingComments + } + return "" +} + +func (m *SourceCodeInfo_Location) GetLeadingDetachedComments() []string { + if m != nil { + return m.LeadingDetachedComments + } + return nil +} + +// Describes the relationship between generated code and its original source +// file. A GeneratedCodeInfo message is associated with only one generated +// source file, but may contain references to different source .proto files. +type GeneratedCodeInfo struct { + // An Annotation connects some span of text in generated code to an element + // of its generating .proto file. + Annotation []*GeneratedCodeInfo_Annotation `protobuf:"bytes,1,rep,name=annotation" json:"annotation,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *GeneratedCodeInfo) Reset() { *m = GeneratedCodeInfo{} } +func (m *GeneratedCodeInfo) String() string { return proto.CompactTextString(m) } +func (*GeneratedCodeInfo) ProtoMessage() {} +func (*GeneratedCodeInfo) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{20} } + +func (m *GeneratedCodeInfo) GetAnnotation() []*GeneratedCodeInfo_Annotation { + if m != nil { + return m.Annotation + } + return nil +} + +type GeneratedCodeInfo_Annotation struct { + // Identifies the element in the original source .proto file. This field + // is formatted the same as SourceCodeInfo.Location.path. + Path []int32 `protobuf:"varint,1,rep,packed,name=path" json:"path,omitempty"` + // Identifies the filesystem path to the original source .proto. + SourceFile *string `protobuf:"bytes,2,opt,name=source_file,json=sourceFile" json:"source_file,omitempty"` + // Identifies the starting offset in bytes in the generated code + // that relates to the identified object. + Begin *int32 `protobuf:"varint,3,opt,name=begin" json:"begin,omitempty"` + // Identifies the ending offset in bytes in the generated code that + // relates to the identified offset. The end offset should be one past + // the last relevant byte (so the length of the text = end - begin). + End *int32 `protobuf:"varint,4,opt,name=end" json:"end,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *GeneratedCodeInfo_Annotation) Reset() { *m = GeneratedCodeInfo_Annotation{} } +func (m *GeneratedCodeInfo_Annotation) String() string { return proto.CompactTextString(m) } +func (*GeneratedCodeInfo_Annotation) ProtoMessage() {} +func (*GeneratedCodeInfo_Annotation) Descriptor() ([]byte, []int) { + return fileDescriptor0, []int{20, 0} +} + +func (m *GeneratedCodeInfo_Annotation) GetPath() []int32 { + if m != nil { + return m.Path + } + return nil +} + +func (m *GeneratedCodeInfo_Annotation) GetSourceFile() string { + if m != nil && m.SourceFile != nil { + return *m.SourceFile + } + return "" +} + +func (m *GeneratedCodeInfo_Annotation) GetBegin() int32 { + if m != nil && m.Begin != nil { + return *m.Begin + } + return 0 +} + +func (m *GeneratedCodeInfo_Annotation) GetEnd() int32 { + if m != nil && m.End != nil { + return *m.End + } + return 0 +} + +func init() { + proto.RegisterType((*FileDescriptorSet)(nil), "google.protobuf.FileDescriptorSet") + proto.RegisterType((*FileDescriptorProto)(nil), "google.protobuf.FileDescriptorProto") + proto.RegisterType((*DescriptorProto)(nil), "google.protobuf.DescriptorProto") + proto.RegisterType((*DescriptorProto_ExtensionRange)(nil), "google.protobuf.DescriptorProto.ExtensionRange") + proto.RegisterType((*DescriptorProto_ReservedRange)(nil), "google.protobuf.DescriptorProto.ReservedRange") + proto.RegisterType((*ExtensionRangeOptions)(nil), "google.protobuf.ExtensionRangeOptions") + proto.RegisterType((*FieldDescriptorProto)(nil), "google.protobuf.FieldDescriptorProto") + proto.RegisterType((*OneofDescriptorProto)(nil), "google.protobuf.OneofDescriptorProto") + proto.RegisterType((*EnumDescriptorProto)(nil), "google.protobuf.EnumDescriptorProto") + proto.RegisterType((*EnumValueDescriptorProto)(nil), "google.protobuf.EnumValueDescriptorProto") + proto.RegisterType((*ServiceDescriptorProto)(nil), "google.protobuf.ServiceDescriptorProto") + proto.RegisterType((*MethodDescriptorProto)(nil), "google.protobuf.MethodDescriptorProto") + proto.RegisterType((*FileOptions)(nil), "google.protobuf.FileOptions") + proto.RegisterType((*MessageOptions)(nil), "google.protobuf.MessageOptions") + proto.RegisterType((*FieldOptions)(nil), "google.protobuf.FieldOptions") + proto.RegisterType((*OneofOptions)(nil), "google.protobuf.OneofOptions") + proto.RegisterType((*EnumOptions)(nil), "google.protobuf.EnumOptions") + proto.RegisterType((*EnumValueOptions)(nil), "google.protobuf.EnumValueOptions") + proto.RegisterType((*ServiceOptions)(nil), "google.protobuf.ServiceOptions") + proto.RegisterType((*MethodOptions)(nil), "google.protobuf.MethodOptions") + proto.RegisterType((*UninterpretedOption)(nil), "google.protobuf.UninterpretedOption") + proto.RegisterType((*UninterpretedOption_NamePart)(nil), "google.protobuf.UninterpretedOption.NamePart") + proto.RegisterType((*SourceCodeInfo)(nil), "google.protobuf.SourceCodeInfo") + proto.RegisterType((*SourceCodeInfo_Location)(nil), "google.protobuf.SourceCodeInfo.Location") + proto.RegisterType((*GeneratedCodeInfo)(nil), "google.protobuf.GeneratedCodeInfo") + proto.RegisterType((*GeneratedCodeInfo_Annotation)(nil), "google.protobuf.GeneratedCodeInfo.Annotation") + proto.RegisterEnum("google.protobuf.FieldDescriptorProto_Type", FieldDescriptorProto_Type_name, FieldDescriptorProto_Type_value) + proto.RegisterEnum("google.protobuf.FieldDescriptorProto_Label", FieldDescriptorProto_Label_name, FieldDescriptorProto_Label_value) + proto.RegisterEnum("google.protobuf.FileOptions_OptimizeMode", FileOptions_OptimizeMode_name, FileOptions_OptimizeMode_value) + proto.RegisterEnum("google.protobuf.FieldOptions_CType", FieldOptions_CType_name, FieldOptions_CType_value) + proto.RegisterEnum("google.protobuf.FieldOptions_JSType", FieldOptions_JSType_name, FieldOptions_JSType_value) + proto.RegisterEnum("google.protobuf.MethodOptions_IdempotencyLevel", MethodOptions_IdempotencyLevel_name, MethodOptions_IdempotencyLevel_value) +} + +func init() { proto.RegisterFile("google/protobuf/descriptor.proto", fileDescriptor0) } + +var fileDescriptor0 = []byte{ + // 2519 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x59, 0xdd, 0x6e, 0x1b, 0xc7, + 0x15, 0x0e, 0x7f, 0x45, 0x1e, 0x52, 0xd4, 0x68, 0xa4, 0xd8, 0x6b, 0xe5, 0xc7, 0x32, 0xf3, 0x63, + 0xd9, 0x69, 0xa8, 0x40, 0xb1, 0x1d, 0x47, 0x29, 0xd2, 0x52, 0xe4, 0x5a, 0xa1, 0x4a, 0x91, 0xec, + 0x92, 0x6a, 0x7e, 0x6e, 0x16, 0xa3, 0xdd, 0x21, 0xb9, 0xf6, 0x72, 0x77, 0xb3, 0xbb, 0xb4, 0xad, + 0xa0, 0x17, 0x06, 0x7a, 0x55, 0xa0, 0x0f, 0x50, 0x14, 0x45, 0x2f, 0x72, 0x13, 0xa0, 0x0f, 0x50, + 0x20, 0x77, 0x7d, 0x82, 0x02, 0x79, 0x83, 0xa2, 0x28, 0xd0, 0x3e, 0x46, 0x31, 0x33, 0xbb, 0xcb, + 0x5d, 0xfe, 0xc4, 0x6a, 0x80, 0x38, 0x57, 0xe4, 0x7c, 0xe7, 0x3b, 0x67, 0xce, 0x9c, 0x39, 0x33, + 0x73, 0x66, 0x16, 0x76, 0x47, 0xb6, 0x3d, 0x32, 0xe9, 0xbe, 0xe3, 0xda, 0xbe, 0x7d, 0x3e, 0x1d, + 0xee, 0xeb, 0xd4, 0xd3, 0x5c, 0xc3, 0xf1, 0x6d, 0xb7, 0xc6, 0x31, 0xbc, 0x21, 0x18, 0xb5, 0x90, + 0x51, 0x3d, 0x85, 0xcd, 0x07, 0x86, 0x49, 0x9b, 0x11, 0xb1, 0x4f, 0x7d, 0x7c, 0x1f, 0xb2, 0x43, + 0xc3, 0xa4, 0x52, 0x6a, 0x37, 0xb3, 0x57, 0x3a, 0x78, 0xb3, 0x36, 0xa7, 0x54, 0x4b, 0x6a, 0xf4, + 0x18, 0xac, 0x70, 0x8d, 0xea, 0xbf, 0xb3, 0xb0, 0xb5, 0x44, 0x8a, 0x31, 0x64, 0x2d, 0x32, 0x61, + 0x16, 0x53, 0x7b, 0x45, 0x85, 0xff, 0xc7, 0x12, 0xac, 0x39, 0x44, 0x7b, 0x44, 0x46, 0x54, 0x4a, + 0x73, 0x38, 0x6c, 0xe2, 0xd7, 0x01, 0x74, 0xea, 0x50, 0x4b, 0xa7, 0x96, 0x76, 0x21, 0x65, 0x76, + 0x33, 0x7b, 0x45, 0x25, 0x86, 0xe0, 0x77, 0x60, 0xd3, 0x99, 0x9e, 0x9b, 0x86, 0xa6, 0xc6, 0x68, + 0xb0, 0x9b, 0xd9, 0xcb, 0x29, 0x48, 0x08, 0x9a, 0x33, 0xf2, 0x4d, 0xd8, 0x78, 0x42, 0xc9, 0xa3, + 0x38, 0xb5, 0xc4, 0xa9, 0x15, 0x06, 0xc7, 0x88, 0x0d, 0x28, 0x4f, 0xa8, 0xe7, 0x91, 0x11, 0x55, + 0xfd, 0x0b, 0x87, 0x4a, 0x59, 0x3e, 0xfa, 0xdd, 0x85, 0xd1, 0xcf, 0x8f, 0xbc, 0x14, 0x68, 0x0d, + 0x2e, 0x1c, 0x8a, 0xeb, 0x50, 0xa4, 0xd6, 0x74, 0x22, 0x2c, 0xe4, 0x56, 0xc4, 0x4f, 0xb6, 0xa6, + 0x93, 0x79, 0x2b, 0x05, 0xa6, 0x16, 0x98, 0x58, 0xf3, 0xa8, 0xfb, 0xd8, 0xd0, 0xa8, 0x94, 0xe7, + 0x06, 0x6e, 0x2e, 0x18, 0xe8, 0x0b, 0xf9, 0xbc, 0x8d, 0x50, 0x0f, 0x37, 0xa0, 0x48, 0x9f, 0xfa, + 0xd4, 0xf2, 0x0c, 0xdb, 0x92, 0xd6, 0xb8, 0x91, 0xb7, 0x96, 0xcc, 0x22, 0x35, 0xf5, 0x79, 0x13, + 0x33, 0x3d, 0x7c, 0x0f, 0xd6, 0x6c, 0xc7, 0x37, 0x6c, 0xcb, 0x93, 0x0a, 0xbb, 0xa9, 0xbd, 0xd2, + 0xc1, 0xab, 0x4b, 0x13, 0xa1, 0x2b, 0x38, 0x4a, 0x48, 0xc6, 0x2d, 0x40, 0x9e, 0x3d, 0x75, 0x35, + 0xaa, 0x6a, 0xb6, 0x4e, 0x55, 0xc3, 0x1a, 0xda, 0x52, 0x91, 0x1b, 0xb8, 0xbe, 0x38, 0x10, 0x4e, + 0x6c, 0xd8, 0x3a, 0x6d, 0x59, 0x43, 0x5b, 0xa9, 0x78, 0x89, 0x36, 0xbe, 0x02, 0x79, 0xef, 0xc2, + 0xf2, 0xc9, 0x53, 0xa9, 0xcc, 0x33, 0x24, 0x68, 0x55, 0xbf, 0xcd, 0xc3, 0xc6, 0x65, 0x52, 0xec, + 0x23, 0xc8, 0x0d, 0xd9, 0x28, 0xa5, 0xf4, 0xff, 0x13, 0x03, 0xa1, 0x93, 0x0c, 0x62, 0xfe, 0x07, + 0x06, 0xb1, 0x0e, 0x25, 0x8b, 0x7a, 0x3e, 0xd5, 0x45, 0x46, 0x64, 0x2e, 0x99, 0x53, 0x20, 0x94, + 0x16, 0x53, 0x2a, 0xfb, 0x83, 0x52, 0xea, 0x33, 0xd8, 0x88, 0x5c, 0x52, 0x5d, 0x62, 0x8d, 0xc2, + 0xdc, 0xdc, 0x7f, 0x9e, 0x27, 0x35, 0x39, 0xd4, 0x53, 0x98, 0x9a, 0x52, 0xa1, 0x89, 0x36, 0x6e, + 0x02, 0xd8, 0x16, 0xb5, 0x87, 0xaa, 0x4e, 0x35, 0x53, 0x2a, 0xac, 0x88, 0x52, 0x97, 0x51, 0x16, + 0xa2, 0x64, 0x0b, 0x54, 0x33, 0xf1, 0x87, 0xb3, 0x54, 0x5b, 0x5b, 0x91, 0x29, 0xa7, 0x62, 0x91, + 0x2d, 0x64, 0xdb, 0x19, 0x54, 0x5c, 0xca, 0xf2, 0x9e, 0xea, 0xc1, 0xc8, 0x8a, 0xdc, 0x89, 0xda, + 0x73, 0x47, 0xa6, 0x04, 0x6a, 0x62, 0x60, 0xeb, 0x6e, 0xbc, 0x89, 0xdf, 0x80, 0x08, 0x50, 0x79, + 0x5a, 0x01, 0xdf, 0x85, 0xca, 0x21, 0xd8, 0x21, 0x13, 0xba, 0xf3, 0x15, 0x54, 0x92, 0xe1, 0xc1, + 0xdb, 0x90, 0xf3, 0x7c, 0xe2, 0xfa, 0x3c, 0x0b, 0x73, 0x8a, 0x68, 0x60, 0x04, 0x19, 0x6a, 0xe9, + 0x7c, 0x97, 0xcb, 0x29, 0xec, 0x2f, 0xfe, 0xe5, 0x6c, 0xc0, 0x19, 0x3e, 0xe0, 0xb7, 0x17, 0x67, + 0x34, 0x61, 0x79, 0x7e, 0xdc, 0x3b, 0x1f, 0xc0, 0x7a, 0x62, 0x00, 0x97, 0xed, 0xba, 0xfa, 0x5b, + 0x78, 0x79, 0xa9, 0x69, 0xfc, 0x19, 0x6c, 0x4f, 0x2d, 0xc3, 0xf2, 0xa9, 0xeb, 0xb8, 0x94, 0x65, + 0xac, 0xe8, 0x4a, 0xfa, 0xcf, 0xda, 0x8a, 0x9c, 0x3b, 0x8b, 0xb3, 0x85, 0x15, 0x65, 0x6b, 0xba, + 0x08, 0xde, 0x2e, 0x16, 0xfe, 0xbb, 0x86, 0x9e, 0x3d, 0x7b, 0xf6, 0x2c, 0x5d, 0xfd, 0x63, 0x1e, + 0xb6, 0x97, 0xad, 0x99, 0xa5, 0xcb, 0xf7, 0x0a, 0xe4, 0xad, 0xe9, 0xe4, 0x9c, 0xba, 0x3c, 0x48, + 0x39, 0x25, 0x68, 0xe1, 0x3a, 0xe4, 0x4c, 0x72, 0x4e, 0x4d, 0x29, 0xbb, 0x9b, 0xda, 0xab, 0x1c, + 0xbc, 0x73, 0xa9, 0x55, 0x59, 0x6b, 0x33, 0x15, 0x45, 0x68, 0xe2, 0x8f, 0x21, 0x1b, 0x6c, 0xd1, + 0xcc, 0xc2, 0xed, 0xcb, 0x59, 0x60, 0x6b, 0x49, 0xe1, 0x7a, 0xf8, 0x15, 0x28, 0xb2, 0x5f, 0x91, + 0x1b, 0x79, 0xee, 0x73, 0x81, 0x01, 0x2c, 0x2f, 0xf0, 0x0e, 0x14, 0xf8, 0x32, 0xd1, 0x69, 0x78, + 0xb4, 0x45, 0x6d, 0x96, 0x58, 0x3a, 0x1d, 0x92, 0xa9, 0xe9, 0xab, 0x8f, 0x89, 0x39, 0xa5, 0x3c, + 0xe1, 0x8b, 0x4a, 0x39, 0x00, 0x7f, 0xc3, 0x30, 0x7c, 0x1d, 0x4a, 0x62, 0x55, 0x19, 0x96, 0x4e, + 0x9f, 0xf2, 0xdd, 0x33, 0xa7, 0x88, 0x85, 0xd6, 0x62, 0x08, 0xeb, 0xfe, 0xa1, 0x67, 0x5b, 0x61, + 0x6a, 0xf2, 0x2e, 0x18, 0xc0, 0xbb, 0xff, 0x60, 0x7e, 0xe3, 0x7e, 0x6d, 0xf9, 0xf0, 0xe6, 0x73, + 0xaa, 0xfa, 0xb7, 0x34, 0x64, 0xf9, 0x7e, 0xb1, 0x01, 0xa5, 0xc1, 0xe7, 0x3d, 0x59, 0x6d, 0x76, + 0xcf, 0x8e, 0xda, 0x32, 0x4a, 0xe1, 0x0a, 0x00, 0x07, 0x1e, 0xb4, 0xbb, 0xf5, 0x01, 0x4a, 0x47, + 0xed, 0x56, 0x67, 0x70, 0xef, 0x0e, 0xca, 0x44, 0x0a, 0x67, 0x02, 0xc8, 0xc6, 0x09, 0xef, 0x1f, + 0xa0, 0x1c, 0x46, 0x50, 0x16, 0x06, 0x5a, 0x9f, 0xc9, 0xcd, 0x7b, 0x77, 0x50, 0x3e, 0x89, 0xbc, + 0x7f, 0x80, 0xd6, 0xf0, 0x3a, 0x14, 0x39, 0x72, 0xd4, 0xed, 0xb6, 0x51, 0x21, 0xb2, 0xd9, 0x1f, + 0x28, 0xad, 0xce, 0x31, 0x2a, 0x46, 0x36, 0x8f, 0x95, 0xee, 0x59, 0x0f, 0x41, 0x64, 0xe1, 0x54, + 0xee, 0xf7, 0xeb, 0xc7, 0x32, 0x2a, 0x45, 0x8c, 0xa3, 0xcf, 0x07, 0x72, 0x1f, 0x95, 0x13, 0x6e, + 0xbd, 0x7f, 0x80, 0xd6, 0xa3, 0x2e, 0xe4, 0xce, 0xd9, 0x29, 0xaa, 0xe0, 0x4d, 0x58, 0x17, 0x5d, + 0x84, 0x4e, 0x6c, 0xcc, 0x41, 0xf7, 0xee, 0x20, 0x34, 0x73, 0x44, 0x58, 0xd9, 0x4c, 0x00, 0xf7, + 0xee, 0x20, 0x5c, 0x6d, 0x40, 0x8e, 0x67, 0x17, 0xc6, 0x50, 0x69, 0xd7, 0x8f, 0xe4, 0xb6, 0xda, + 0xed, 0x0d, 0x5a, 0xdd, 0x4e, 0xbd, 0x8d, 0x52, 0x33, 0x4c, 0x91, 0x7f, 0x7d, 0xd6, 0x52, 0xe4, + 0x26, 0x4a, 0xc7, 0xb1, 0x9e, 0x5c, 0x1f, 0xc8, 0x4d, 0x94, 0xa9, 0x6a, 0xb0, 0xbd, 0x6c, 0x9f, + 0x5c, 0xba, 0x32, 0x62, 0x53, 0x9c, 0x5e, 0x31, 0xc5, 0xdc, 0xd6, 0xc2, 0x14, 0x7f, 0x9d, 0x82, + 0xad, 0x25, 0x67, 0xc5, 0xd2, 0x4e, 0x7e, 0x01, 0x39, 0x91, 0xa2, 0xe2, 0xf4, 0xbc, 0xb5, 0xf4, + 0xd0, 0xe1, 0x09, 0xbb, 0x70, 0x82, 0x72, 0xbd, 0x78, 0x05, 0x91, 0x59, 0x51, 0x41, 0x30, 0x13, + 0x0b, 0x4e, 0xfe, 0x2e, 0x05, 0xd2, 0x2a, 0xdb, 0xcf, 0xd9, 0x28, 0xd2, 0x89, 0x8d, 0xe2, 0xa3, + 0x79, 0x07, 0x6e, 0xac, 0x1e, 0xc3, 0x82, 0x17, 0xdf, 0xa4, 0xe0, 0xca, 0xf2, 0x42, 0x6b, 0xa9, + 0x0f, 0x1f, 0x43, 0x7e, 0x42, 0xfd, 0xb1, 0x1d, 0x16, 0x1b, 0x6f, 0x2f, 0x39, 0xc2, 0x98, 0x78, + 0x3e, 0x56, 0x81, 0x56, 0xfc, 0x0c, 0xcc, 0xac, 0xaa, 0x96, 0x84, 0x37, 0x0b, 0x9e, 0xfe, 0x3e, + 0x0d, 0x2f, 0x2f, 0x35, 0xbe, 0xd4, 0xd1, 0xd7, 0x00, 0x0c, 0xcb, 0x99, 0xfa, 0xa2, 0xa0, 0x10, + 0xfb, 0x53, 0x91, 0x23, 0x7c, 0xed, 0xb3, 0xbd, 0x67, 0xea, 0x47, 0xf2, 0x0c, 0x97, 0x83, 0x80, + 0x38, 0xe1, 0xfe, 0xcc, 0xd1, 0x2c, 0x77, 0xf4, 0xf5, 0x15, 0x23, 0x5d, 0x38, 0xab, 0xdf, 0x03, + 0xa4, 0x99, 0x06, 0xb5, 0x7c, 0xd5, 0xf3, 0x5d, 0x4a, 0x26, 0x86, 0x35, 0xe2, 0x1b, 0x70, 0xe1, + 0x30, 0x37, 0x24, 0xa6, 0x47, 0x95, 0x0d, 0x21, 0xee, 0x87, 0x52, 0xa6, 0xc1, 0xcf, 0x38, 0x37, + 0xa6, 0x91, 0x4f, 0x68, 0x08, 0x71, 0xa4, 0x51, 0xfd, 0xb6, 0x00, 0xa5, 0x58, 0x59, 0x8a, 0x6f, + 0x40, 0xf9, 0x21, 0x79, 0x4c, 0xd4, 0xf0, 0xaa, 0x21, 0x22, 0x51, 0x62, 0x58, 0x2f, 0xb8, 0x6e, + 0xbc, 0x07, 0xdb, 0x9c, 0x62, 0x4f, 0x7d, 0xea, 0xaa, 0x9a, 0x49, 0x3c, 0x8f, 0x07, 0xad, 0xc0, + 0xa9, 0x98, 0xc9, 0xba, 0x4c, 0xd4, 0x08, 0x25, 0xf8, 0x2e, 0x6c, 0x71, 0x8d, 0xc9, 0xd4, 0xf4, + 0x0d, 0xc7, 0xa4, 0x2a, 0xbb, 0xfc, 0x78, 0x7c, 0x23, 0x8e, 0x3c, 0xdb, 0x64, 0x8c, 0xd3, 0x80, + 0xc0, 0x3c, 0xf2, 0x70, 0x13, 0x5e, 0xe3, 0x6a, 0x23, 0x6a, 0x51, 0x97, 0xf8, 0x54, 0xa5, 0x5f, + 0x4e, 0x89, 0xe9, 0xa9, 0xc4, 0xd2, 0xd5, 0x31, 0xf1, 0xc6, 0xd2, 0x36, 0x33, 0x70, 0x94, 0x96, + 0x52, 0xca, 0x35, 0x46, 0x3c, 0x0e, 0x78, 0x32, 0xa7, 0xd5, 0x2d, 0xfd, 0x13, 0xe2, 0x8d, 0xf1, + 0x21, 0x5c, 0xe1, 0x56, 0x3c, 0xdf, 0x35, 0xac, 0x91, 0xaa, 0x8d, 0xa9, 0xf6, 0x48, 0x9d, 0xfa, + 0xc3, 0xfb, 0xd2, 0x2b, 0xf1, 0xfe, 0xb9, 0x87, 0x7d, 0xce, 0x69, 0x30, 0xca, 0x99, 0x3f, 0xbc, + 0x8f, 0xfb, 0x50, 0x66, 0x93, 0x31, 0x31, 0xbe, 0xa2, 0xea, 0xd0, 0x76, 0xf9, 0xc9, 0x52, 0x59, + 0xb2, 0xb2, 0x63, 0x11, 0xac, 0x75, 0x03, 0x85, 0x53, 0x5b, 0xa7, 0x87, 0xb9, 0x7e, 0x4f, 0x96, + 0x9b, 0x4a, 0x29, 0xb4, 0xf2, 0xc0, 0x76, 0x59, 0x42, 0x8d, 0xec, 0x28, 0xc0, 0x25, 0x91, 0x50, + 0x23, 0x3b, 0x0c, 0xef, 0x5d, 0xd8, 0xd2, 0x34, 0x31, 0x66, 0x43, 0x53, 0x83, 0x2b, 0x8a, 0x27, + 0xa1, 0x44, 0xb0, 0x34, 0xed, 0x58, 0x10, 0x82, 0x1c, 0xf7, 0xf0, 0x87, 0xf0, 0xf2, 0x2c, 0x58, + 0x71, 0xc5, 0xcd, 0x85, 0x51, 0xce, 0xab, 0xde, 0x85, 0x2d, 0xe7, 0x62, 0x51, 0x11, 0x27, 0x7a, + 0x74, 0x2e, 0xe6, 0xd5, 0x3e, 0x80, 0x6d, 0x67, 0xec, 0x2c, 0xea, 0xdd, 0x8e, 0xeb, 0x61, 0x67, + 0xec, 0xcc, 0x2b, 0xbe, 0xc5, 0xef, 0xab, 0x2e, 0xd5, 0x88, 0x4f, 0x75, 0xe9, 0x6a, 0x9c, 0x1e, + 0x13, 0xe0, 0x7d, 0x40, 0x9a, 0xa6, 0x52, 0x8b, 0x9c, 0x9b, 0x54, 0x25, 0x2e, 0xb5, 0x88, 0x27, + 0x5d, 0x8f, 0x93, 0x2b, 0x9a, 0x26, 0x73, 0x69, 0x9d, 0x0b, 0xf1, 0x6d, 0xd8, 0xb4, 0xcf, 0x1f, + 0x6a, 0x22, 0x25, 0x55, 0xc7, 0xa5, 0x43, 0xe3, 0xa9, 0xf4, 0x26, 0x8f, 0xef, 0x06, 0x13, 0xf0, + 0x84, 0xec, 0x71, 0x18, 0xdf, 0x02, 0xa4, 0x79, 0x63, 0xe2, 0x3a, 0xbc, 0x26, 0xf0, 0x1c, 0xa2, + 0x51, 0xe9, 0x2d, 0x41, 0x15, 0x78, 0x27, 0x84, 0xd9, 0x92, 0xf0, 0x9e, 0x18, 0x43, 0x3f, 0xb4, + 0x78, 0x53, 0x2c, 0x09, 0x8e, 0x05, 0xd6, 0xf6, 0x00, 0xb1, 0x50, 0x24, 0x3a, 0xde, 0xe3, 0xb4, + 0x8a, 0x33, 0x76, 0xe2, 0xfd, 0xbe, 0x01, 0xeb, 0x8c, 0x39, 0xeb, 0xf4, 0x96, 0xa8, 0x67, 0x9c, + 0x71, 0xac, 0xc7, 0x1f, 0xad, 0xb4, 0xac, 0x1e, 0x42, 0x39, 0x9e, 0x9f, 0xb8, 0x08, 0x22, 0x43, + 0x51, 0x8a, 0x9d, 0xf5, 0x8d, 0x6e, 0x93, 0x9d, 0xd2, 0x5f, 0xc8, 0x28, 0xcd, 0xaa, 0x85, 0x76, + 0x6b, 0x20, 0xab, 0xca, 0x59, 0x67, 0xd0, 0x3a, 0x95, 0x51, 0x26, 0x56, 0x96, 0x9e, 0x64, 0x0b, + 0x6f, 0xa3, 0x9b, 0xd5, 0xef, 0xd2, 0x50, 0x49, 0xde, 0x33, 0xf0, 0xcf, 0xe1, 0x6a, 0xf8, 0x28, + 0xe0, 0x51, 0x5f, 0x7d, 0x62, 0xb8, 0x7c, 0xe1, 0x4c, 0x88, 0xa8, 0xb3, 0xa3, 0xa9, 0xdb, 0x0e, + 0x58, 0x7d, 0xea, 0x7f, 0x6a, 0xb8, 0x6c, 0x59, 0x4c, 0x88, 0x8f, 0xdb, 0x70, 0xdd, 0xb2, 0x55, + 0xcf, 0x27, 0x96, 0x4e, 0x5c, 0x5d, 0x9d, 0x3d, 0xc7, 0xa8, 0x44, 0xd3, 0xa8, 0xe7, 0xd9, 0xe2, + 0xc0, 0x8a, 0xac, 0xbc, 0x6a, 0xd9, 0xfd, 0x80, 0x3c, 0xdb, 0xc9, 0xeb, 0x01, 0x75, 0x2e, 0xcd, + 0x32, 0xab, 0xd2, 0xec, 0x15, 0x28, 0x4e, 0x88, 0xa3, 0x52, 0xcb, 0x77, 0x2f, 0x78, 0x75, 0x59, + 0x50, 0x0a, 0x13, 0xe2, 0xc8, 0xac, 0xfd, 0x42, 0x8a, 0xfc, 0x93, 0x6c, 0xa1, 0x80, 0x8a, 0x27, + 0xd9, 0x42, 0x11, 0x41, 0xf5, 0x5f, 0x19, 0x28, 0xc7, 0xab, 0x4d, 0x56, 0xbc, 0x6b, 0xfc, 0x64, + 0x49, 0xf1, 0xbd, 0xe7, 0x8d, 0xef, 0xad, 0x4d, 0x6b, 0x0d, 0x76, 0xe4, 0x1c, 0xe6, 0x45, 0x0d, + 0xa8, 0x08, 0x4d, 0x76, 0xdc, 0xb3, 0xdd, 0x86, 0x8a, 0x7b, 0x4d, 0x41, 0x09, 0x5a, 0xf8, 0x18, + 0xf2, 0x0f, 0x3d, 0x6e, 0x3b, 0xcf, 0x6d, 0xbf, 0xf9, 0xfd, 0xb6, 0x4f, 0xfa, 0xdc, 0x78, 0xf1, + 0xa4, 0xaf, 0x76, 0xba, 0xca, 0x69, 0xbd, 0xad, 0x04, 0xea, 0xf8, 0x1a, 0x64, 0x4d, 0xf2, 0xd5, + 0x45, 0xf2, 0x70, 0xe2, 0xd0, 0x65, 0x27, 0xe1, 0x1a, 0x64, 0x9f, 0x50, 0xf2, 0x28, 0x79, 0x24, + 0x70, 0xe8, 0x47, 0x5c, 0x0c, 0xfb, 0x90, 0xe3, 0xf1, 0xc2, 0x00, 0x41, 0xc4, 0xd0, 0x4b, 0xb8, + 0x00, 0xd9, 0x46, 0x57, 0x61, 0x0b, 0x02, 0x41, 0x59, 0xa0, 0x6a, 0xaf, 0x25, 0x37, 0x64, 0x94, + 0xae, 0xde, 0x85, 0xbc, 0x08, 0x02, 0x5b, 0x2c, 0x51, 0x18, 0xd0, 0x4b, 0x41, 0x33, 0xb0, 0x91, + 0x0a, 0xa5, 0x67, 0xa7, 0x47, 0xb2, 0x82, 0xd2, 0xc9, 0xa9, 0xce, 0xa2, 0x5c, 0xd5, 0x83, 0x72, + 0xbc, 0xdc, 0x7c, 0x31, 0x57, 0xc9, 0xbf, 0xa7, 0xa0, 0x14, 0x2b, 0x1f, 0x59, 0xe1, 0x42, 0x4c, + 0xd3, 0x7e, 0xa2, 0x12, 0xd3, 0x20, 0x5e, 0x90, 0x1a, 0xc0, 0xa1, 0x3a, 0x43, 0x2e, 0x3b, 0x75, + 0x2f, 0x68, 0x89, 0xe4, 0x50, 0xbe, 0xfa, 0x97, 0x14, 0xa0, 0xf9, 0x02, 0x74, 0xce, 0xcd, 0xd4, + 0x4f, 0xe9, 0x66, 0xf5, 0xcf, 0x29, 0xa8, 0x24, 0xab, 0xce, 0x39, 0xf7, 0x6e, 0xfc, 0xa4, 0xee, + 0xfd, 0x33, 0x0d, 0xeb, 0x89, 0x5a, 0xf3, 0xb2, 0xde, 0x7d, 0x09, 0x9b, 0x86, 0x4e, 0x27, 0x8e, + 0xed, 0x53, 0x4b, 0xbb, 0x50, 0x4d, 0xfa, 0x98, 0x9a, 0x52, 0x95, 0x6f, 0x1a, 0xfb, 0xdf, 0x5f, + 0xcd, 0xd6, 0x5a, 0x33, 0xbd, 0x36, 0x53, 0x3b, 0xdc, 0x6a, 0x35, 0xe5, 0xd3, 0x5e, 0x77, 0x20, + 0x77, 0x1a, 0x9f, 0xab, 0x67, 0x9d, 0x5f, 0x75, 0xba, 0x9f, 0x76, 0x14, 0x64, 0xcc, 0xd1, 0x7e, + 0xc4, 0x65, 0xdf, 0x03, 0x34, 0xef, 0x14, 0xbe, 0x0a, 0xcb, 0xdc, 0x42, 0x2f, 0xe1, 0x2d, 0xd8, + 0xe8, 0x74, 0xd5, 0x7e, 0xab, 0x29, 0xab, 0xf2, 0x83, 0x07, 0x72, 0x63, 0xd0, 0x17, 0xd7, 0xfb, + 0x88, 0x3d, 0x48, 0x2c, 0xf0, 0xea, 0x9f, 0x32, 0xb0, 0xb5, 0xc4, 0x13, 0x5c, 0x0f, 0x6e, 0x16, + 0xe2, 0xb2, 0xf3, 0xee, 0x65, 0xbc, 0xaf, 0xb1, 0x82, 0xa0, 0x47, 0x5c, 0x3f, 0xb8, 0x88, 0xdc, + 0x02, 0x16, 0x25, 0xcb, 0x37, 0x86, 0x06, 0x75, 0x83, 0xd7, 0x10, 0x71, 0xdd, 0xd8, 0x98, 0xe1, + 0xe2, 0x41, 0xe4, 0x67, 0x80, 0x1d, 0xdb, 0x33, 0x7c, 0xe3, 0x31, 0x55, 0x0d, 0x2b, 0x7c, 0x3a, + 0x61, 0xd7, 0x8f, 0xac, 0x82, 0x42, 0x49, 0xcb, 0xf2, 0x23, 0xb6, 0x45, 0x47, 0x64, 0x8e, 0xcd, + 0x36, 0xf3, 0x8c, 0x82, 0x42, 0x49, 0xc4, 0xbe, 0x01, 0x65, 0xdd, 0x9e, 0xb2, 0x9a, 0x4c, 0xf0, + 0xd8, 0xd9, 0x91, 0x52, 0x4a, 0x02, 0x8b, 0x28, 0x41, 0xb5, 0x3d, 0x7b, 0xb3, 0x29, 0x2b, 0x25, + 0x81, 0x09, 0xca, 0x4d, 0xd8, 0x20, 0xa3, 0x91, 0xcb, 0x8c, 0x87, 0x86, 0xc4, 0xfd, 0xa1, 0x12, + 0xc1, 0x9c, 0xb8, 0x73, 0x02, 0x85, 0x30, 0x0e, 0xec, 0xa8, 0x66, 0x91, 0x50, 0x1d, 0xf1, 0x6e, + 0x97, 0xde, 0x2b, 0x2a, 0x05, 0x2b, 0x14, 0xde, 0x80, 0xb2, 0xe1, 0xa9, 0xb3, 0x27, 0xe8, 0xf4, + 0x6e, 0x7a, 0xaf, 0xa0, 0x94, 0x0c, 0x2f, 0x7a, 0xbe, 0xab, 0x7e, 0x93, 0x86, 0x4a, 0xf2, 0x09, + 0x1d, 0x37, 0xa1, 0x60, 0xda, 0x1a, 0xe1, 0xa9, 0x25, 0xbe, 0xdf, 0xec, 0x3d, 0xe7, 0xd5, 0xbd, + 0xd6, 0x0e, 0xf8, 0x4a, 0xa4, 0xb9, 0xf3, 0x8f, 0x14, 0x14, 0x42, 0x18, 0x5f, 0x81, 0xac, 0x43, + 0xfc, 0x31, 0x37, 0x97, 0x3b, 0x4a, 0xa3, 0x94, 0xc2, 0xdb, 0x0c, 0xf7, 0x1c, 0x62, 0xf1, 0x14, + 0x08, 0x70, 0xd6, 0x66, 0xf3, 0x6a, 0x52, 0xa2, 0xf3, 0xcb, 0x89, 0x3d, 0x99, 0x50, 0xcb, 0xf7, + 0xc2, 0x79, 0x0d, 0xf0, 0x46, 0x00, 0xe3, 0x77, 0x60, 0xd3, 0x77, 0x89, 0x61, 0x26, 0xb8, 0x59, + 0xce, 0x45, 0xa1, 0x20, 0x22, 0x1f, 0xc2, 0xb5, 0xd0, 0xae, 0x4e, 0x7d, 0xa2, 0x8d, 0xa9, 0x3e, + 0x53, 0xca, 0xf3, 0xf7, 0xd9, 0xab, 0x01, 0xa1, 0x19, 0xc8, 0x43, 0xdd, 0xea, 0x77, 0x29, 0xd8, + 0x0c, 0xaf, 0x53, 0x7a, 0x14, 0xac, 0x53, 0x00, 0x62, 0x59, 0xb6, 0x1f, 0x0f, 0xd7, 0x62, 0x2a, + 0x2f, 0xe8, 0xd5, 0xea, 0x91, 0x92, 0x12, 0x33, 0xb0, 0x33, 0x01, 0x98, 0x49, 0x56, 0x86, 0xed, + 0x3a, 0x94, 0x82, 0xef, 0x23, 0xfc, 0x23, 0x9b, 0xb8, 0x80, 0x83, 0x80, 0xd8, 0xbd, 0x0b, 0x6f, + 0x43, 0xee, 0x9c, 0x8e, 0x0c, 0x2b, 0x78, 0xf5, 0x14, 0x8d, 0xf0, 0x25, 0x37, 0x1b, 0xbd, 0xe4, + 0x1e, 0xfd, 0x21, 0x05, 0x5b, 0x9a, 0x3d, 0x99, 0xf7, 0xf7, 0x08, 0xcd, 0xbd, 0x02, 0x78, 0x9f, + 0xa4, 0xbe, 0xf8, 0x78, 0x64, 0xf8, 0xe3, 0xe9, 0x79, 0x4d, 0xb3, 0x27, 0xfb, 0x23, 0xdb, 0x24, + 0xd6, 0x68, 0xf6, 0x95, 0x90, 0xff, 0xd1, 0xde, 0x1d, 0x51, 0xeb, 0xdd, 0x91, 0x1d, 0xfb, 0x66, + 0xf8, 0xd1, 0xec, 0xef, 0xd7, 0xe9, 0xcc, 0x71, 0xef, 0xe8, 0xaf, 0xe9, 0x9d, 0x63, 0xd1, 0x57, + 0x2f, 0x8c, 0x8d, 0x42, 0x87, 0x26, 0xd5, 0xd8, 0x78, 0xff, 0x17, 0x00, 0x00, 0xff, 0xff, 0x0c, + 0xab, 0xb6, 0x37, 0x7e, 0x1c, 0x00, 0x00, +} diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/descriptor/descriptor.proto b/vendor/github.com/golang/protobuf/protoc-gen-go/descriptor/descriptor.proto new file mode 100644 index 00000000..4d4fb378 --- /dev/null +++ b/vendor/github.com/golang/protobuf/protoc-gen-go/descriptor/descriptor.proto @@ -0,0 +1,849 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// 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 +// OWNER 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// The messages in this file describe the definitions found in .proto files. +// A valid .proto file can be translated directly to a FileDescriptorProto +// without any other information (e.g. without reading its imports). + + +syntax = "proto2"; + +package google.protobuf; +option go_package = "github.com/golang/protobuf/protoc-gen-go/descriptor;descriptor"; +option java_package = "com.google.protobuf"; +option java_outer_classname = "DescriptorProtos"; +option csharp_namespace = "Google.Protobuf.Reflection"; +option objc_class_prefix = "GPB"; + +// descriptor.proto must be optimized for speed because reflection-based +// algorithms don't work during bootstrapping. +option optimize_for = SPEED; + +// The protocol compiler can output a FileDescriptorSet containing the .proto +// files it parses. +message FileDescriptorSet { + repeated FileDescriptorProto file = 1; +} + +// Describes a complete .proto file. +message FileDescriptorProto { + optional string name = 1; // file name, relative to root of source tree + optional string package = 2; // e.g. "foo", "foo.bar", etc. + + // Names of files imported by this file. + repeated string dependency = 3; + // Indexes of the public imported files in the dependency list above. + repeated int32 public_dependency = 10; + // Indexes of the weak imported files in the dependency list. + // For Google-internal migration only. Do not use. + repeated int32 weak_dependency = 11; + + // All top-level definitions in this file. + repeated DescriptorProto message_type = 4; + repeated EnumDescriptorProto enum_type = 5; + repeated ServiceDescriptorProto service = 6; + repeated FieldDescriptorProto extension = 7; + + optional FileOptions options = 8; + + // This field contains optional information about the original source code. + // You may safely remove this entire field without harming runtime + // functionality of the descriptors -- the information is needed only by + // development tools. + optional SourceCodeInfo source_code_info = 9; + + // The syntax of the proto file. + // The supported values are "proto2" and "proto3". + optional string syntax = 12; +} + +// Describes a message type. +message DescriptorProto { + optional string name = 1; + + repeated FieldDescriptorProto field = 2; + repeated FieldDescriptorProto extension = 6; + + repeated DescriptorProto nested_type = 3; + repeated EnumDescriptorProto enum_type = 4; + + message ExtensionRange { + optional int32 start = 1; + optional int32 end = 2; + + optional ExtensionRangeOptions options = 3; + } + repeated ExtensionRange extension_range = 5; + + repeated OneofDescriptorProto oneof_decl = 8; + + optional MessageOptions options = 7; + + // Range of reserved tag numbers. Reserved tag numbers may not be used by + // fields or extension ranges in the same message. Reserved ranges may + // not overlap. + message ReservedRange { + optional int32 start = 1; // Inclusive. + optional int32 end = 2; // Exclusive. + } + repeated ReservedRange reserved_range = 9; + // Reserved field names, which may not be used by fields in the same message. + // A given name may only be reserved once. + repeated string reserved_name = 10; +} + +message ExtensionRangeOptions { + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +// Describes a field within a message. +message FieldDescriptorProto { + enum Type { + // 0 is reserved for errors. + // Order is weird for historical reasons. + TYPE_DOUBLE = 1; + TYPE_FLOAT = 2; + // Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT64 if + // negative values are likely. + TYPE_INT64 = 3; + TYPE_UINT64 = 4; + // Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT32 if + // negative values are likely. + TYPE_INT32 = 5; + TYPE_FIXED64 = 6; + TYPE_FIXED32 = 7; + TYPE_BOOL = 8; + TYPE_STRING = 9; + // Tag-delimited aggregate. + // Group type is deprecated and not supported in proto3. However, Proto3 + // implementations should still be able to parse the group wire format and + // treat group fields as unknown fields. + TYPE_GROUP = 10; + TYPE_MESSAGE = 11; // Length-delimited aggregate. + + // New in version 2. + TYPE_BYTES = 12; + TYPE_UINT32 = 13; + TYPE_ENUM = 14; + TYPE_SFIXED32 = 15; + TYPE_SFIXED64 = 16; + TYPE_SINT32 = 17; // Uses ZigZag encoding. + TYPE_SINT64 = 18; // Uses ZigZag encoding. + }; + + enum Label { + // 0 is reserved for errors + LABEL_OPTIONAL = 1; + LABEL_REQUIRED = 2; + LABEL_REPEATED = 3; + }; + + optional string name = 1; + optional int32 number = 3; + optional Label label = 4; + + // If type_name is set, this need not be set. If both this and type_name + // are set, this must be one of TYPE_ENUM, TYPE_MESSAGE or TYPE_GROUP. + optional Type type = 5; + + // For message and enum types, this is the name of the type. If the name + // starts with a '.', it is fully-qualified. Otherwise, C++-like scoping + // rules are used to find the type (i.e. first the nested types within this + // message are searched, then within the parent, on up to the root + // namespace). + optional string type_name = 6; + + // For extensions, this is the name of the type being extended. It is + // resolved in the same manner as type_name. + optional string extendee = 2; + + // For numeric types, contains the original text representation of the value. + // For booleans, "true" or "false". + // For strings, contains the default text contents (not escaped in any way). + // For bytes, contains the C escaped value. All bytes >= 128 are escaped. + // TODO(kenton): Base-64 encode? + optional string default_value = 7; + + // If set, gives the index of a oneof in the containing type's oneof_decl + // list. This field is a member of that oneof. + optional int32 oneof_index = 9; + + // JSON name of this field. The value is set by protocol compiler. If the + // user has set a "json_name" option on this field, that option's value + // will be used. Otherwise, it's deduced from the field's name by converting + // it to camelCase. + optional string json_name = 10; + + optional FieldOptions options = 8; +} + +// Describes a oneof. +message OneofDescriptorProto { + optional string name = 1; + optional OneofOptions options = 2; +} + +// Describes an enum type. +message EnumDescriptorProto { + optional string name = 1; + + repeated EnumValueDescriptorProto value = 2; + + optional EnumOptions options = 3; +} + +// Describes a value within an enum. +message EnumValueDescriptorProto { + optional string name = 1; + optional int32 number = 2; + + optional EnumValueOptions options = 3; +} + +// Describes a service. +message ServiceDescriptorProto { + optional string name = 1; + repeated MethodDescriptorProto method = 2; + + optional ServiceOptions options = 3; +} + +// Describes a method of a service. +message MethodDescriptorProto { + optional string name = 1; + + // Input and output type names. These are resolved in the same way as + // FieldDescriptorProto.type_name, but must refer to a message type. + optional string input_type = 2; + optional string output_type = 3; + + optional MethodOptions options = 4; + + // Identifies if client streams multiple client messages + optional bool client_streaming = 5 [default=false]; + // Identifies if server streams multiple server messages + optional bool server_streaming = 6 [default=false]; +} + + +// =================================================================== +// Options + +// Each of the definitions above may have "options" attached. These are +// just annotations which may cause code to be generated slightly differently +// or may contain hints for code that manipulates protocol messages. +// +// Clients may define custom options as extensions of the *Options messages. +// These extensions may not yet be known at parsing time, so the parser cannot +// store the values in them. Instead it stores them in a field in the *Options +// message called uninterpreted_option. This field must have the same name +// across all *Options messages. We then use this field to populate the +// extensions when we build a descriptor, at which point all protos have been +// parsed and so all extensions are known. +// +// Extension numbers for custom options may be chosen as follows: +// * For options which will only be used within a single application or +// organization, or for experimental options, use field numbers 50000 +// through 99999. It is up to you to ensure that you do not use the +// same number for multiple options. +// * For options which will be published and used publicly by multiple +// independent entities, e-mail protobuf-global-extension-registry@google.com +// to reserve extension numbers. Simply provide your project name (e.g. +// Objective-C plugin) and your project website (if available) -- there's no +// need to explain how you intend to use them. Usually you only need one +// extension number. You can declare multiple options with only one extension +// number by putting them in a sub-message. See the Custom Options section of +// the docs for examples: +// https://developers.google.com/protocol-buffers/docs/proto#options +// If this turns out to be popular, a web service will be set up +// to automatically assign option numbers. + + +message FileOptions { + + // Sets the Java package where classes generated from this .proto will be + // placed. By default, the proto package is used, but this is often + // inappropriate because proto packages do not normally start with backwards + // domain names. + optional string java_package = 1; + + + // If set, all the classes from the .proto file are wrapped in a single + // outer class with the given name. This applies to both Proto1 + // (equivalent to the old "--one_java_file" option) and Proto2 (where + // a .proto always translates to a single class, but you may want to + // explicitly choose the class name). + optional string java_outer_classname = 8; + + // If set true, then the Java code generator will generate a separate .java + // file for each top-level message, enum, and service defined in the .proto + // file. Thus, these types will *not* be nested inside the outer class + // named by java_outer_classname. However, the outer class will still be + // generated to contain the file's getDescriptor() method as well as any + // top-level extensions defined in the file. + optional bool java_multiple_files = 10 [default=false]; + + // This option does nothing. + optional bool java_generate_equals_and_hash = 20 [deprecated=true]; + + // If set true, then the Java2 code generator will generate code that + // throws an exception whenever an attempt is made to assign a non-UTF-8 + // byte sequence to a string field. + // Message reflection will do the same. + // However, an extension field still accepts non-UTF-8 byte sequences. + // This option has no effect on when used with the lite runtime. + optional bool java_string_check_utf8 = 27 [default=false]; + + + // Generated classes can be optimized for speed or code size. + enum OptimizeMode { + SPEED = 1; // Generate complete code for parsing, serialization, + // etc. + CODE_SIZE = 2; // Use ReflectionOps to implement these methods. + LITE_RUNTIME = 3; // Generate code using MessageLite and the lite runtime. + } + optional OptimizeMode optimize_for = 9 [default=SPEED]; + + // Sets the Go package where structs generated from this .proto will be + // placed. If omitted, the Go package will be derived from the following: + // - The basename of the package import path, if provided. + // - Otherwise, the package statement in the .proto file, if present. + // - Otherwise, the basename of the .proto file, without extension. + optional string go_package = 11; + + + + // Should generic services be generated in each language? "Generic" services + // are not specific to any particular RPC system. They are generated by the + // main code generators in each language (without additional plugins). + // Generic services were the only kind of service generation supported by + // early versions of google.protobuf. + // + // Generic services are now considered deprecated in favor of using plugins + // that generate code specific to your particular RPC system. Therefore, + // these default to false. Old code which depends on generic services should + // explicitly set them to true. + optional bool cc_generic_services = 16 [default=false]; + optional bool java_generic_services = 17 [default=false]; + optional bool py_generic_services = 18 [default=false]; + optional bool php_generic_services = 42 [default=false]; + + // Is this file deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for everything in the file, or it will be completely ignored; in the very + // least, this is a formalization for deprecating files. + optional bool deprecated = 23 [default=false]; + + // Enables the use of arenas for the proto messages in this file. This applies + // only to generated classes for C++. + optional bool cc_enable_arenas = 31 [default=false]; + + + // Sets the objective c class prefix which is prepended to all objective c + // generated classes from this .proto. There is no default. + optional string objc_class_prefix = 36; + + // Namespace for generated classes; defaults to the package. + optional string csharp_namespace = 37; + + // By default Swift generators will take the proto package and CamelCase it + // replacing '.' with underscore and use that to prefix the types/symbols + // defined. When this options is provided, they will use this value instead + // to prefix the types/symbols defined. + optional string swift_prefix = 39; + + // Sets the php class prefix which is prepended to all php generated classes + // from this .proto. Default is empty. + optional string php_class_prefix = 40; + + // Use this option to change the namespace of php generated classes. Default + // is empty. When this option is empty, the package name will be used for + // determining the namespace. + optional string php_namespace = 41; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; + + reserved 38; +} + +message MessageOptions { + // Set true to use the old proto1 MessageSet wire format for extensions. + // This is provided for backwards-compatibility with the MessageSet wire + // format. You should not use this for any other reason: It's less + // efficient, has fewer features, and is more complicated. + // + // The message must be defined exactly as follows: + // message Foo { + // option message_set_wire_format = true; + // extensions 4 to max; + // } + // Note that the message cannot have any defined fields; MessageSets only + // have extensions. + // + // All extensions of your type must be singular messages; e.g. they cannot + // be int32s, enums, or repeated messages. + // + // Because this is an option, the above two restrictions are not enforced by + // the protocol compiler. + optional bool message_set_wire_format = 1 [default=false]; + + // Disables the generation of the standard "descriptor()" accessor, which can + // conflict with a field of the same name. This is meant to make migration + // from proto1 easier; new code should avoid fields named "descriptor". + optional bool no_standard_descriptor_accessor = 2 [default=false]; + + // Is this message deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for the message, or it will be completely ignored; in the very least, + // this is a formalization for deprecating messages. + optional bool deprecated = 3 [default=false]; + + // Whether the message is an automatically generated map entry type for the + // maps field. + // + // For maps fields: + // map map_field = 1; + // The parsed descriptor looks like: + // message MapFieldEntry { + // option map_entry = true; + // optional KeyType key = 1; + // optional ValueType value = 2; + // } + // repeated MapFieldEntry map_field = 1; + // + // Implementations may choose not to generate the map_entry=true message, but + // use a native map in the target language to hold the keys and values. + // The reflection APIs in such implementions still need to work as + // if the field is a repeated message field. + // + // NOTE: Do not set the option in .proto files. Always use the maps syntax + // instead. The option should only be implicitly set by the proto compiler + // parser. + optional bool map_entry = 7; + + reserved 8; // javalite_serializable + reserved 9; // javanano_as_lite + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message FieldOptions { + // The ctype option instructs the C++ code generator to use a different + // representation of the field than it normally would. See the specific + // options below. This option is not yet implemented in the open source + // release -- sorry, we'll try to include it in a future version! + optional CType ctype = 1 [default = STRING]; + enum CType { + // Default mode. + STRING = 0; + + CORD = 1; + + STRING_PIECE = 2; + } + // The packed option can be enabled for repeated primitive fields to enable + // a more efficient representation on the wire. Rather than repeatedly + // writing the tag and type for each element, the entire array is encoded as + // a single length-delimited blob. In proto3, only explicit setting it to + // false will avoid using packed encoding. + optional bool packed = 2; + + // The jstype option determines the JavaScript type used for values of the + // field. The option is permitted only for 64 bit integral and fixed types + // (int64, uint64, sint64, fixed64, sfixed64). A field with jstype JS_STRING + // is represented as JavaScript string, which avoids loss of precision that + // can happen when a large value is converted to a floating point JavaScript. + // Specifying JS_NUMBER for the jstype causes the generated JavaScript code to + // use the JavaScript "number" type. The behavior of the default option + // JS_NORMAL is implementation dependent. + // + // This option is an enum to permit additional types to be added, e.g. + // goog.math.Integer. + optional JSType jstype = 6 [default = JS_NORMAL]; + enum JSType { + // Use the default type. + JS_NORMAL = 0; + + // Use JavaScript strings. + JS_STRING = 1; + + // Use JavaScript numbers. + JS_NUMBER = 2; + } + + // Should this field be parsed lazily? Lazy applies only to message-type + // fields. It means that when the outer message is initially parsed, the + // inner message's contents will not be parsed but instead stored in encoded + // form. The inner message will actually be parsed when it is first accessed. + // + // This is only a hint. Implementations are free to choose whether to use + // eager or lazy parsing regardless of the value of this option. However, + // setting this option true suggests that the protocol author believes that + // using lazy parsing on this field is worth the additional bookkeeping + // overhead typically needed to implement it. + // + // This option does not affect the public interface of any generated code; + // all method signatures remain the same. Furthermore, thread-safety of the + // interface is not affected by this option; const methods remain safe to + // call from multiple threads concurrently, while non-const methods continue + // to require exclusive access. + // + // + // Note that implementations may choose not to check required fields within + // a lazy sub-message. That is, calling IsInitialized() on the outer message + // may return true even if the inner message has missing required fields. + // This is necessary because otherwise the inner message would have to be + // parsed in order to perform the check, defeating the purpose of lazy + // parsing. An implementation which chooses not to check required fields + // must be consistent about it. That is, for any particular sub-message, the + // implementation must either *always* check its required fields, or *never* + // check its required fields, regardless of whether or not the message has + // been parsed. + optional bool lazy = 5 [default=false]; + + // Is this field deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for accessors, or it will be completely ignored; in the very least, this + // is a formalization for deprecating fields. + optional bool deprecated = 3 [default=false]; + + // For Google-internal migration only. Do not use. + optional bool weak = 10 [default=false]; + + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; + + reserved 4; // removed jtype +} + +message OneofOptions { + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message EnumOptions { + + // Set this option to true to allow mapping different tag names to the same + // value. + optional bool allow_alias = 2; + + // Is this enum deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for the enum, or it will be completely ignored; in the very least, this + // is a formalization for deprecating enums. + optional bool deprecated = 3 [default=false]; + + reserved 5; // javanano_as_lite + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message EnumValueOptions { + // Is this enum value deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for the enum value, or it will be completely ignored; in the very least, + // this is a formalization for deprecating enum values. + optional bool deprecated = 1 [default=false]; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message ServiceOptions { + + // Note: Field numbers 1 through 32 are reserved for Google's internal RPC + // framework. We apologize for hoarding these numbers to ourselves, but + // we were already using them long before we decided to release Protocol + // Buffers. + + // Is this service deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for the service, or it will be completely ignored; in the very least, + // this is a formalization for deprecating services. + optional bool deprecated = 33 [default=false]; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message MethodOptions { + + // Note: Field numbers 1 through 32 are reserved for Google's internal RPC + // framework. We apologize for hoarding these numbers to ourselves, but + // we were already using them long before we decided to release Protocol + // Buffers. + + // Is this method deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for the method, or it will be completely ignored; in the very least, + // this is a formalization for deprecating methods. + optional bool deprecated = 33 [default=false]; + + // Is this method side-effect-free (or safe in HTTP parlance), or idempotent, + // or neither? HTTP based RPC implementation may choose GET verb for safe + // methods, and PUT verb for idempotent methods instead of the default POST. + enum IdempotencyLevel { + IDEMPOTENCY_UNKNOWN = 0; + NO_SIDE_EFFECTS = 1; // implies idempotent + IDEMPOTENT = 2; // idempotent, but may have side effects + } + optional IdempotencyLevel idempotency_level = + 34 [default=IDEMPOTENCY_UNKNOWN]; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + + +// A message representing a option the parser does not recognize. This only +// appears in options protos created by the compiler::Parser class. +// DescriptorPool resolves these when building Descriptor objects. Therefore, +// options protos in descriptor objects (e.g. returned by Descriptor::options(), +// or produced by Descriptor::CopyTo()) will never have UninterpretedOptions +// in them. +message UninterpretedOption { + // The name of the uninterpreted option. Each string represents a segment in + // a dot-separated name. is_extension is true iff a segment represents an + // extension (denoted with parentheses in options specs in .proto files). + // E.g.,{ ["foo", false], ["bar.baz", true], ["qux", false] } represents + // "foo.(bar.baz).qux". + message NamePart { + required string name_part = 1; + required bool is_extension = 2; + } + repeated NamePart name = 2; + + // The value of the uninterpreted option, in whatever type the tokenizer + // identified it as during parsing. Exactly one of these should be set. + optional string identifier_value = 3; + optional uint64 positive_int_value = 4; + optional int64 negative_int_value = 5; + optional double double_value = 6; + optional bytes string_value = 7; + optional string aggregate_value = 8; +} + +// =================================================================== +// Optional source code info + +// Encapsulates information about the original source file from which a +// FileDescriptorProto was generated. +message SourceCodeInfo { + // A Location identifies a piece of source code in a .proto file which + // corresponds to a particular definition. This information is intended + // to be useful to IDEs, code indexers, documentation generators, and similar + // tools. + // + // For example, say we have a file like: + // message Foo { + // optional string foo = 1; + // } + // Let's look at just the field definition: + // optional string foo = 1; + // ^ ^^ ^^ ^ ^^^ + // a bc de f ghi + // We have the following locations: + // span path represents + // [a,i) [ 4, 0, 2, 0 ] The whole field definition. + // [a,b) [ 4, 0, 2, 0, 4 ] The label (optional). + // [c,d) [ 4, 0, 2, 0, 5 ] The type (string). + // [e,f) [ 4, 0, 2, 0, 1 ] The name (foo). + // [g,h) [ 4, 0, 2, 0, 3 ] The number (1). + // + // Notes: + // - A location may refer to a repeated field itself (i.e. not to any + // particular index within it). This is used whenever a set of elements are + // logically enclosed in a single code segment. For example, an entire + // extend block (possibly containing multiple extension definitions) will + // have an outer location whose path refers to the "extensions" repeated + // field without an index. + // - Multiple locations may have the same path. This happens when a single + // logical declaration is spread out across multiple places. The most + // obvious example is the "extend" block again -- there may be multiple + // extend blocks in the same scope, each of which will have the same path. + // - A location's span is not always a subset of its parent's span. For + // example, the "extendee" of an extension declaration appears at the + // beginning of the "extend" block and is shared by all extensions within + // the block. + // - Just because a location's span is a subset of some other location's span + // does not mean that it is a descendent. For example, a "group" defines + // both a type and a field in a single declaration. Thus, the locations + // corresponding to the type and field and their components will overlap. + // - Code which tries to interpret locations should probably be designed to + // ignore those that it doesn't understand, as more types of locations could + // be recorded in the future. + repeated Location location = 1; + message Location { + // Identifies which part of the FileDescriptorProto was defined at this + // location. + // + // Each element is a field number or an index. They form a path from + // the root FileDescriptorProto to the place where the definition. For + // example, this path: + // [ 4, 3, 2, 7, 1 ] + // refers to: + // file.message_type(3) // 4, 3 + // .field(7) // 2, 7 + // .name() // 1 + // This is because FileDescriptorProto.message_type has field number 4: + // repeated DescriptorProto message_type = 4; + // and DescriptorProto.field has field number 2: + // repeated FieldDescriptorProto field = 2; + // and FieldDescriptorProto.name has field number 1: + // optional string name = 1; + // + // Thus, the above path gives the location of a field name. If we removed + // the last element: + // [ 4, 3, 2, 7 ] + // this path refers to the whole field declaration (from the beginning + // of the label to the terminating semicolon). + repeated int32 path = 1 [packed=true]; + + // Always has exactly three or four elements: start line, start column, + // end line (optional, otherwise assumed same as start line), end column. + // These are packed into a single field for efficiency. Note that line + // and column numbers are zero-based -- typically you will want to add + // 1 to each before displaying to a user. + repeated int32 span = 2 [packed=true]; + + // If this SourceCodeInfo represents a complete declaration, these are any + // comments appearing before and after the declaration which appear to be + // attached to the declaration. + // + // A series of line comments appearing on consecutive lines, with no other + // tokens appearing on those lines, will be treated as a single comment. + // + // leading_detached_comments will keep paragraphs of comments that appear + // before (but not connected to) the current element. Each paragraph, + // separated by empty lines, will be one comment element in the repeated + // field. + // + // Only the comment content is provided; comment markers (e.g. //) are + // stripped out. For block comments, leading whitespace and an asterisk + // will be stripped from the beginning of each line other than the first. + // Newlines are included in the output. + // + // Examples: + // + // optional int32 foo = 1; // Comment attached to foo. + // // Comment attached to bar. + // optional int32 bar = 2; + // + // optional string baz = 3; + // // Comment attached to baz. + // // Another line attached to baz. + // + // // Comment attached to qux. + // // + // // Another line attached to qux. + // optional double qux = 4; + // + // // Detached comment for corge. This is not leading or trailing comments + // // to qux or corge because there are blank lines separating it from + // // both. + // + // // Detached comment for corge paragraph 2. + // + // optional string corge = 5; + // /* Block comment attached + // * to corge. Leading asterisks + // * will be removed. */ + // /* Block comment attached to + // * grault. */ + // optional int32 grault = 6; + // + // // ignored detached comments. + optional string leading_comments = 3; + optional string trailing_comments = 4; + repeated string leading_detached_comments = 6; + } +} + +// Describes the relationship between generated code and its original source +// file. A GeneratedCodeInfo message is associated with only one generated +// source file, but may contain references to different source .proto files. +message GeneratedCodeInfo { + // An Annotation connects some span of text in generated code to an element + // of its generating .proto file. + repeated Annotation annotation = 1; + message Annotation { + // Identifies the element in the original source .proto file. This field + // is formatted the same as SourceCodeInfo.Location.path. + repeated int32 path = 1 [packed=true]; + + // Identifies the filesystem path to the original source .proto. + optional string source_file = 2; + + // Identifies the starting offset in bytes in the generated code + // that relates to the identified object. + optional int32 begin = 3; + + // Identifies the ending offset in bytes in the generated code that + // relates to the identified offset. The end offset should be one past + // the last relevant byte (so the length of the text = end - begin). + optional int32 end = 4; + } +} diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/doc.go b/vendor/github.com/golang/protobuf/protoc-gen-go/doc.go new file mode 100644 index 00000000..0d6055d6 --- /dev/null +++ b/vendor/github.com/golang/protobuf/protoc-gen-go/doc.go @@ -0,0 +1,51 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2010 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// 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 +// OWNER 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. + +/* + A plugin for the Google protocol buffer compiler to generate Go code. + Run it by building this program and putting it in your path with the name + protoc-gen-go + That word 'go' at the end becomes part of the option string set for the + protocol compiler, so once the protocol compiler (protoc) is installed + you can run + protoc --go_out=output_directory input_directory/file.proto + to generate Go bindings for the protocol defined by file.proto. + With that input, the output will be written to + output_directory/file.pb.go + + The generated code is documented in the package comment for + the library. + + See the README and documentation for protocol buffers to learn more: + https://developers.google.com/protocol-buffers/ + +*/ +package documentation diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/generator/Makefile b/vendor/github.com/golang/protobuf/protoc-gen-go/generator/Makefile new file mode 100644 index 00000000..b5715c35 --- /dev/null +++ b/vendor/github.com/golang/protobuf/protoc-gen-go/generator/Makefile @@ -0,0 +1,40 @@ +# Go support for Protocol Buffers - Google's data interchange format +# +# Copyright 2010 The Go Authors. All rights reserved. +# https://github.com/golang/protobuf +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# 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 +# OWNER 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. + +include $(GOROOT)/src/Make.inc + +TARG=github.com/golang/protobuf/compiler/generator +GOFILES=\ + generator.go\ + +DEPS=../descriptor ../plugin ../../proto + +include $(GOROOT)/src/Make.pkg diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/generator/generator.go b/vendor/github.com/golang/protobuf/protoc-gen-go/generator/generator.go new file mode 100644 index 00000000..60d52464 --- /dev/null +++ b/vendor/github.com/golang/protobuf/protoc-gen-go/generator/generator.go @@ -0,0 +1,2866 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2010 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// 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 +// OWNER 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. + +/* + The code generator for the plugin for the Google protocol buffer compiler. + It generates Go code from the protocol buffer description files read by the + main routine. +*/ +package generator + +import ( + "bufio" + "bytes" + "compress/gzip" + "fmt" + "go/parser" + "go/printer" + "go/token" + "log" + "os" + "path" + "strconv" + "strings" + "unicode" + "unicode/utf8" + + "github.com/golang/protobuf/proto" + + "github.com/golang/protobuf/protoc-gen-go/descriptor" + plugin "github.com/golang/protobuf/protoc-gen-go/plugin" +) + +// generatedCodeVersion indicates a version of the generated code. +// It is incremented whenever an incompatibility between the generated code and +// proto package is introduced; the generated code references +// a constant, proto.ProtoPackageIsVersionN (where N is generatedCodeVersion). +const generatedCodeVersion = 2 + +// A Plugin provides functionality to add to the output during Go code generation, +// such as to produce RPC stubs. +type Plugin interface { + // Name identifies the plugin. + Name() string + // Init is called once after data structures are built but before + // code generation begins. + Init(g *Generator) + // Generate produces the code generated by the plugin for this file, + // except for the imports, by calling the generator's methods P, In, and Out. + Generate(file *FileDescriptor) + // GenerateImports produces the import declarations for this file. + // It is called after Generate. + GenerateImports(file *FileDescriptor) +} + +var plugins []Plugin + +// RegisterPlugin installs a (second-order) plugin to be run when the Go output is generated. +// It is typically called during initialization. +func RegisterPlugin(p Plugin) { + plugins = append(plugins, p) +} + +// Each type we import as a protocol buffer (other than FileDescriptorProto) needs +// a pointer to the FileDescriptorProto that represents it. These types achieve that +// wrapping by placing each Proto inside a struct with the pointer to its File. The +// structs have the same names as their contents, with "Proto" removed. +// FileDescriptor is used to store the things that it points to. + +// The file and package name method are common to messages and enums. +type common struct { + file *descriptor.FileDescriptorProto // File this object comes from. +} + +// PackageName is name in the package clause in the generated file. +func (c *common) PackageName() string { return uniquePackageOf(c.file) } + +func (c *common) File() *descriptor.FileDescriptorProto { return c.file } + +func fileIsProto3(file *descriptor.FileDescriptorProto) bool { + return file.GetSyntax() == "proto3" +} + +func (c *common) proto3() bool { return fileIsProto3(c.file) } + +// Descriptor represents a protocol buffer message. +type Descriptor struct { + common + *descriptor.DescriptorProto + parent *Descriptor // The containing message, if any. + nested []*Descriptor // Inner messages, if any. + enums []*EnumDescriptor // Inner enums, if any. + ext []*ExtensionDescriptor // Extensions, if any. + typename []string // Cached typename vector. + index int // The index into the container, whether the file or another message. + path string // The SourceCodeInfo path as comma-separated integers. + group bool +} + +// TypeName returns the elements of the dotted type name. +// The package name is not part of this name. +func (d *Descriptor) TypeName() []string { + if d.typename != nil { + return d.typename + } + n := 0 + for parent := d; parent != nil; parent = parent.parent { + n++ + } + s := make([]string, n, n) + for parent := d; parent != nil; parent = parent.parent { + n-- + s[n] = parent.GetName() + } + d.typename = s + return s +} + +// EnumDescriptor describes an enum. If it's at top level, its parent will be nil. +// Otherwise it will be the descriptor of the message in which it is defined. +type EnumDescriptor struct { + common + *descriptor.EnumDescriptorProto + parent *Descriptor // The containing message, if any. + typename []string // Cached typename vector. + index int // The index into the container, whether the file or a message. + path string // The SourceCodeInfo path as comma-separated integers. +} + +// TypeName returns the elements of the dotted type name. +// The package name is not part of this name. +func (e *EnumDescriptor) TypeName() (s []string) { + if e.typename != nil { + return e.typename + } + name := e.GetName() + if e.parent == nil { + s = make([]string, 1) + } else { + pname := e.parent.TypeName() + s = make([]string, len(pname)+1) + copy(s, pname) + } + s[len(s)-1] = name + e.typename = s + return s +} + +// Everything but the last element of the full type name, CamelCased. +// The values of type Foo.Bar are call Foo_value1... not Foo_Bar_value1... . +func (e *EnumDescriptor) prefix() string { + if e.parent == nil { + // If the enum is not part of a message, the prefix is just the type name. + return CamelCase(*e.Name) + "_" + } + typeName := e.TypeName() + return CamelCaseSlice(typeName[0:len(typeName)-1]) + "_" +} + +// The integer value of the named constant in this enumerated type. +func (e *EnumDescriptor) integerValueAsString(name string) string { + for _, c := range e.Value { + if c.GetName() == name { + return fmt.Sprint(c.GetNumber()) + } + } + log.Fatal("cannot find value for enum constant") + return "" +} + +// ExtensionDescriptor describes an extension. If it's at top level, its parent will be nil. +// Otherwise it will be the descriptor of the message in which it is defined. +type ExtensionDescriptor struct { + common + *descriptor.FieldDescriptorProto + parent *Descriptor // The containing message, if any. +} + +// TypeName returns the elements of the dotted type name. +// The package name is not part of this name. +func (e *ExtensionDescriptor) TypeName() (s []string) { + name := e.GetName() + if e.parent == nil { + // top-level extension + s = make([]string, 1) + } else { + pname := e.parent.TypeName() + s = make([]string, len(pname)+1) + copy(s, pname) + } + s[len(s)-1] = name + return s +} + +// DescName returns the variable name used for the generated descriptor. +func (e *ExtensionDescriptor) DescName() string { + // The full type name. + typeName := e.TypeName() + // Each scope of the extension is individually CamelCased, and all are joined with "_" with an "E_" prefix. + for i, s := range typeName { + typeName[i] = CamelCase(s) + } + return "E_" + strings.Join(typeName, "_") +} + +// ImportedDescriptor describes a type that has been publicly imported from another file. +type ImportedDescriptor struct { + common + o Object +} + +func (id *ImportedDescriptor) TypeName() []string { return id.o.TypeName() } + +// FileDescriptor describes an protocol buffer descriptor file (.proto). +// It includes slices of all the messages and enums defined within it. +// Those slices are constructed by WrapTypes. +type FileDescriptor struct { + *descriptor.FileDescriptorProto + desc []*Descriptor // All the messages defined in this file. + enum []*EnumDescriptor // All the enums defined in this file. + ext []*ExtensionDescriptor // All the top-level extensions defined in this file. + imp []*ImportedDescriptor // All types defined in files publicly imported by this file. + + // Comments, stored as a map of path (comma-separated integers) to the comment. + comments map[string]*descriptor.SourceCodeInfo_Location + + // The full list of symbols that are exported, + // as a map from the exported object to its symbols. + // This is used for supporting public imports. + exported map[Object][]symbol + + index int // The index of this file in the list of files to generate code for + + proto3 bool // whether to generate proto3 code for this file +} + +// PackageName is the package name we'll use in the generated code to refer to this file. +func (d *FileDescriptor) PackageName() string { return uniquePackageOf(d.FileDescriptorProto) } + +// VarName is the variable name we'll use in the generated code to refer +// to the compressed bytes of this descriptor. It is not exported, so +// it is only valid inside the generated package. +func (d *FileDescriptor) VarName() string { return fmt.Sprintf("fileDescriptor%d", d.index) } + +// goPackageOption interprets the file's go_package option. +// If there is no go_package, it returns ("", "", false). +// If there's a simple name, it returns ("", pkg, true). +// If the option implies an import path, it returns (impPath, pkg, true). +func (d *FileDescriptor) goPackageOption() (impPath, pkg string, ok bool) { + pkg = d.GetOptions().GetGoPackage() + if pkg == "" { + return + } + ok = true + // The presence of a slash implies there's an import path. + slash := strings.LastIndex(pkg, "/") + if slash < 0 { + return + } + impPath, pkg = pkg, pkg[slash+1:] + // A semicolon-delimited suffix overrides the package name. + sc := strings.IndexByte(impPath, ';') + if sc < 0 { + return + } + impPath, pkg = impPath[:sc], impPath[sc+1:] + return +} + +// goPackageName returns the Go package name to use in the +// generated Go file. The result explicit reports whether the name +// came from an option go_package statement. If explicit is false, +// the name was derived from the protocol buffer's package statement +// or the input file name. +func (d *FileDescriptor) goPackageName() (name string, explicit bool) { + // Does the file have a "go_package" option? + if _, pkg, ok := d.goPackageOption(); ok { + return pkg, true + } + + // Does the file have a package clause? + if pkg := d.GetPackage(); pkg != "" { + return pkg, false + } + // Use the file base name. + return baseName(d.GetName()), false +} + +// goFileName returns the output name for the generated Go file. +func (d *FileDescriptor) goFileName() string { + name := *d.Name + if ext := path.Ext(name); ext == ".proto" || ext == ".protodevel" { + name = name[:len(name)-len(ext)] + } + name += ".pb.go" + + // Does the file have a "go_package" option? + // If it does, it may override the filename. + if impPath, _, ok := d.goPackageOption(); ok && impPath != "" { + // Replace the existing dirname with the declared import path. + _, name = path.Split(name) + name = path.Join(impPath, name) + return name + } + + return name +} + +func (d *FileDescriptor) addExport(obj Object, sym symbol) { + d.exported[obj] = append(d.exported[obj], sym) +} + +// symbol is an interface representing an exported Go symbol. +type symbol interface { + // GenerateAlias should generate an appropriate alias + // for the symbol from the named package. + GenerateAlias(g *Generator, pkg string) +} + +type messageSymbol struct { + sym string + hasExtensions, isMessageSet bool + hasOneof bool + getters []getterSymbol +} + +type getterSymbol struct { + name string + typ string + typeName string // canonical name in proto world; empty for proto.Message and similar + genType bool // whether typ contains a generated type (message/group/enum) +} + +func (ms *messageSymbol) GenerateAlias(g *Generator, pkg string) { + remoteSym := pkg + "." + ms.sym + + g.P("type ", ms.sym, " ", remoteSym) + g.P("func (m *", ms.sym, ") Reset() { (*", remoteSym, ")(m).Reset() }") + g.P("func (m *", ms.sym, ") String() string { return (*", remoteSym, ")(m).String() }") + g.P("func (*", ms.sym, ") ProtoMessage() {}") + if ms.hasExtensions { + g.P("func (*", ms.sym, ") ExtensionRangeArray() []", g.Pkg["proto"], ".ExtensionRange ", + "{ return (*", remoteSym, ")(nil).ExtensionRangeArray() }") + if ms.isMessageSet { + g.P("func (m *", ms.sym, ") Marshal() ([]byte, error) ", + "{ return (*", remoteSym, ")(m).Marshal() }") + g.P("func (m *", ms.sym, ") Unmarshal(buf []byte) error ", + "{ return (*", remoteSym, ")(m).Unmarshal(buf) }") + } + } + if ms.hasOneof { + // Oneofs and public imports do not mix well. + // We can make them work okay for the binary format, + // but they're going to break weirdly for text/JSON. + enc := "_" + ms.sym + "_OneofMarshaler" + dec := "_" + ms.sym + "_OneofUnmarshaler" + size := "_" + ms.sym + "_OneofSizer" + encSig := "(msg " + g.Pkg["proto"] + ".Message, b *" + g.Pkg["proto"] + ".Buffer) error" + decSig := "(msg " + g.Pkg["proto"] + ".Message, tag, wire int, b *" + g.Pkg["proto"] + ".Buffer) (bool, error)" + sizeSig := "(msg " + g.Pkg["proto"] + ".Message) int" + g.P("func (m *", ms.sym, ") XXX_OneofFuncs() (func", encSig, ", func", decSig, ", func", sizeSig, ", []interface{}) {") + g.P("return ", enc, ", ", dec, ", ", size, ", nil") + g.P("}") + + g.P("func ", enc, encSig, " {") + g.P("m := msg.(*", ms.sym, ")") + g.P("m0 := (*", remoteSym, ")(m)") + g.P("enc, _, _, _ := m0.XXX_OneofFuncs()") + g.P("return enc(m0, b)") + g.P("}") + + g.P("func ", dec, decSig, " {") + g.P("m := msg.(*", ms.sym, ")") + g.P("m0 := (*", remoteSym, ")(m)") + g.P("_, dec, _, _ := m0.XXX_OneofFuncs()") + g.P("return dec(m0, tag, wire, b)") + g.P("}") + + g.P("func ", size, sizeSig, " {") + g.P("m := msg.(*", ms.sym, ")") + g.P("m0 := (*", remoteSym, ")(m)") + g.P("_, _, size, _ := m0.XXX_OneofFuncs()") + g.P("return size(m0)") + g.P("}") + } + for _, get := range ms.getters { + + if get.typeName != "" { + g.RecordTypeUse(get.typeName) + } + typ := get.typ + val := "(*" + remoteSym + ")(m)." + get.name + "()" + if get.genType { + // typ will be "*pkg.T" (message/group) or "pkg.T" (enum) + // or "map[t]*pkg.T" (map to message/enum). + // The first two of those might have a "[]" prefix if it is repeated. + // Drop any package qualifier since we have hoisted the type into this package. + rep := strings.HasPrefix(typ, "[]") + if rep { + typ = typ[2:] + } + isMap := strings.HasPrefix(typ, "map[") + star := typ[0] == '*' + if !isMap { // map types handled lower down + typ = typ[strings.Index(typ, ".")+1:] + } + if star { + typ = "*" + typ + } + if rep { + // Go does not permit conversion between slice types where both + // element types are named. That means we need to generate a bit + // of code in this situation. + // typ is the element type. + // val is the expression to get the slice from the imported type. + + ctyp := typ // conversion type expression; "Foo" or "(*Foo)" + if star { + ctyp = "(" + typ + ")" + } + + g.P("func (m *", ms.sym, ") ", get.name, "() []", typ, " {") + g.In() + g.P("o := ", val) + g.P("if o == nil {") + g.In() + g.P("return nil") + g.Out() + g.P("}") + g.P("s := make([]", typ, ", len(o))") + g.P("for i, x := range o {") + g.In() + g.P("s[i] = ", ctyp, "(x)") + g.Out() + g.P("}") + g.P("return s") + g.Out() + g.P("}") + continue + } + if isMap { + // Split map[keyTyp]valTyp. + bra, ket := strings.Index(typ, "["), strings.Index(typ, "]") + keyTyp, valTyp := typ[bra+1:ket], typ[ket+1:] + // Drop any package qualifier. + // Only the value type may be foreign. + star := valTyp[0] == '*' + valTyp = valTyp[strings.Index(valTyp, ".")+1:] + if star { + valTyp = "*" + valTyp + } + + typ := "map[" + keyTyp + "]" + valTyp + g.P("func (m *", ms.sym, ") ", get.name, "() ", typ, " {") + g.P("o := ", val) + g.P("if o == nil { return nil }") + g.P("s := make(", typ, ", len(o))") + g.P("for k, v := range o {") + g.P("s[k] = (", valTyp, ")(v)") + g.P("}") + g.P("return s") + g.P("}") + continue + } + // Convert imported type into the forwarding type. + val = "(" + typ + ")(" + val + ")" + } + + g.P("func (m *", ms.sym, ") ", get.name, "() ", typ, " { return ", val, " }") + } + +} + +type enumSymbol struct { + name string + proto3 bool // Whether this came from a proto3 file. +} + +func (es enumSymbol) GenerateAlias(g *Generator, pkg string) { + s := es.name + g.P("type ", s, " ", pkg, ".", s) + g.P("var ", s, "_name = ", pkg, ".", s, "_name") + g.P("var ", s, "_value = ", pkg, ".", s, "_value") + g.P("func (x ", s, ") String() string { return (", pkg, ".", s, ")(x).String() }") + if !es.proto3 { + g.P("func (x ", s, ") Enum() *", s, "{ return (*", s, ")((", pkg, ".", s, ")(x).Enum()) }") + g.P("func (x *", s, ") UnmarshalJSON(data []byte) error { return (*", pkg, ".", s, ")(x).UnmarshalJSON(data) }") + } +} + +type constOrVarSymbol struct { + sym string + typ string // either "const" or "var" + cast string // if non-empty, a type cast is required (used for enums) +} + +func (cs constOrVarSymbol) GenerateAlias(g *Generator, pkg string) { + v := pkg + "." + cs.sym + if cs.cast != "" { + v = cs.cast + "(" + v + ")" + } + g.P(cs.typ, " ", cs.sym, " = ", v) +} + +// Object is an interface abstracting the abilities shared by enums, messages, extensions and imported objects. +type Object interface { + PackageName() string // The name we use in our output (a_b_c), possibly renamed for uniqueness. + TypeName() []string + File() *descriptor.FileDescriptorProto +} + +// Each package name we generate must be unique. The package we're generating +// gets its own name but every other package must have a unique name that does +// not conflict in the code we generate. These names are chosen globally (although +// they don't have to be, it simplifies things to do them globally). +func uniquePackageOf(fd *descriptor.FileDescriptorProto) string { + s, ok := uniquePackageName[fd] + if !ok { + log.Fatal("internal error: no package name defined for " + fd.GetName()) + } + return s +} + +// Generator is the type whose methods generate the output, stored in the associated response structure. +type Generator struct { + *bytes.Buffer + + Request *plugin.CodeGeneratorRequest // The input. + Response *plugin.CodeGeneratorResponse // The output. + + Param map[string]string // Command-line parameters. + PackageImportPath string // Go import path of the package we're generating code for + ImportPrefix string // String to prefix to imported package file names. + ImportMap map[string]string // Mapping from .proto file name to import path + + Pkg map[string]string // The names under which we import support packages + + packageName string // What we're calling ourselves. + allFiles []*FileDescriptor // All files in the tree + allFilesByName map[string]*FileDescriptor // All files by filename. + genFiles []*FileDescriptor // Those files we will generate output for. + file *FileDescriptor // The file we are compiling now. + usedPackages map[string]bool // Names of packages used in current file. + typeNameToObject map[string]Object // Key is a fully-qualified name in input syntax. + init []string // Lines to emit in the init function. + indent string + writeOutput bool +} + +// New creates a new generator and allocates the request and response protobufs. +func New() *Generator { + g := new(Generator) + g.Buffer = new(bytes.Buffer) + g.Request = new(plugin.CodeGeneratorRequest) + g.Response = new(plugin.CodeGeneratorResponse) + return g +} + +// Error reports a problem, including an error, and exits the program. +func (g *Generator) Error(err error, msgs ...string) { + s := strings.Join(msgs, " ") + ":" + err.Error() + log.Print("protoc-gen-go: error:", s) + os.Exit(1) +} + +// Fail reports a problem and exits the program. +func (g *Generator) Fail(msgs ...string) { + s := strings.Join(msgs, " ") + log.Print("protoc-gen-go: error:", s) + os.Exit(1) +} + +// CommandLineParameters breaks the comma-separated list of key=value pairs +// in the parameter (a member of the request protobuf) into a key/value map. +// It then sets file name mappings defined by those entries. +func (g *Generator) CommandLineParameters(parameter string) { + g.Param = make(map[string]string) + for _, p := range strings.Split(parameter, ",") { + if i := strings.Index(p, "="); i < 0 { + g.Param[p] = "" + } else { + g.Param[p[0:i]] = p[i+1:] + } + } + + g.ImportMap = make(map[string]string) + pluginList := "none" // Default list of plugin names to enable (empty means all). + for k, v := range g.Param { + switch k { + case "import_prefix": + g.ImportPrefix = v + case "import_path": + g.PackageImportPath = v + case "plugins": + pluginList = v + default: + if len(k) > 0 && k[0] == 'M' { + g.ImportMap[k[1:]] = v + } + } + } + if pluginList != "" { + // Amend the set of plugins. + enabled := make(map[string]bool) + for _, name := range strings.Split(pluginList, "+") { + enabled[name] = true + } + var nplugins []Plugin + for _, p := range plugins { + if enabled[p.Name()] { + nplugins = append(nplugins, p) + } + } + plugins = nplugins + } +} + +// DefaultPackageName returns the package name printed for the object. +// If its file is in a different package, it returns the package name we're using for this file, plus ".". +// Otherwise it returns the empty string. +func (g *Generator) DefaultPackageName(obj Object) string { + pkg := obj.PackageName() + if pkg == g.packageName { + return "" + } + return pkg + "." +} + +// For each input file, the unique package name to use, underscored. +var uniquePackageName = make(map[*descriptor.FileDescriptorProto]string) + +// Package names already registered. Key is the name from the .proto file; +// value is the name that appears in the generated code. +var pkgNamesInUse = make(map[string]bool) + +// Create and remember a guaranteed unique package name for this file descriptor. +// Pkg is the candidate name. If f is nil, it's a builtin package like "proto" and +// has no file descriptor. +func RegisterUniquePackageName(pkg string, f *FileDescriptor) string { + // Convert dots to underscores before finding a unique alias. + pkg = strings.Map(badToUnderscore, pkg) + + for i, orig := 1, pkg; pkgNamesInUse[pkg]; i++ { + // It's a duplicate; must rename. + pkg = orig + strconv.Itoa(i) + } + // Install it. + pkgNamesInUse[pkg] = true + if f != nil { + uniquePackageName[f.FileDescriptorProto] = pkg + } + return pkg +} + +var isGoKeyword = map[string]bool{ + "break": true, + "case": true, + "chan": true, + "const": true, + "continue": true, + "default": true, + "else": true, + "defer": true, + "fallthrough": true, + "for": true, + "func": true, + "go": true, + "goto": true, + "if": true, + "import": true, + "interface": true, + "map": true, + "package": true, + "range": true, + "return": true, + "select": true, + "struct": true, + "switch": true, + "type": true, + "var": true, +} + +// defaultGoPackage returns the package name to use, +// derived from the import path of the package we're building code for. +func (g *Generator) defaultGoPackage() string { + p := g.PackageImportPath + if i := strings.LastIndex(p, "/"); i >= 0 { + p = p[i+1:] + } + if p == "" { + return "" + } + + p = strings.Map(badToUnderscore, p) + // Identifier must not be keyword: insert _. + if isGoKeyword[p] { + p = "_" + p + } + // Identifier must not begin with digit: insert _. + if r, _ := utf8.DecodeRuneInString(p); unicode.IsDigit(r) { + p = "_" + p + } + return p +} + +// SetPackageNames sets the package name for this run. +// The package name must agree across all files being generated. +// It also defines unique package names for all imported files. +func (g *Generator) SetPackageNames() { + // Register the name for this package. It will be the first name + // registered so is guaranteed to be unmodified. + pkg, explicit := g.genFiles[0].goPackageName() + + // Check all files for an explicit go_package option. + for _, f := range g.genFiles { + thisPkg, thisExplicit := f.goPackageName() + if thisExplicit { + if !explicit { + // Let this file's go_package option serve for all input files. + pkg, explicit = thisPkg, true + } else if thisPkg != pkg { + g.Fail("inconsistent package names:", thisPkg, pkg) + } + } + } + + // If we don't have an explicit go_package option but we have an + // import path, use that. + if !explicit { + p := g.defaultGoPackage() + if p != "" { + pkg, explicit = p, true + } + } + + // If there was no go_package and no import path to use, + // double-check that all the inputs have the same implicit + // Go package name. + if !explicit { + for _, f := range g.genFiles { + thisPkg, _ := f.goPackageName() + if thisPkg != pkg { + g.Fail("inconsistent package names:", thisPkg, pkg) + } + } + } + + g.packageName = RegisterUniquePackageName(pkg, g.genFiles[0]) + + // Register the support package names. They might collide with the + // name of a package we import. + g.Pkg = map[string]string{ + "fmt": RegisterUniquePackageName("fmt", nil), + "math": RegisterUniquePackageName("math", nil), + "proto": RegisterUniquePackageName("proto", nil), + } + +AllFiles: + for _, f := range g.allFiles { + for _, genf := range g.genFiles { + if f == genf { + // In this package already. + uniquePackageName[f.FileDescriptorProto] = g.packageName + continue AllFiles + } + } + // The file is a dependency, so we want to ignore its go_package option + // because that is only relevant for its specific generated output. + pkg := f.GetPackage() + if pkg == "" { + pkg = baseName(*f.Name) + } + RegisterUniquePackageName(pkg, f) + } +} + +// WrapTypes walks the incoming data, wrapping DescriptorProtos, EnumDescriptorProtos +// and FileDescriptorProtos into file-referenced objects within the Generator. +// It also creates the list of files to generate and so should be called before GenerateAllFiles. +func (g *Generator) WrapTypes() { + g.allFiles = make([]*FileDescriptor, 0, len(g.Request.ProtoFile)) + g.allFilesByName = make(map[string]*FileDescriptor, len(g.allFiles)) + for _, f := range g.Request.ProtoFile { + // We must wrap the descriptors before we wrap the enums + descs := wrapDescriptors(f) + g.buildNestedDescriptors(descs) + enums := wrapEnumDescriptors(f, descs) + g.buildNestedEnums(descs, enums) + exts := wrapExtensions(f) + fd := &FileDescriptor{ + FileDescriptorProto: f, + desc: descs, + enum: enums, + ext: exts, + exported: make(map[Object][]symbol), + proto3: fileIsProto3(f), + } + extractComments(fd) + g.allFiles = append(g.allFiles, fd) + g.allFilesByName[f.GetName()] = fd + } + for _, fd := range g.allFiles { + fd.imp = wrapImported(fd.FileDescriptorProto, g) + } + + g.genFiles = make([]*FileDescriptor, 0, len(g.Request.FileToGenerate)) + for _, fileName := range g.Request.FileToGenerate { + fd := g.allFilesByName[fileName] + if fd == nil { + g.Fail("could not find file named", fileName) + } + fd.index = len(g.genFiles) + g.genFiles = append(g.genFiles, fd) + } +} + +// Scan the descriptors in this file. For each one, build the slice of nested descriptors +func (g *Generator) buildNestedDescriptors(descs []*Descriptor) { + for _, desc := range descs { + if len(desc.NestedType) != 0 { + for _, nest := range descs { + if nest.parent == desc { + desc.nested = append(desc.nested, nest) + } + } + if len(desc.nested) != len(desc.NestedType) { + g.Fail("internal error: nesting failure for", desc.GetName()) + } + } + } +} + +func (g *Generator) buildNestedEnums(descs []*Descriptor, enums []*EnumDescriptor) { + for _, desc := range descs { + if len(desc.EnumType) != 0 { + for _, enum := range enums { + if enum.parent == desc { + desc.enums = append(desc.enums, enum) + } + } + if len(desc.enums) != len(desc.EnumType) { + g.Fail("internal error: enum nesting failure for", desc.GetName()) + } + } + } +} + +// Construct the Descriptor +func newDescriptor(desc *descriptor.DescriptorProto, parent *Descriptor, file *descriptor.FileDescriptorProto, index int) *Descriptor { + d := &Descriptor{ + common: common{file}, + DescriptorProto: desc, + parent: parent, + index: index, + } + if parent == nil { + d.path = fmt.Sprintf("%d,%d", messagePath, index) + } else { + d.path = fmt.Sprintf("%s,%d,%d", parent.path, messageMessagePath, index) + } + + // The only way to distinguish a group from a message is whether + // the containing message has a TYPE_GROUP field that matches. + if parent != nil { + parts := d.TypeName() + if file.Package != nil { + parts = append([]string{*file.Package}, parts...) + } + exp := "." + strings.Join(parts, ".") + for _, field := range parent.Field { + if field.GetType() == descriptor.FieldDescriptorProto_TYPE_GROUP && field.GetTypeName() == exp { + d.group = true + break + } + } + } + + for _, field := range desc.Extension { + d.ext = append(d.ext, &ExtensionDescriptor{common{file}, field, d}) + } + + return d +} + +// Return a slice of all the Descriptors defined within this file +func wrapDescriptors(file *descriptor.FileDescriptorProto) []*Descriptor { + sl := make([]*Descriptor, 0, len(file.MessageType)+10) + for i, desc := range file.MessageType { + sl = wrapThisDescriptor(sl, desc, nil, file, i) + } + return sl +} + +// Wrap this Descriptor, recursively +func wrapThisDescriptor(sl []*Descriptor, desc *descriptor.DescriptorProto, parent *Descriptor, file *descriptor.FileDescriptorProto, index int) []*Descriptor { + sl = append(sl, newDescriptor(desc, parent, file, index)) + me := sl[len(sl)-1] + for i, nested := range desc.NestedType { + sl = wrapThisDescriptor(sl, nested, me, file, i) + } + return sl +} + +// Construct the EnumDescriptor +func newEnumDescriptor(desc *descriptor.EnumDescriptorProto, parent *Descriptor, file *descriptor.FileDescriptorProto, index int) *EnumDescriptor { + ed := &EnumDescriptor{ + common: common{file}, + EnumDescriptorProto: desc, + parent: parent, + index: index, + } + if parent == nil { + ed.path = fmt.Sprintf("%d,%d", enumPath, index) + } else { + ed.path = fmt.Sprintf("%s,%d,%d", parent.path, messageEnumPath, index) + } + return ed +} + +// Return a slice of all the EnumDescriptors defined within this file +func wrapEnumDescriptors(file *descriptor.FileDescriptorProto, descs []*Descriptor) []*EnumDescriptor { + sl := make([]*EnumDescriptor, 0, len(file.EnumType)+10) + // Top-level enums. + for i, enum := range file.EnumType { + sl = append(sl, newEnumDescriptor(enum, nil, file, i)) + } + // Enums within messages. Enums within embedded messages appear in the outer-most message. + for _, nested := range descs { + for i, enum := range nested.EnumType { + sl = append(sl, newEnumDescriptor(enum, nested, file, i)) + } + } + return sl +} + +// Return a slice of all the top-level ExtensionDescriptors defined within this file. +func wrapExtensions(file *descriptor.FileDescriptorProto) []*ExtensionDescriptor { + var sl []*ExtensionDescriptor + for _, field := range file.Extension { + sl = append(sl, &ExtensionDescriptor{common{file}, field, nil}) + } + return sl +} + +// Return a slice of all the types that are publicly imported into this file. +func wrapImported(file *descriptor.FileDescriptorProto, g *Generator) (sl []*ImportedDescriptor) { + for _, index := range file.PublicDependency { + df := g.fileByName(file.Dependency[index]) + for _, d := range df.desc { + if d.GetOptions().GetMapEntry() { + continue + } + sl = append(sl, &ImportedDescriptor{common{file}, d}) + } + for _, e := range df.enum { + sl = append(sl, &ImportedDescriptor{common{file}, e}) + } + for _, ext := range df.ext { + sl = append(sl, &ImportedDescriptor{common{file}, ext}) + } + } + return +} + +func extractComments(file *FileDescriptor) { + file.comments = make(map[string]*descriptor.SourceCodeInfo_Location) + for _, loc := range file.GetSourceCodeInfo().GetLocation() { + if loc.LeadingComments == nil { + continue + } + var p []string + for _, n := range loc.Path { + p = append(p, strconv.Itoa(int(n))) + } + file.comments[strings.Join(p, ",")] = loc + } +} + +// BuildTypeNameMap builds the map from fully qualified type names to objects. +// The key names for the map come from the input data, which puts a period at the beginning. +// It should be called after SetPackageNames and before GenerateAllFiles. +func (g *Generator) BuildTypeNameMap() { + g.typeNameToObject = make(map[string]Object) + for _, f := range g.allFiles { + // The names in this loop are defined by the proto world, not us, so the + // package name may be empty. If so, the dotted package name of X will + // be ".X"; otherwise it will be ".pkg.X". + dottedPkg := "." + f.GetPackage() + if dottedPkg != "." { + dottedPkg += "." + } + for _, enum := range f.enum { + name := dottedPkg + dottedSlice(enum.TypeName()) + g.typeNameToObject[name] = enum + } + for _, desc := range f.desc { + name := dottedPkg + dottedSlice(desc.TypeName()) + g.typeNameToObject[name] = desc + } + } +} + +// ObjectNamed, given a fully-qualified input type name as it appears in the input data, +// returns the descriptor for the message or enum with that name. +func (g *Generator) ObjectNamed(typeName string) Object { + o, ok := g.typeNameToObject[typeName] + if !ok { + g.Fail("can't find object with type", typeName) + } + + // If the file of this object isn't a direct dependency of the current file, + // or in the current file, then this object has been publicly imported into + // a dependency of the current file. + // We should return the ImportedDescriptor object for it instead. + direct := *o.File().Name == *g.file.Name + if !direct { + for _, dep := range g.file.Dependency { + if *g.fileByName(dep).Name == *o.File().Name { + direct = true + break + } + } + } + if !direct { + found := false + Loop: + for _, dep := range g.file.Dependency { + df := g.fileByName(*g.fileByName(dep).Name) + for _, td := range df.imp { + if td.o == o { + // Found it! + o = td + found = true + break Loop + } + } + } + if !found { + log.Printf("protoc-gen-go: WARNING: failed finding publicly imported dependency for %v, used in %v", typeName, *g.file.Name) + } + } + + return o +} + +// P prints the arguments to the generated output. It handles strings and int32s, plus +// handling indirections because they may be *string, etc. +func (g *Generator) P(str ...interface{}) { + if !g.writeOutput { + return + } + g.WriteString(g.indent) + for _, v := range str { + switch s := v.(type) { + case string: + g.WriteString(s) + case *string: + g.WriteString(*s) + case bool: + fmt.Fprintf(g, "%t", s) + case *bool: + fmt.Fprintf(g, "%t", *s) + case int: + fmt.Fprintf(g, "%d", s) + case *int32: + fmt.Fprintf(g, "%d", *s) + case *int64: + fmt.Fprintf(g, "%d", *s) + case float64: + fmt.Fprintf(g, "%g", s) + case *float64: + fmt.Fprintf(g, "%g", *s) + default: + g.Fail(fmt.Sprintf("unknown type in printer: %T", v)) + } + } + g.WriteByte('\n') +} + +// addInitf stores the given statement to be printed inside the file's init function. +// The statement is given as a format specifier and arguments. +func (g *Generator) addInitf(stmt string, a ...interface{}) { + g.init = append(g.init, fmt.Sprintf(stmt, a...)) +} + +// In Indents the output one tab stop. +func (g *Generator) In() { g.indent += "\t" } + +// Out unindents the output one tab stop. +func (g *Generator) Out() { + if len(g.indent) > 0 { + g.indent = g.indent[1:] + } +} + +// GenerateAllFiles generates the output for all the files we're outputting. +func (g *Generator) GenerateAllFiles() { + // Initialize the plugins + for _, p := range plugins { + p.Init(g) + } + // Generate the output. The generator runs for every file, even the files + // that we don't generate output for, so that we can collate the full list + // of exported symbols to support public imports. + genFileMap := make(map[*FileDescriptor]bool, len(g.genFiles)) + for _, file := range g.genFiles { + genFileMap[file] = true + } + for _, file := range g.allFiles { + g.Reset() + g.writeOutput = genFileMap[file] + g.generate(file) + if !g.writeOutput { + continue + } + g.Response.File = append(g.Response.File, &plugin.CodeGeneratorResponse_File{ + Name: proto.String(file.goFileName()), + Content: proto.String(g.String()), + }) + } +} + +// Run all the plugins associated with the file. +func (g *Generator) runPlugins(file *FileDescriptor) { + for _, p := range plugins { + p.Generate(file) + } +} + +// FileOf return the FileDescriptor for this FileDescriptorProto. +func (g *Generator) FileOf(fd *descriptor.FileDescriptorProto) *FileDescriptor { + for _, file := range g.allFiles { + if file.FileDescriptorProto == fd { + return file + } + } + g.Fail("could not find file in table:", fd.GetName()) + return nil +} + +// Fill the response protocol buffer with the generated output for all the files we're +// supposed to generate. +func (g *Generator) generate(file *FileDescriptor) { + g.file = g.FileOf(file.FileDescriptorProto) + g.usedPackages = make(map[string]bool) + + if g.file.index == 0 { + // For one file in the package, assert version compatibility. + g.P("// This is a compile-time assertion to ensure that this generated file") + g.P("// is compatible with the proto package it is being compiled against.") + g.P("// A compilation error at this line likely means your copy of the") + g.P("// proto package needs to be updated.") + g.P("const _ = ", g.Pkg["proto"], ".ProtoPackageIsVersion", generatedCodeVersion, " // please upgrade the proto package") + g.P() + } + for _, td := range g.file.imp { + g.generateImported(td) + } + for _, enum := range g.file.enum { + g.generateEnum(enum) + } + for _, desc := range g.file.desc { + // Don't generate virtual messages for maps. + if desc.GetOptions().GetMapEntry() { + continue + } + g.generateMessage(desc) + } + for _, ext := range g.file.ext { + g.generateExtension(ext) + } + g.generateInitFunction() + + // Run the plugins before the imports so we know which imports are necessary. + g.runPlugins(file) + + g.generateFileDescriptor(file) + + // Generate header and imports last, though they appear first in the output. + rem := g.Buffer + g.Buffer = new(bytes.Buffer) + g.generateHeader() + g.generateImports() + if !g.writeOutput { + return + } + g.Write(rem.Bytes()) + + // Reformat generated code. + fset := token.NewFileSet() + raw := g.Bytes() + ast, err := parser.ParseFile(fset, "", g, parser.ParseComments) + if err != nil { + // Print out the bad code with line numbers. + // This should never happen in practice, but it can while changing generated code, + // so consider this a debugging aid. + var src bytes.Buffer + s := bufio.NewScanner(bytes.NewReader(raw)) + for line := 1; s.Scan(); line++ { + fmt.Fprintf(&src, "%5d\t%s\n", line, s.Bytes()) + } + g.Fail("bad Go source code was generated:", err.Error(), "\n"+src.String()) + } + g.Reset() + err = (&printer.Config{Mode: printer.TabIndent | printer.UseSpaces, Tabwidth: 8}).Fprint(g, fset, ast) + if err != nil { + g.Fail("generated Go source code could not be reformatted:", err.Error()) + } +} + +// Generate the header, including package definition +func (g *Generator) generateHeader() { + g.P("// Code generated by protoc-gen-go. DO NOT EDIT.") + g.P("// source: ", g.file.Name) + g.P() + + name := g.file.PackageName() + + if g.file.index == 0 { + // Generate package docs for the first file in the package. + g.P("/*") + g.P("Package ", name, " is a generated protocol buffer package.") + g.P() + if loc, ok := g.file.comments[strconv.Itoa(packagePath)]; ok { + // not using g.PrintComments because this is a /* */ comment block. + text := strings.TrimSuffix(loc.GetLeadingComments(), "\n") + for _, line := range strings.Split(text, "\n") { + line = strings.TrimPrefix(line, " ") + // ensure we don't escape from the block comment + line = strings.Replace(line, "*/", "* /", -1) + g.P(line) + } + g.P() + } + var topMsgs []string + g.P("It is generated from these files:") + for _, f := range g.genFiles { + g.P("\t", f.Name) + for _, msg := range f.desc { + if msg.parent != nil { + continue + } + topMsgs = append(topMsgs, CamelCaseSlice(msg.TypeName())) + } + } + g.P() + g.P("It has these top-level messages:") + for _, msg := range topMsgs { + g.P("\t", msg) + } + g.P("*/") + } + + g.P("package ", name) + g.P() +} + +// PrintComments prints any comments from the source .proto file. +// The path is a comma-separated list of integers. +// It returns an indication of whether any comments were printed. +// See descriptor.proto for its format. +func (g *Generator) PrintComments(path string) bool { + if !g.writeOutput { + return false + } + if loc, ok := g.file.comments[path]; ok { + text := strings.TrimSuffix(loc.GetLeadingComments(), "\n") + for _, line := range strings.Split(text, "\n") { + g.P("// ", strings.TrimPrefix(line, " ")) + } + return true + } + return false +} + +func (g *Generator) fileByName(filename string) *FileDescriptor { + return g.allFilesByName[filename] +} + +// weak returns whether the ith import of the current file is a weak import. +func (g *Generator) weak(i int32) bool { + for _, j := range g.file.WeakDependency { + if j == i { + return true + } + } + return false +} + +// Generate the imports +func (g *Generator) generateImports() { + // We almost always need a proto import. Rather than computing when we + // do, which is tricky when there's a plugin, just import it and + // reference it later. The same argument applies to the fmt and math packages. + g.P("import " + g.Pkg["proto"] + " " + strconv.Quote(g.ImportPrefix+"github.com/golang/protobuf/proto")) + g.P("import " + g.Pkg["fmt"] + ` "fmt"`) + g.P("import " + g.Pkg["math"] + ` "math"`) + for i, s := range g.file.Dependency { + fd := g.fileByName(s) + // Do not import our own package. + if fd.PackageName() == g.packageName { + continue + } + filename := fd.goFileName() + // By default, import path is the dirname of the Go filename. + importPath := path.Dir(filename) + if substitution, ok := g.ImportMap[s]; ok { + importPath = substitution + } + importPath = g.ImportPrefix + importPath + // Skip weak imports. + if g.weak(int32(i)) { + g.P("// skipping weak import ", fd.PackageName(), " ", strconv.Quote(importPath)) + continue + } + // We need to import all the dependencies, even if we don't reference them, + // because other code and tools depend on having the full transitive closure + // of protocol buffer types in the binary. + pname := fd.PackageName() + if _, ok := g.usedPackages[pname]; !ok { + pname = "_" + } + g.P("import ", pname, " ", strconv.Quote(importPath)) + } + g.P() + // TODO: may need to worry about uniqueness across plugins + for _, p := range plugins { + p.GenerateImports(g.file) + g.P() + } + g.P("// Reference imports to suppress errors if they are not otherwise used.") + g.P("var _ = ", g.Pkg["proto"], ".Marshal") + g.P("var _ = ", g.Pkg["fmt"], ".Errorf") + g.P("var _ = ", g.Pkg["math"], ".Inf") + g.P() +} + +func (g *Generator) generateImported(id *ImportedDescriptor) { + // Don't generate public import symbols for files that we are generating + // code for, since those symbols will already be in this package. + // We can't simply avoid creating the ImportedDescriptor objects, + // because g.genFiles isn't populated at that stage. + tn := id.TypeName() + sn := tn[len(tn)-1] + df := g.FileOf(id.o.File()) + filename := *df.Name + for _, fd := range g.genFiles { + if *fd.Name == filename { + g.P("// Ignoring public import of ", sn, " from ", filename) + g.P() + return + } + } + g.P("// ", sn, " from public import ", filename) + g.usedPackages[df.PackageName()] = true + + for _, sym := range df.exported[id.o] { + sym.GenerateAlias(g, df.PackageName()) + } + + g.P() +} + +// Generate the enum definitions for this EnumDescriptor. +func (g *Generator) generateEnum(enum *EnumDescriptor) { + // The full type name + typeName := enum.TypeName() + // The full type name, CamelCased. + ccTypeName := CamelCaseSlice(typeName) + ccPrefix := enum.prefix() + + g.PrintComments(enum.path) + g.P("type ", ccTypeName, " int32") + g.file.addExport(enum, enumSymbol{ccTypeName, enum.proto3()}) + g.P("const (") + g.In() + for i, e := range enum.Value { + g.PrintComments(fmt.Sprintf("%s,%d,%d", enum.path, enumValuePath, i)) + + name := ccPrefix + *e.Name + g.P(name, " ", ccTypeName, " = ", e.Number) + g.file.addExport(enum, constOrVarSymbol{name, "const", ccTypeName}) + } + g.Out() + g.P(")") + g.P("var ", ccTypeName, "_name = map[int32]string{") + g.In() + generated := make(map[int32]bool) // avoid duplicate values + for _, e := range enum.Value { + duplicate := "" + if _, present := generated[*e.Number]; present { + duplicate = "// Duplicate value: " + } + g.P(duplicate, e.Number, ": ", strconv.Quote(*e.Name), ",") + generated[*e.Number] = true + } + g.Out() + g.P("}") + g.P("var ", ccTypeName, "_value = map[string]int32{") + g.In() + for _, e := range enum.Value { + g.P(strconv.Quote(*e.Name), ": ", e.Number, ",") + } + g.Out() + g.P("}") + + if !enum.proto3() { + g.P("func (x ", ccTypeName, ") Enum() *", ccTypeName, " {") + g.In() + g.P("p := new(", ccTypeName, ")") + g.P("*p = x") + g.P("return p") + g.Out() + g.P("}") + } + + g.P("func (x ", ccTypeName, ") String() string {") + g.In() + g.P("return ", g.Pkg["proto"], ".EnumName(", ccTypeName, "_name, int32(x))") + g.Out() + g.P("}") + + if !enum.proto3() { + g.P("func (x *", ccTypeName, ") UnmarshalJSON(data []byte) error {") + g.In() + g.P("value, err := ", g.Pkg["proto"], ".UnmarshalJSONEnum(", ccTypeName, `_value, data, "`, ccTypeName, `")`) + g.P("if err != nil {") + g.In() + g.P("return err") + g.Out() + g.P("}") + g.P("*x = ", ccTypeName, "(value)") + g.P("return nil") + g.Out() + g.P("}") + } + + var indexes []string + for m := enum.parent; m != nil; m = m.parent { + // XXX: skip groups? + indexes = append([]string{strconv.Itoa(m.index)}, indexes...) + } + indexes = append(indexes, strconv.Itoa(enum.index)) + g.P("func (", ccTypeName, ") EnumDescriptor() ([]byte, []int) { return ", g.file.VarName(), ", []int{", strings.Join(indexes, ", "), "} }") + if enum.file.GetPackage() == "google.protobuf" && enum.GetName() == "NullValue" { + g.P("func (", ccTypeName, `) XXX_WellKnownType() string { return "`, enum.GetName(), `" }`) + } + + g.P() +} + +// The tag is a string like "varint,2,opt,name=fieldname,def=7" that +// identifies details of the field for the protocol buffer marshaling and unmarshaling +// code. The fields are: +// wire encoding +// protocol tag number +// opt,req,rep for optional, required, or repeated +// packed whether the encoding is "packed" (optional; repeated primitives only) +// name= the original declared name +// enum= the name of the enum type if it is an enum-typed field. +// proto3 if this field is in a proto3 message +// def= string representation of the default value, if any. +// The default value must be in a representation that can be used at run-time +// to generate the default value. Thus bools become 0 and 1, for instance. +func (g *Generator) goTag(message *Descriptor, field *descriptor.FieldDescriptorProto, wiretype string) string { + optrepreq := "" + switch { + case isOptional(field): + optrepreq = "opt" + case isRequired(field): + optrepreq = "req" + case isRepeated(field): + optrepreq = "rep" + } + var defaultValue string + if dv := field.DefaultValue; dv != nil { // set means an explicit default + defaultValue = *dv + // Some types need tweaking. + switch *field.Type { + case descriptor.FieldDescriptorProto_TYPE_BOOL: + if defaultValue == "true" { + defaultValue = "1" + } else { + defaultValue = "0" + } + case descriptor.FieldDescriptorProto_TYPE_STRING, + descriptor.FieldDescriptorProto_TYPE_BYTES: + // Nothing to do. Quoting is done for the whole tag. + case descriptor.FieldDescriptorProto_TYPE_ENUM: + // For enums we need to provide the integer constant. + obj := g.ObjectNamed(field.GetTypeName()) + if id, ok := obj.(*ImportedDescriptor); ok { + // It is an enum that was publicly imported. + // We need the underlying type. + obj = id.o + } + enum, ok := obj.(*EnumDescriptor) + if !ok { + log.Printf("obj is a %T", obj) + if id, ok := obj.(*ImportedDescriptor); ok { + log.Printf("id.o is a %T", id.o) + } + g.Fail("unknown enum type", CamelCaseSlice(obj.TypeName())) + } + defaultValue = enum.integerValueAsString(defaultValue) + } + defaultValue = ",def=" + defaultValue + } + enum := "" + if *field.Type == descriptor.FieldDescriptorProto_TYPE_ENUM { + // We avoid using obj.PackageName(), because we want to use the + // original (proto-world) package name. + obj := g.ObjectNamed(field.GetTypeName()) + if id, ok := obj.(*ImportedDescriptor); ok { + obj = id.o + } + enum = ",enum=" + if pkg := obj.File().GetPackage(); pkg != "" { + enum += pkg + "." + } + enum += CamelCaseSlice(obj.TypeName()) + } + packed := "" + if (field.Options != nil && field.Options.GetPacked()) || + // Per https://developers.google.com/protocol-buffers/docs/proto3#simple: + // "In proto3, repeated fields of scalar numeric types use packed encoding by default." + (message.proto3() && (field.Options == nil || field.Options.Packed == nil) && + isRepeated(field) && isScalar(field)) { + packed = ",packed" + } + fieldName := field.GetName() + name := fieldName + if *field.Type == descriptor.FieldDescriptorProto_TYPE_GROUP { + // We must use the type name for groups instead of + // the field name to preserve capitalization. + // type_name in FieldDescriptorProto is fully-qualified, + // but we only want the local part. + name = *field.TypeName + if i := strings.LastIndex(name, "."); i >= 0 { + name = name[i+1:] + } + } + if json := field.GetJsonName(); json != "" && json != name { + // TODO: escaping might be needed, in which case + // perhaps this should be in its own "json" tag. + name += ",json=" + json + } + name = ",name=" + name + if message.proto3() { + // We only need the extra tag for []byte fields; + // no need to add noise for the others. + if *field.Type == descriptor.FieldDescriptorProto_TYPE_BYTES { + name += ",proto3" + } + + } + oneof := "" + if field.OneofIndex != nil { + oneof = ",oneof" + } + return strconv.Quote(fmt.Sprintf("%s,%d,%s%s%s%s%s%s", + wiretype, + field.GetNumber(), + optrepreq, + packed, + name, + enum, + oneof, + defaultValue)) +} + +func needsStar(typ descriptor.FieldDescriptorProto_Type) bool { + switch typ { + case descriptor.FieldDescriptorProto_TYPE_GROUP: + return false + case descriptor.FieldDescriptorProto_TYPE_MESSAGE: + return false + case descriptor.FieldDescriptorProto_TYPE_BYTES: + return false + } + return true +} + +// TypeName is the printed name appropriate for an item. If the object is in the current file, +// TypeName drops the package name and underscores the rest. +// Otherwise the object is from another package; and the result is the underscored +// package name followed by the item name. +// The result always has an initial capital. +func (g *Generator) TypeName(obj Object) string { + return g.DefaultPackageName(obj) + CamelCaseSlice(obj.TypeName()) +} + +// TypeNameWithPackage is like TypeName, but always includes the package +// name even if the object is in our own package. +func (g *Generator) TypeNameWithPackage(obj Object) string { + return obj.PackageName() + CamelCaseSlice(obj.TypeName()) +} + +// GoType returns a string representing the type name, and the wire type +func (g *Generator) GoType(message *Descriptor, field *descriptor.FieldDescriptorProto) (typ string, wire string) { + // TODO: Options. + switch *field.Type { + case descriptor.FieldDescriptorProto_TYPE_DOUBLE: + typ, wire = "float64", "fixed64" + case descriptor.FieldDescriptorProto_TYPE_FLOAT: + typ, wire = "float32", "fixed32" + case descriptor.FieldDescriptorProto_TYPE_INT64: + typ, wire = "int64", "varint" + case descriptor.FieldDescriptorProto_TYPE_UINT64: + typ, wire = "uint64", "varint" + case descriptor.FieldDescriptorProto_TYPE_INT32: + typ, wire = "int32", "varint" + case descriptor.FieldDescriptorProto_TYPE_UINT32: + typ, wire = "uint32", "varint" + case descriptor.FieldDescriptorProto_TYPE_FIXED64: + typ, wire = "uint64", "fixed64" + case descriptor.FieldDescriptorProto_TYPE_FIXED32: + typ, wire = "uint32", "fixed32" + case descriptor.FieldDescriptorProto_TYPE_BOOL: + typ, wire = "bool", "varint" + case descriptor.FieldDescriptorProto_TYPE_STRING: + typ, wire = "string", "bytes" + case descriptor.FieldDescriptorProto_TYPE_GROUP: + desc := g.ObjectNamed(field.GetTypeName()) + typ, wire = "*"+g.TypeName(desc), "group" + case descriptor.FieldDescriptorProto_TYPE_MESSAGE: + desc := g.ObjectNamed(field.GetTypeName()) + typ, wire = "*"+g.TypeName(desc), "bytes" + case descriptor.FieldDescriptorProto_TYPE_BYTES: + typ, wire = "[]byte", "bytes" + case descriptor.FieldDescriptorProto_TYPE_ENUM: + desc := g.ObjectNamed(field.GetTypeName()) + typ, wire = g.TypeName(desc), "varint" + case descriptor.FieldDescriptorProto_TYPE_SFIXED32: + typ, wire = "int32", "fixed32" + case descriptor.FieldDescriptorProto_TYPE_SFIXED64: + typ, wire = "int64", "fixed64" + case descriptor.FieldDescriptorProto_TYPE_SINT32: + typ, wire = "int32", "zigzag32" + case descriptor.FieldDescriptorProto_TYPE_SINT64: + typ, wire = "int64", "zigzag64" + default: + g.Fail("unknown type for", field.GetName()) + } + if isRepeated(field) { + typ = "[]" + typ + } else if message != nil && message.proto3() { + return + } else if field.OneofIndex != nil && message != nil { + return + } else if needsStar(*field.Type) { + typ = "*" + typ + } + return +} + +func (g *Generator) RecordTypeUse(t string) { + if obj, ok := g.typeNameToObject[t]; ok { + // Call ObjectNamed to get the true object to record the use. + obj = g.ObjectNamed(t) + g.usedPackages[obj.PackageName()] = true + } +} + +// Method names that may be generated. Fields with these names get an +// underscore appended. Any change to this set is a potential incompatible +// API change because it changes generated field names. +var methodNames = [...]string{ + "Reset", + "String", + "ProtoMessage", + "Marshal", + "Unmarshal", + "ExtensionRangeArray", + "ExtensionMap", + "Descriptor", +} + +// Names of messages in the `google.protobuf` package for which +// we will generate XXX_WellKnownType methods. +var wellKnownTypes = map[string]bool{ + "Any": true, + "Duration": true, + "Empty": true, + "Struct": true, + "Timestamp": true, + + "Value": true, + "ListValue": true, + "DoubleValue": true, + "FloatValue": true, + "Int64Value": true, + "UInt64Value": true, + "Int32Value": true, + "UInt32Value": true, + "BoolValue": true, + "StringValue": true, + "BytesValue": true, +} + +// Generate the type and default constant definitions for this Descriptor. +func (g *Generator) generateMessage(message *Descriptor) { + // The full type name + typeName := message.TypeName() + // The full type name, CamelCased. + ccTypeName := CamelCaseSlice(typeName) + + usedNames := make(map[string]bool) + for _, n := range methodNames { + usedNames[n] = true + } + fieldNames := make(map[*descriptor.FieldDescriptorProto]string) + fieldGetterNames := make(map[*descriptor.FieldDescriptorProto]string) + fieldTypes := make(map[*descriptor.FieldDescriptorProto]string) + mapFieldTypes := make(map[*descriptor.FieldDescriptorProto]string) + + oneofFieldName := make(map[int32]string) // indexed by oneof_index field of FieldDescriptorProto + oneofDisc := make(map[int32]string) // name of discriminator method + oneofTypeName := make(map[*descriptor.FieldDescriptorProto]string) // without star + oneofInsertPoints := make(map[int32]int) // oneof_index => offset of g.Buffer + + g.PrintComments(message.path) + g.P("type ", ccTypeName, " struct {") + g.In() + + // allocNames finds a conflict-free variation of the given strings, + // consistently mutating their suffixes. + // It returns the same number of strings. + allocNames := func(ns ...string) []string { + Loop: + for { + for _, n := range ns { + if usedNames[n] { + for i := range ns { + ns[i] += "_" + } + continue Loop + } + } + for _, n := range ns { + usedNames[n] = true + } + return ns + } + } + + for i, field := range message.Field { + // Allocate the getter and the field at the same time so name + // collisions create field/method consistent names. + // TODO: This allocation occurs based on the order of the fields + // in the proto file, meaning that a change in the field + // ordering can change generated Method/Field names. + base := CamelCase(*field.Name) + ns := allocNames(base, "Get"+base) + fieldName, fieldGetterName := ns[0], ns[1] + typename, wiretype := g.GoType(message, field) + jsonName := *field.Name + tag := fmt.Sprintf("protobuf:%s json:%q", g.goTag(message, field, wiretype), jsonName+",omitempty") + + fieldNames[field] = fieldName + fieldGetterNames[field] = fieldGetterName + + oneof := field.OneofIndex != nil + if oneof && oneofFieldName[*field.OneofIndex] == "" { + odp := message.OneofDecl[int(*field.OneofIndex)] + fname := allocNames(CamelCase(odp.GetName()))[0] + + // This is the first field of a oneof we haven't seen before. + // Generate the union field. + com := g.PrintComments(fmt.Sprintf("%s,%d,%d", message.path, messageOneofPath, *field.OneofIndex)) + if com { + g.P("//") + } + g.P("// Types that are valid to be assigned to ", fname, ":") + // Generate the rest of this comment later, + // when we've computed any disambiguation. + oneofInsertPoints[*field.OneofIndex] = g.Buffer.Len() + + dname := "is" + ccTypeName + "_" + fname + oneofFieldName[*field.OneofIndex] = fname + oneofDisc[*field.OneofIndex] = dname + tag := `protobuf_oneof:"` + odp.GetName() + `"` + g.P(fname, " ", dname, " `", tag, "`") + } + + if *field.Type == descriptor.FieldDescriptorProto_TYPE_MESSAGE { + desc := g.ObjectNamed(field.GetTypeName()) + if d, ok := desc.(*Descriptor); ok && d.GetOptions().GetMapEntry() { + // Figure out the Go types and tags for the key and value types. + keyField, valField := d.Field[0], d.Field[1] + keyType, keyWire := g.GoType(d, keyField) + valType, valWire := g.GoType(d, valField) + keyTag, valTag := g.goTag(d, keyField, keyWire), g.goTag(d, valField, valWire) + + // We don't use stars, except for message-typed values. + // Message and enum types are the only two possibly foreign types used in maps, + // so record their use. They are not permitted as map keys. + keyType = strings.TrimPrefix(keyType, "*") + switch *valField.Type { + case descriptor.FieldDescriptorProto_TYPE_ENUM: + valType = strings.TrimPrefix(valType, "*") + g.RecordTypeUse(valField.GetTypeName()) + case descriptor.FieldDescriptorProto_TYPE_MESSAGE: + g.RecordTypeUse(valField.GetTypeName()) + default: + valType = strings.TrimPrefix(valType, "*") + } + + typename = fmt.Sprintf("map[%s]%s", keyType, valType) + mapFieldTypes[field] = typename // record for the getter generation + + tag += fmt.Sprintf(" protobuf_key:%s protobuf_val:%s", keyTag, valTag) + } + } + + fieldTypes[field] = typename + + if oneof { + tname := ccTypeName + "_" + fieldName + // It is possible for this to collide with a message or enum + // nested in this message. Check for collisions. + for { + ok := true + for _, desc := range message.nested { + if CamelCaseSlice(desc.TypeName()) == tname { + ok = false + break + } + } + for _, enum := range message.enums { + if CamelCaseSlice(enum.TypeName()) == tname { + ok = false + break + } + } + if !ok { + tname += "_" + continue + } + break + } + + oneofTypeName[field] = tname + continue + } + + g.PrintComments(fmt.Sprintf("%s,%d,%d", message.path, messageFieldPath, i)) + g.P(fieldName, "\t", typename, "\t`", tag, "`") + g.RecordTypeUse(field.GetTypeName()) + } + if len(message.ExtensionRange) > 0 { + g.P(g.Pkg["proto"], ".XXX_InternalExtensions `json:\"-\"`") + } + if !message.proto3() { + g.P("XXX_unrecognized\t[]byte `json:\"-\"`") + } + g.Out() + g.P("}") + + // Update g.Buffer to list valid oneof types. + // We do this down here, after we've disambiguated the oneof type names. + // We go in reverse order of insertion point to avoid invalidating offsets. + for oi := int32(len(message.OneofDecl)); oi >= 0; oi-- { + ip := oneofInsertPoints[oi] + all := g.Buffer.Bytes() + rem := all[ip:] + g.Buffer = bytes.NewBuffer(all[:ip:ip]) // set cap so we don't scribble on rem + for _, field := range message.Field { + if field.OneofIndex == nil || *field.OneofIndex != oi { + continue + } + g.P("//\t*", oneofTypeName[field]) + } + g.Buffer.Write(rem) + } + + // Reset, String and ProtoMessage methods. + g.P("func (m *", ccTypeName, ") Reset() { *m = ", ccTypeName, "{} }") + g.P("func (m *", ccTypeName, ") String() string { return ", g.Pkg["proto"], ".CompactTextString(m) }") + g.P("func (*", ccTypeName, ") ProtoMessage() {}") + var indexes []string + for m := message; m != nil; m = m.parent { + indexes = append([]string{strconv.Itoa(m.index)}, indexes...) + } + g.P("func (*", ccTypeName, ") Descriptor() ([]byte, []int) { return ", g.file.VarName(), ", []int{", strings.Join(indexes, ", "), "} }") + // TODO: Revisit the decision to use a XXX_WellKnownType method + // if we change proto.MessageName to work with multiple equivalents. + if message.file.GetPackage() == "google.protobuf" && wellKnownTypes[message.GetName()] { + g.P("func (*", ccTypeName, `) XXX_WellKnownType() string { return "`, message.GetName(), `" }`) + } + + // Extension support methods + var hasExtensions, isMessageSet bool + if len(message.ExtensionRange) > 0 { + hasExtensions = true + // message_set_wire_format only makes sense when extensions are defined. + if opts := message.Options; opts != nil && opts.GetMessageSetWireFormat() { + isMessageSet = true + g.P() + g.P("func (m *", ccTypeName, ") Marshal() ([]byte, error) {") + g.In() + g.P("return ", g.Pkg["proto"], ".MarshalMessageSet(&m.XXX_InternalExtensions)") + g.Out() + g.P("}") + g.P("func (m *", ccTypeName, ") Unmarshal(buf []byte) error {") + g.In() + g.P("return ", g.Pkg["proto"], ".UnmarshalMessageSet(buf, &m.XXX_InternalExtensions)") + g.Out() + g.P("}") + g.P("func (m *", ccTypeName, ") MarshalJSON() ([]byte, error) {") + g.In() + g.P("return ", g.Pkg["proto"], ".MarshalMessageSetJSON(&m.XXX_InternalExtensions)") + g.Out() + g.P("}") + g.P("func (m *", ccTypeName, ") UnmarshalJSON(buf []byte) error {") + g.In() + g.P("return ", g.Pkg["proto"], ".UnmarshalMessageSetJSON(buf, &m.XXX_InternalExtensions)") + g.Out() + g.P("}") + g.P("// ensure ", ccTypeName, " satisfies proto.Marshaler and proto.Unmarshaler") + g.P("var _ ", g.Pkg["proto"], ".Marshaler = (*", ccTypeName, ")(nil)") + g.P("var _ ", g.Pkg["proto"], ".Unmarshaler = (*", ccTypeName, ")(nil)") + } + + g.P() + g.P("var extRange_", ccTypeName, " = []", g.Pkg["proto"], ".ExtensionRange{") + g.In() + for _, r := range message.ExtensionRange { + end := fmt.Sprint(*r.End - 1) // make range inclusive on both ends + g.P("{", r.Start, ", ", end, "},") + } + g.Out() + g.P("}") + g.P("func (*", ccTypeName, ") ExtensionRangeArray() []", g.Pkg["proto"], ".ExtensionRange {") + g.In() + g.P("return extRange_", ccTypeName) + g.Out() + g.P("}") + } + + // Default constants + defNames := make(map[*descriptor.FieldDescriptorProto]string) + for _, field := range message.Field { + def := field.GetDefaultValue() + if def == "" { + continue + } + fieldname := "Default_" + ccTypeName + "_" + CamelCase(*field.Name) + defNames[field] = fieldname + typename, _ := g.GoType(message, field) + if typename[0] == '*' { + typename = typename[1:] + } + kind := "const " + switch { + case typename == "bool": + case typename == "string": + def = strconv.Quote(def) + case typename == "[]byte": + def = "[]byte(" + strconv.Quote(unescape(def)) + ")" + kind = "var " + case def == "inf", def == "-inf", def == "nan": + // These names are known to, and defined by, the protocol language. + switch def { + case "inf": + def = "math.Inf(1)" + case "-inf": + def = "math.Inf(-1)" + case "nan": + def = "math.NaN()" + } + if *field.Type == descriptor.FieldDescriptorProto_TYPE_FLOAT { + def = "float32(" + def + ")" + } + kind = "var " + case *field.Type == descriptor.FieldDescriptorProto_TYPE_ENUM: + // Must be an enum. Need to construct the prefixed name. + obj := g.ObjectNamed(field.GetTypeName()) + var enum *EnumDescriptor + if id, ok := obj.(*ImportedDescriptor); ok { + // The enum type has been publicly imported. + enum, _ = id.o.(*EnumDescriptor) + } else { + enum, _ = obj.(*EnumDescriptor) + } + if enum == nil { + log.Printf("don't know how to generate constant for %s", fieldname) + continue + } + def = g.DefaultPackageName(obj) + enum.prefix() + def + } + g.P(kind, fieldname, " ", typename, " = ", def) + g.file.addExport(message, constOrVarSymbol{fieldname, kind, ""}) + } + g.P() + + // Oneof per-field types, discriminants and getters. + // + // Generate unexported named types for the discriminant interfaces. + // We shouldn't have to do this, but there was (~19 Aug 2015) a compiler/linker bug + // that was triggered by using anonymous interfaces here. + // TODO: Revisit this and consider reverting back to anonymous interfaces. + for oi := range message.OneofDecl { + dname := oneofDisc[int32(oi)] + g.P("type ", dname, " interface { ", dname, "() }") + } + g.P() + for _, field := range message.Field { + if field.OneofIndex == nil { + continue + } + _, wiretype := g.GoType(message, field) + tag := "protobuf:" + g.goTag(message, field, wiretype) + g.P("type ", oneofTypeName[field], " struct{ ", fieldNames[field], " ", fieldTypes[field], " `", tag, "` }") + g.RecordTypeUse(field.GetTypeName()) + } + g.P() + for _, field := range message.Field { + if field.OneofIndex == nil { + continue + } + g.P("func (*", oneofTypeName[field], ") ", oneofDisc[*field.OneofIndex], "() {}") + } + g.P() + for oi := range message.OneofDecl { + fname := oneofFieldName[int32(oi)] + g.P("func (m *", ccTypeName, ") Get", fname, "() ", oneofDisc[int32(oi)], " {") + g.P("if m != nil { return m.", fname, " }") + g.P("return nil") + g.P("}") + } + g.P() + + // Field getters + var getters []getterSymbol + for _, field := range message.Field { + oneof := field.OneofIndex != nil + + fname := fieldNames[field] + typename, _ := g.GoType(message, field) + if t, ok := mapFieldTypes[field]; ok { + typename = t + } + mname := fieldGetterNames[field] + star := "" + if needsStar(*field.Type) && typename[0] == '*' { + typename = typename[1:] + star = "*" + } + + // Only export getter symbols for basic types, + // and for messages and enums in the same package. + // Groups are not exported. + // Foreign types can't be hoisted through a public import because + // the importer may not already be importing the defining .proto. + // As an example, imagine we have an import tree like this: + // A.proto -> B.proto -> C.proto + // If A publicly imports B, we need to generate the getters from B in A's output, + // but if one such getter returns something from C then we cannot do that + // because A is not importing C already. + var getter, genType bool + switch *field.Type { + case descriptor.FieldDescriptorProto_TYPE_GROUP: + getter = false + case descriptor.FieldDescriptorProto_TYPE_MESSAGE, descriptor.FieldDescriptorProto_TYPE_ENUM: + // Only export getter if its return type is in this package. + getter = g.ObjectNamed(field.GetTypeName()).PackageName() == message.PackageName() + genType = true + default: + getter = true + } + if getter { + getters = append(getters, getterSymbol{ + name: mname, + typ: typename, + typeName: field.GetTypeName(), + genType: genType, + }) + } + + g.P("func (m *", ccTypeName, ") "+mname+"() "+typename+" {") + g.In() + def, hasDef := defNames[field] + typeDefaultIsNil := false // whether this field type's default value is a literal nil unless specified + switch *field.Type { + case descriptor.FieldDescriptorProto_TYPE_BYTES: + typeDefaultIsNil = !hasDef + case descriptor.FieldDescriptorProto_TYPE_GROUP, descriptor.FieldDescriptorProto_TYPE_MESSAGE: + typeDefaultIsNil = true + } + if isRepeated(field) { + typeDefaultIsNil = true + } + if typeDefaultIsNil && !oneof { + // A bytes field with no explicit default needs less generated code, + // as does a message or group field, or a repeated field. + g.P("if m != nil {") + g.In() + g.P("return m." + fname) + g.Out() + g.P("}") + g.P("return nil") + g.Out() + g.P("}") + g.P() + continue + } + if !oneof { + if message.proto3() { + g.P("if m != nil {") + } else { + g.P("if m != nil && m." + fname + " != nil {") + } + g.In() + g.P("return " + star + "m." + fname) + g.Out() + g.P("}") + } else { + uname := oneofFieldName[*field.OneofIndex] + tname := oneofTypeName[field] + g.P("if x, ok := m.Get", uname, "().(*", tname, "); ok {") + g.P("return x.", fname) + g.P("}") + } + if hasDef { + if *field.Type != descriptor.FieldDescriptorProto_TYPE_BYTES { + g.P("return " + def) + } else { + // The default is a []byte var. + // Make a copy when returning it to be safe. + g.P("return append([]byte(nil), ", def, "...)") + } + } else { + switch *field.Type { + case descriptor.FieldDescriptorProto_TYPE_BOOL: + g.P("return false") + case descriptor.FieldDescriptorProto_TYPE_STRING: + g.P(`return ""`) + case descriptor.FieldDescriptorProto_TYPE_GROUP, + descriptor.FieldDescriptorProto_TYPE_MESSAGE, + descriptor.FieldDescriptorProto_TYPE_BYTES: + // This is only possible for oneof fields. + g.P("return nil") + case descriptor.FieldDescriptorProto_TYPE_ENUM: + // The default default for an enum is the first value in the enum, + // not zero. + obj := g.ObjectNamed(field.GetTypeName()) + var enum *EnumDescriptor + if id, ok := obj.(*ImportedDescriptor); ok { + // The enum type has been publicly imported. + enum, _ = id.o.(*EnumDescriptor) + } else { + enum, _ = obj.(*EnumDescriptor) + } + if enum == nil { + log.Printf("don't know how to generate getter for %s", field.GetName()) + continue + } + if len(enum.Value) == 0 { + g.P("return 0 // empty enum") + } else { + first := enum.Value[0].GetName() + g.P("return ", g.DefaultPackageName(obj)+enum.prefix()+first) + } + default: + g.P("return 0") + } + } + g.Out() + g.P("}") + g.P() + } + + if !message.group { + ms := &messageSymbol{ + sym: ccTypeName, + hasExtensions: hasExtensions, + isMessageSet: isMessageSet, + hasOneof: len(message.OneofDecl) > 0, + getters: getters, + } + g.file.addExport(message, ms) + } + + // Oneof functions + if len(message.OneofDecl) > 0 { + fieldWire := make(map[*descriptor.FieldDescriptorProto]string) + + // method + enc := "_" + ccTypeName + "_OneofMarshaler" + dec := "_" + ccTypeName + "_OneofUnmarshaler" + size := "_" + ccTypeName + "_OneofSizer" + encSig := "(msg " + g.Pkg["proto"] + ".Message, b *" + g.Pkg["proto"] + ".Buffer) error" + decSig := "(msg " + g.Pkg["proto"] + ".Message, tag, wire int, b *" + g.Pkg["proto"] + ".Buffer) (bool, error)" + sizeSig := "(msg " + g.Pkg["proto"] + ".Message) (n int)" + + g.P("// XXX_OneofFuncs is for the internal use of the proto package.") + g.P("func (*", ccTypeName, ") XXX_OneofFuncs() (func", encSig, ", func", decSig, ", func", sizeSig, ", []interface{}) {") + g.P("return ", enc, ", ", dec, ", ", size, ", []interface{}{") + for _, field := range message.Field { + if field.OneofIndex == nil { + continue + } + g.P("(*", oneofTypeName[field], ")(nil),") + } + g.P("}") + g.P("}") + g.P() + + // marshaler + g.P("func ", enc, encSig, " {") + g.P("m := msg.(*", ccTypeName, ")") + for oi, odp := range message.OneofDecl { + g.P("// ", odp.GetName()) + fname := oneofFieldName[int32(oi)] + g.P("switch x := m.", fname, ".(type) {") + for _, field := range message.Field { + if field.OneofIndex == nil || int(*field.OneofIndex) != oi { + continue + } + g.P("case *", oneofTypeName[field], ":") + var wire, pre, post string + val := "x." + fieldNames[field] // overridden for TYPE_BOOL + canFail := false // only TYPE_MESSAGE and TYPE_GROUP can fail + switch *field.Type { + case descriptor.FieldDescriptorProto_TYPE_DOUBLE: + wire = "WireFixed64" + pre = "b.EncodeFixed64(" + g.Pkg["math"] + ".Float64bits(" + post = "))" + case descriptor.FieldDescriptorProto_TYPE_FLOAT: + wire = "WireFixed32" + pre = "b.EncodeFixed32(uint64(" + g.Pkg["math"] + ".Float32bits(" + post = ")))" + case descriptor.FieldDescriptorProto_TYPE_INT64, + descriptor.FieldDescriptorProto_TYPE_UINT64: + wire = "WireVarint" + pre, post = "b.EncodeVarint(uint64(", "))" + case descriptor.FieldDescriptorProto_TYPE_INT32, + descriptor.FieldDescriptorProto_TYPE_UINT32, + descriptor.FieldDescriptorProto_TYPE_ENUM: + wire = "WireVarint" + pre, post = "b.EncodeVarint(uint64(", "))" + case descriptor.FieldDescriptorProto_TYPE_FIXED64, + descriptor.FieldDescriptorProto_TYPE_SFIXED64: + wire = "WireFixed64" + pre, post = "b.EncodeFixed64(uint64(", "))" + case descriptor.FieldDescriptorProto_TYPE_FIXED32, + descriptor.FieldDescriptorProto_TYPE_SFIXED32: + wire = "WireFixed32" + pre, post = "b.EncodeFixed32(uint64(", "))" + case descriptor.FieldDescriptorProto_TYPE_BOOL: + // bool needs special handling. + g.P("t := uint64(0)") + g.P("if ", val, " { t = 1 }") + val = "t" + wire = "WireVarint" + pre, post = "b.EncodeVarint(", ")" + case descriptor.FieldDescriptorProto_TYPE_STRING: + wire = "WireBytes" + pre, post = "b.EncodeStringBytes(", ")" + case descriptor.FieldDescriptorProto_TYPE_GROUP: + wire = "WireStartGroup" + pre, post = "b.Marshal(", ")" + canFail = true + case descriptor.FieldDescriptorProto_TYPE_MESSAGE: + wire = "WireBytes" + pre, post = "b.EncodeMessage(", ")" + canFail = true + case descriptor.FieldDescriptorProto_TYPE_BYTES: + wire = "WireBytes" + pre, post = "b.EncodeRawBytes(", ")" + case descriptor.FieldDescriptorProto_TYPE_SINT32: + wire = "WireVarint" + pre, post = "b.EncodeZigzag32(uint64(", "))" + case descriptor.FieldDescriptorProto_TYPE_SINT64: + wire = "WireVarint" + pre, post = "b.EncodeZigzag64(uint64(", "))" + default: + g.Fail("unhandled oneof field type ", field.Type.String()) + } + fieldWire[field] = wire + g.P("b.EncodeVarint(", field.Number, "<<3|", g.Pkg["proto"], ".", wire, ")") + if !canFail { + g.P(pre, val, post) + } else { + g.P("if err := ", pre, val, post, "; err != nil {") + g.P("return err") + g.P("}") + } + if *field.Type == descriptor.FieldDescriptorProto_TYPE_GROUP { + g.P("b.EncodeVarint(", field.Number, "<<3|", g.Pkg["proto"], ".WireEndGroup)") + } + } + g.P("case nil:") + g.P("default: return ", g.Pkg["fmt"], `.Errorf("`, ccTypeName, ".", fname, ` has unexpected type %T", x)`) + g.P("}") + } + g.P("return nil") + g.P("}") + g.P() + + // unmarshaler + g.P("func ", dec, decSig, " {") + g.P("m := msg.(*", ccTypeName, ")") + g.P("switch tag {") + for _, field := range message.Field { + if field.OneofIndex == nil { + continue + } + odp := message.OneofDecl[int(*field.OneofIndex)] + g.P("case ", field.Number, ": // ", odp.GetName(), ".", *field.Name) + g.P("if wire != ", g.Pkg["proto"], ".", fieldWire[field], " {") + g.P("return true, ", g.Pkg["proto"], ".ErrInternalBadWireType") + g.P("}") + lhs := "x, err" // overridden for TYPE_MESSAGE and TYPE_GROUP + var dec, cast, cast2 string + switch *field.Type { + case descriptor.FieldDescriptorProto_TYPE_DOUBLE: + dec, cast = "b.DecodeFixed64()", g.Pkg["math"]+".Float64frombits" + case descriptor.FieldDescriptorProto_TYPE_FLOAT: + dec, cast, cast2 = "b.DecodeFixed32()", "uint32", g.Pkg["math"]+".Float32frombits" + case descriptor.FieldDescriptorProto_TYPE_INT64: + dec, cast = "b.DecodeVarint()", "int64" + case descriptor.FieldDescriptorProto_TYPE_UINT64: + dec = "b.DecodeVarint()" + case descriptor.FieldDescriptorProto_TYPE_INT32: + dec, cast = "b.DecodeVarint()", "int32" + case descriptor.FieldDescriptorProto_TYPE_FIXED64: + dec = "b.DecodeFixed64()" + case descriptor.FieldDescriptorProto_TYPE_FIXED32: + dec, cast = "b.DecodeFixed32()", "uint32" + case descriptor.FieldDescriptorProto_TYPE_BOOL: + dec = "b.DecodeVarint()" + // handled specially below + case descriptor.FieldDescriptorProto_TYPE_STRING: + dec = "b.DecodeStringBytes()" + case descriptor.FieldDescriptorProto_TYPE_GROUP: + g.P("msg := new(", fieldTypes[field][1:], ")") // drop star + lhs = "err" + dec = "b.DecodeGroup(msg)" + // handled specially below + case descriptor.FieldDescriptorProto_TYPE_MESSAGE: + g.P("msg := new(", fieldTypes[field][1:], ")") // drop star + lhs = "err" + dec = "b.DecodeMessage(msg)" + // handled specially below + case descriptor.FieldDescriptorProto_TYPE_BYTES: + dec = "b.DecodeRawBytes(true)" + case descriptor.FieldDescriptorProto_TYPE_UINT32: + dec, cast = "b.DecodeVarint()", "uint32" + case descriptor.FieldDescriptorProto_TYPE_ENUM: + dec, cast = "b.DecodeVarint()", fieldTypes[field] + case descriptor.FieldDescriptorProto_TYPE_SFIXED32: + dec, cast = "b.DecodeFixed32()", "int32" + case descriptor.FieldDescriptorProto_TYPE_SFIXED64: + dec, cast = "b.DecodeFixed64()", "int64" + case descriptor.FieldDescriptorProto_TYPE_SINT32: + dec, cast = "b.DecodeZigzag32()", "int32" + case descriptor.FieldDescriptorProto_TYPE_SINT64: + dec, cast = "b.DecodeZigzag64()", "int64" + default: + g.Fail("unhandled oneof field type ", field.Type.String()) + } + g.P(lhs, " := ", dec) + val := "x" + if cast != "" { + val = cast + "(" + val + ")" + } + if cast2 != "" { + val = cast2 + "(" + val + ")" + } + switch *field.Type { + case descriptor.FieldDescriptorProto_TYPE_BOOL: + val += " != 0" + case descriptor.FieldDescriptorProto_TYPE_GROUP, + descriptor.FieldDescriptorProto_TYPE_MESSAGE: + val = "msg" + } + g.P("m.", oneofFieldName[*field.OneofIndex], " = &", oneofTypeName[field], "{", val, "}") + g.P("return true, err") + } + g.P("default: return false, nil") + g.P("}") + g.P("}") + g.P() + + // sizer + g.P("func ", size, sizeSig, " {") + g.P("m := msg.(*", ccTypeName, ")") + for oi, odp := range message.OneofDecl { + g.P("// ", odp.GetName()) + fname := oneofFieldName[int32(oi)] + g.P("switch x := m.", fname, ".(type) {") + for _, field := range message.Field { + if field.OneofIndex == nil || int(*field.OneofIndex) != oi { + continue + } + g.P("case *", oneofTypeName[field], ":") + val := "x." + fieldNames[field] + var wire, varint, fixed string + switch *field.Type { + case descriptor.FieldDescriptorProto_TYPE_DOUBLE: + wire = "WireFixed64" + fixed = "8" + case descriptor.FieldDescriptorProto_TYPE_FLOAT: + wire = "WireFixed32" + fixed = "4" + case descriptor.FieldDescriptorProto_TYPE_INT64, + descriptor.FieldDescriptorProto_TYPE_UINT64, + descriptor.FieldDescriptorProto_TYPE_INT32, + descriptor.FieldDescriptorProto_TYPE_UINT32, + descriptor.FieldDescriptorProto_TYPE_ENUM: + wire = "WireVarint" + varint = val + case descriptor.FieldDescriptorProto_TYPE_FIXED64, + descriptor.FieldDescriptorProto_TYPE_SFIXED64: + wire = "WireFixed64" + fixed = "8" + case descriptor.FieldDescriptorProto_TYPE_FIXED32, + descriptor.FieldDescriptorProto_TYPE_SFIXED32: + wire = "WireFixed32" + fixed = "4" + case descriptor.FieldDescriptorProto_TYPE_BOOL: + wire = "WireVarint" + fixed = "1" + case descriptor.FieldDescriptorProto_TYPE_STRING: + wire = "WireBytes" + fixed = "len(" + val + ")" + varint = fixed + case descriptor.FieldDescriptorProto_TYPE_GROUP: + wire = "WireStartGroup" + fixed = g.Pkg["proto"] + ".Size(" + val + ")" + case descriptor.FieldDescriptorProto_TYPE_MESSAGE: + wire = "WireBytes" + g.P("s := ", g.Pkg["proto"], ".Size(", val, ")") + fixed = "s" + varint = fixed + case descriptor.FieldDescriptorProto_TYPE_BYTES: + wire = "WireBytes" + fixed = "len(" + val + ")" + varint = fixed + case descriptor.FieldDescriptorProto_TYPE_SINT32: + wire = "WireVarint" + varint = "(uint32(" + val + ") << 1) ^ uint32((int32(" + val + ") >> 31))" + case descriptor.FieldDescriptorProto_TYPE_SINT64: + wire = "WireVarint" + varint = "uint64(" + val + " << 1) ^ uint64((int64(" + val + ") >> 63))" + default: + g.Fail("unhandled oneof field type ", field.Type.String()) + } + g.P("n += ", g.Pkg["proto"], ".SizeVarint(", field.Number, "<<3|", g.Pkg["proto"], ".", wire, ")") + if varint != "" { + g.P("n += ", g.Pkg["proto"], ".SizeVarint(uint64(", varint, "))") + } + if fixed != "" { + g.P("n += ", fixed) + } + if *field.Type == descriptor.FieldDescriptorProto_TYPE_GROUP { + g.P("n += ", g.Pkg["proto"], ".SizeVarint(", field.Number, "<<3|", g.Pkg["proto"], ".WireEndGroup)") + } + } + g.P("case nil:") + g.P("default:") + g.P("panic(", g.Pkg["fmt"], ".Sprintf(\"proto: unexpected type %T in oneof\", x))") + g.P("}") + } + g.P("return n") + g.P("}") + g.P() + } + + for _, ext := range message.ext { + g.generateExtension(ext) + } + + fullName := strings.Join(message.TypeName(), ".") + if g.file.Package != nil { + fullName = *g.file.Package + "." + fullName + } + + g.addInitf("%s.RegisterType((*%s)(nil), %q)", g.Pkg["proto"], ccTypeName, fullName) +} + +var escapeChars = [256]byte{ + 'a': '\a', 'b': '\b', 'f': '\f', 'n': '\n', 'r': '\r', 't': '\t', 'v': '\v', '\\': '\\', '"': '"', '\'': '\'', '?': '?', +} + +// unescape reverses the "C" escaping that protoc does for default values of bytes fields. +// It is best effort in that it effectively ignores malformed input. Seemingly invalid escape +// sequences are conveyed, unmodified, into the decoded result. +func unescape(s string) string { + // NB: Sadly, we can't use strconv.Unquote because protoc will escape both + // single and double quotes, but strconv.Unquote only allows one or the + // other (based on actual surrounding quotes of its input argument). + + var out []byte + for len(s) > 0 { + // regular character, or too short to be valid escape + if s[0] != '\\' || len(s) < 2 { + out = append(out, s[0]) + s = s[1:] + } else if c := escapeChars[s[1]]; c != 0 { + // escape sequence + out = append(out, c) + s = s[2:] + } else if s[1] == 'x' || s[1] == 'X' { + // hex escape, e.g. "\x80 + if len(s) < 4 { + // too short to be valid + out = append(out, s[:2]...) + s = s[2:] + continue + } + v, err := strconv.ParseUint(s[2:4], 16, 8) + if err != nil { + out = append(out, s[:4]...) + } else { + out = append(out, byte(v)) + } + s = s[4:] + } else if '0' <= s[1] && s[1] <= '7' { + // octal escape, can vary from 1 to 3 octal digits; e.g., "\0" "\40" or "\164" + // so consume up to 2 more bytes or up to end-of-string + n := len(s[1:]) - len(strings.TrimLeft(s[1:], "01234567")) + if n > 3 { + n = 3 + } + v, err := strconv.ParseUint(s[1:1+n], 8, 8) + if err != nil { + out = append(out, s[:1+n]...) + } else { + out = append(out, byte(v)) + } + s = s[1+n:] + } else { + // bad escape, just propagate the slash as-is + out = append(out, s[0]) + s = s[1:] + } + } + + return string(out) +} + +func (g *Generator) generateExtension(ext *ExtensionDescriptor) { + ccTypeName := ext.DescName() + + extObj := g.ObjectNamed(*ext.Extendee) + var extDesc *Descriptor + if id, ok := extObj.(*ImportedDescriptor); ok { + // This is extending a publicly imported message. + // We need the underlying type for goTag. + extDesc = id.o.(*Descriptor) + } else { + extDesc = extObj.(*Descriptor) + } + extendedType := "*" + g.TypeName(extObj) // always use the original + field := ext.FieldDescriptorProto + fieldType, wireType := g.GoType(ext.parent, field) + tag := g.goTag(extDesc, field, wireType) + g.RecordTypeUse(*ext.Extendee) + if n := ext.FieldDescriptorProto.TypeName; n != nil { + // foreign extension type + g.RecordTypeUse(*n) + } + + typeName := ext.TypeName() + + // Special case for proto2 message sets: If this extension is extending + // proto2_bridge.MessageSet, and its final name component is "message_set_extension", + // then drop that last component. + mset := false + if extendedType == "*proto2_bridge.MessageSet" && typeName[len(typeName)-1] == "message_set_extension" { + typeName = typeName[:len(typeName)-1] + mset = true + } + + // For text formatting, the package must be exactly what the .proto file declares, + // ignoring overrides such as the go_package option, and with no dot/underscore mapping. + extName := strings.Join(typeName, ".") + if g.file.Package != nil { + extName = *g.file.Package + "." + extName + } + + g.P("var ", ccTypeName, " = &", g.Pkg["proto"], ".ExtensionDesc{") + g.In() + g.P("ExtendedType: (", extendedType, ")(nil),") + g.P("ExtensionType: (", fieldType, ")(nil),") + g.P("Field: ", field.Number, ",") + g.P(`Name: "`, extName, `",`) + g.P("Tag: ", tag, ",") + g.P(`Filename: "`, g.file.GetName(), `",`) + + g.Out() + g.P("}") + g.P() + + if mset { + // Generate a bit more code to register with message_set.go. + g.addInitf("%s.RegisterMessageSetType((%s)(nil), %d, %q)", g.Pkg["proto"], fieldType, *field.Number, extName) + } + + g.file.addExport(ext, constOrVarSymbol{ccTypeName, "var", ""}) +} + +func (g *Generator) generateInitFunction() { + for _, enum := range g.file.enum { + g.generateEnumRegistration(enum) + } + for _, d := range g.file.desc { + for _, ext := range d.ext { + g.generateExtensionRegistration(ext) + } + } + for _, ext := range g.file.ext { + g.generateExtensionRegistration(ext) + } + if len(g.init) == 0 { + return + } + g.P("func init() {") + g.In() + for _, l := range g.init { + g.P(l) + } + g.Out() + g.P("}") + g.init = nil +} + +func (g *Generator) generateFileDescriptor(file *FileDescriptor) { + // Make a copy and trim source_code_info data. + // TODO: Trim this more when we know exactly what we need. + pb := proto.Clone(file.FileDescriptorProto).(*descriptor.FileDescriptorProto) + pb.SourceCodeInfo = nil + + b, err := proto.Marshal(pb) + if err != nil { + g.Fail(err.Error()) + } + + var buf bytes.Buffer + w, _ := gzip.NewWriterLevel(&buf, gzip.BestCompression) + w.Write(b) + w.Close() + b = buf.Bytes() + + v := file.VarName() + g.P() + g.P("func init() { ", g.Pkg["proto"], ".RegisterFile(", strconv.Quote(*file.Name), ", ", v, ") }") + g.P("var ", v, " = []byte{") + g.In() + g.P("// ", len(b), " bytes of a gzipped FileDescriptorProto") + for len(b) > 0 { + n := 16 + if n > len(b) { + n = len(b) + } + + s := "" + for _, c := range b[:n] { + s += fmt.Sprintf("0x%02x,", c) + } + g.P(s) + + b = b[n:] + } + g.Out() + g.P("}") +} + +func (g *Generator) generateEnumRegistration(enum *EnumDescriptor) { + // // We always print the full (proto-world) package name here. + pkg := enum.File().GetPackage() + if pkg != "" { + pkg += "." + } + // The full type name + typeName := enum.TypeName() + // The full type name, CamelCased. + ccTypeName := CamelCaseSlice(typeName) + g.addInitf("%s.RegisterEnum(%q, %[3]s_name, %[3]s_value)", g.Pkg["proto"], pkg+ccTypeName, ccTypeName) +} + +func (g *Generator) generateExtensionRegistration(ext *ExtensionDescriptor) { + g.addInitf("%s.RegisterExtension(%s)", g.Pkg["proto"], ext.DescName()) +} + +// And now lots of helper functions. + +// Is c an ASCII lower-case letter? +func isASCIILower(c byte) bool { + return 'a' <= c && c <= 'z' +} + +// Is c an ASCII digit? +func isASCIIDigit(c byte) bool { + return '0' <= c && c <= '9' +} + +// CamelCase returns the CamelCased name. +// If there is an interior underscore followed by a lower case letter, +// drop the underscore and convert the letter to upper case. +// There is a remote possibility of this rewrite causing a name collision, +// but it's so remote we're prepared to pretend it's nonexistent - since the +// C++ generator lowercases names, it's extremely unlikely to have two fields +// with different capitalizations. +// In short, _my_field_name_2 becomes XMyFieldName_2. +func CamelCase(s string) string { + if s == "" { + return "" + } + t := make([]byte, 0, 32) + i := 0 + if s[0] == '_' { + // Need a capital letter; drop the '_'. + t = append(t, 'X') + i++ + } + // Invariant: if the next letter is lower case, it must be converted + // to upper case. + // That is, we process a word at a time, where words are marked by _ or + // upper case letter. Digits are treated as words. + for ; i < len(s); i++ { + c := s[i] + if c == '_' && i+1 < len(s) && isASCIILower(s[i+1]) { + continue // Skip the underscore in s. + } + if isASCIIDigit(c) { + t = append(t, c) + continue + } + // Assume we have a letter now - if not, it's a bogus identifier. + // The next word is a sequence of characters that must start upper case. + if isASCIILower(c) { + c ^= ' ' // Make it a capital letter. + } + t = append(t, c) // Guaranteed not lower case. + // Accept lower case sequence that follows. + for i+1 < len(s) && isASCIILower(s[i+1]) { + i++ + t = append(t, s[i]) + } + } + return string(t) +} + +// CamelCaseSlice is like CamelCase, but the argument is a slice of strings to +// be joined with "_". +func CamelCaseSlice(elem []string) string { return CamelCase(strings.Join(elem, "_")) } + +// dottedSlice turns a sliced name into a dotted name. +func dottedSlice(elem []string) string { return strings.Join(elem, ".") } + +// Is this field optional? +func isOptional(field *descriptor.FieldDescriptorProto) bool { + return field.Label != nil && *field.Label == descriptor.FieldDescriptorProto_LABEL_OPTIONAL +} + +// Is this field required? +func isRequired(field *descriptor.FieldDescriptorProto) bool { + return field.Label != nil && *field.Label == descriptor.FieldDescriptorProto_LABEL_REQUIRED +} + +// Is this field repeated? +func isRepeated(field *descriptor.FieldDescriptorProto) bool { + return field.Label != nil && *field.Label == descriptor.FieldDescriptorProto_LABEL_REPEATED +} + +// Is this field a scalar numeric type? +func isScalar(field *descriptor.FieldDescriptorProto) bool { + if field.Type == nil { + return false + } + switch *field.Type { + case descriptor.FieldDescriptorProto_TYPE_DOUBLE, + descriptor.FieldDescriptorProto_TYPE_FLOAT, + descriptor.FieldDescriptorProto_TYPE_INT64, + descriptor.FieldDescriptorProto_TYPE_UINT64, + descriptor.FieldDescriptorProto_TYPE_INT32, + descriptor.FieldDescriptorProto_TYPE_FIXED64, + descriptor.FieldDescriptorProto_TYPE_FIXED32, + descriptor.FieldDescriptorProto_TYPE_BOOL, + descriptor.FieldDescriptorProto_TYPE_UINT32, + descriptor.FieldDescriptorProto_TYPE_ENUM, + descriptor.FieldDescriptorProto_TYPE_SFIXED32, + descriptor.FieldDescriptorProto_TYPE_SFIXED64, + descriptor.FieldDescriptorProto_TYPE_SINT32, + descriptor.FieldDescriptorProto_TYPE_SINT64: + return true + default: + return false + } +} + +// badToUnderscore is the mapping function used to generate Go names from package names, +// which can be dotted in the input .proto file. It replaces non-identifier characters such as +// dot or dash with underscore. +func badToUnderscore(r rune) rune { + if unicode.IsLetter(r) || unicode.IsDigit(r) || r == '_' { + return r + } + return '_' +} + +// baseName returns the last path element of the name, with the last dotted suffix removed. +func baseName(name string) string { + // First, find the last element + if i := strings.LastIndex(name, "/"); i >= 0 { + name = name[i+1:] + } + // Now drop the suffix + if i := strings.LastIndex(name, "."); i >= 0 { + name = name[0:i] + } + return name +} + +// The SourceCodeInfo message describes the location of elements of a parsed +// .proto file by way of a "path", which is a sequence of integers that +// describe the route from a FileDescriptorProto to the relevant submessage. +// The path alternates between a field number of a repeated field, and an index +// into that repeated field. The constants below define the field numbers that +// are used. +// +// See descriptor.proto for more information about this. +const ( + // tag numbers in FileDescriptorProto + packagePath = 2 // package + messagePath = 4 // message_type + enumPath = 5 // enum_type + // tag numbers in DescriptorProto + messageFieldPath = 2 // field + messageMessagePath = 3 // nested_type + messageEnumPath = 4 // enum_type + messageOneofPath = 8 // oneof_decl + // tag numbers in EnumDescriptorProto + enumValuePath = 2 // value +) diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/generator/name_test.go b/vendor/github.com/golang/protobuf/protoc-gen-go/generator/name_test.go new file mode 100644 index 00000000..76808f3b --- /dev/null +++ b/vendor/github.com/golang/protobuf/protoc-gen-go/generator/name_test.go @@ -0,0 +1,114 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2013 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// 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 +// OWNER 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. + +package generator + +import ( + "testing" + + "github.com/golang/protobuf/protoc-gen-go/descriptor" +) + +func TestCamelCase(t *testing.T) { + tests := []struct { + in, want string + }{ + {"one", "One"}, + {"one_two", "OneTwo"}, + {"_my_field_name_2", "XMyFieldName_2"}, + {"Something_Capped", "Something_Capped"}, + {"my_Name", "My_Name"}, + {"OneTwo", "OneTwo"}, + {"_", "X"}, + {"_a_", "XA_"}, + } + for _, tc := range tests { + if got := CamelCase(tc.in); got != tc.want { + t.Errorf("CamelCase(%q) = %q, want %q", tc.in, got, tc.want) + } + } +} + +func TestGoPackageOption(t *testing.T) { + tests := []struct { + in string + impPath, pkg string + ok bool + }{ + {"", "", "", false}, + {"foo", "", "foo", true}, + {"github.com/golang/bar", "github.com/golang/bar", "bar", true}, + {"github.com/golang/bar;baz", "github.com/golang/bar", "baz", true}, + } + for _, tc := range tests { + d := &FileDescriptor{ + FileDescriptorProto: &descriptor.FileDescriptorProto{ + Options: &descriptor.FileOptions{ + GoPackage: &tc.in, + }, + }, + } + impPath, pkg, ok := d.goPackageOption() + if impPath != tc.impPath || pkg != tc.pkg || ok != tc.ok { + t.Errorf("go_package = %q => (%q, %q, %t), want (%q, %q, %t)", tc.in, + impPath, pkg, ok, tc.impPath, tc.pkg, tc.ok) + } + } +} + +func TestUnescape(t *testing.T) { + tests := []struct { + in string + out string + }{ + // successful cases, including all kinds of escapes + {"", ""}, + {"foo bar baz frob nitz", "foo bar baz frob nitz"}, + {`\000\001\002\003\004\005\006\007`, string([]byte{0, 1, 2, 3, 4, 5, 6, 7})}, + {`\a\b\f\n\r\t\v\\\?\'\"`, string([]byte{'\a', '\b', '\f', '\n', '\r', '\t', '\v', '\\', '?', '\'', '"'})}, + {`\x10\x20\x30\x40\x50\x60\x70\x80`, string([]byte{16, 32, 48, 64, 80, 96, 112, 128})}, + // variable length octal escapes + {`\0\018\222\377\3\04\005\6\07`, string([]byte{0, 1, '8', 0222, 255, 3, 4, 5, 6, 7})}, + // malformed escape sequences left as is + {"foo \\g bar", "foo \\g bar"}, + {"foo \\xg0 bar", "foo \\xg0 bar"}, + {"\\", "\\"}, + {"\\x", "\\x"}, + {"\\xf", "\\xf"}, + {"\\777", "\\777"}, // overflows byte + } + for _, tc := range tests { + s := unescape(tc.in) + if s != tc.out { + t.Errorf("doUnescape(%q) = %q; should have been %q", tc.in, s, tc.out) + } + } +} diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/grpc/grpc.go b/vendor/github.com/golang/protobuf/protoc-gen-go/grpc/grpc.go new file mode 100644 index 00000000..2660e47a --- /dev/null +++ b/vendor/github.com/golang/protobuf/protoc-gen-go/grpc/grpc.go @@ -0,0 +1,463 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2015 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// 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 +// OWNER 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. + +// Package grpc outputs gRPC service descriptions in Go code. +// It runs as a plugin for the Go protocol buffer compiler plugin. +// It is linked in to protoc-gen-go. +package grpc + +import ( + "fmt" + "path" + "strconv" + "strings" + + pb "github.com/golang/protobuf/protoc-gen-go/descriptor" + "github.com/golang/protobuf/protoc-gen-go/generator" +) + +// generatedCodeVersion indicates a version of the generated code. +// It is incremented whenever an incompatibility between the generated code and +// the grpc package is introduced; the generated code references +// a constant, grpc.SupportPackageIsVersionN (where N is generatedCodeVersion). +const generatedCodeVersion = 4 + +// Paths for packages used by code generated in this file, +// relative to the import_prefix of the generator.Generator. +const ( + contextPkgPath = "golang.org/x/net/context" + grpcPkgPath = "google.golang.org/grpc" +) + +func init() { + generator.RegisterPlugin(new(grpc)) +} + +// grpc is an implementation of the Go protocol buffer compiler's +// plugin architecture. It generates bindings for gRPC support. +type grpc struct { + gen *generator.Generator +} + +// Name returns the name of this plugin, "grpc". +func (g *grpc) Name() string { + return "grpc" +} + +// The names for packages imported in the generated code. +// They may vary from the final path component of the import path +// if the name is used by other packages. +var ( + contextPkg string + grpcPkg string +) + +// Init initializes the plugin. +func (g *grpc) Init(gen *generator.Generator) { + g.gen = gen + contextPkg = generator.RegisterUniquePackageName("context", nil) + grpcPkg = generator.RegisterUniquePackageName("grpc", nil) +} + +// Given a type name defined in a .proto, return its object. +// Also record that we're using it, to guarantee the associated import. +func (g *grpc) objectNamed(name string) generator.Object { + g.gen.RecordTypeUse(name) + return g.gen.ObjectNamed(name) +} + +// Given a type name defined in a .proto, return its name as we will print it. +func (g *grpc) typeName(str string) string { + return g.gen.TypeName(g.objectNamed(str)) +} + +// P forwards to g.gen.P. +func (g *grpc) P(args ...interface{}) { g.gen.P(args...) } + +// Generate generates code for the services in the given file. +func (g *grpc) Generate(file *generator.FileDescriptor) { + if len(file.FileDescriptorProto.Service) == 0 { + return + } + + g.P("// Reference imports to suppress errors if they are not otherwise used.") + g.P("var _ ", contextPkg, ".Context") + g.P("var _ ", grpcPkg, ".ClientConn") + g.P() + + // Assert version compatibility. + g.P("// This is a compile-time assertion to ensure that this generated file") + g.P("// is compatible with the grpc package it is being compiled against.") + g.P("const _ = ", grpcPkg, ".SupportPackageIsVersion", generatedCodeVersion) + g.P() + + for i, service := range file.FileDescriptorProto.Service { + g.generateService(file, service, i) + } +} + +// GenerateImports generates the import declaration for this file. +func (g *grpc) GenerateImports(file *generator.FileDescriptor) { + if len(file.FileDescriptorProto.Service) == 0 { + return + } + g.P("import (") + g.P(contextPkg, " ", strconv.Quote(path.Join(g.gen.ImportPrefix, contextPkgPath))) + g.P(grpcPkg, " ", strconv.Quote(path.Join(g.gen.ImportPrefix, grpcPkgPath))) + g.P(")") + g.P() +} + +// reservedClientName records whether a client name is reserved on the client side. +var reservedClientName = map[string]bool{ +// TODO: do we need any in gRPC? +} + +func unexport(s string) string { return strings.ToLower(s[:1]) + s[1:] } + +// generateService generates all the code for the named service. +func (g *grpc) generateService(file *generator.FileDescriptor, service *pb.ServiceDescriptorProto, index int) { + path := fmt.Sprintf("6,%d", index) // 6 means service. + + origServName := service.GetName() + fullServName := origServName + if pkg := file.GetPackage(); pkg != "" { + fullServName = pkg + "." + fullServName + } + servName := generator.CamelCase(origServName) + + g.P() + g.P("// Client API for ", servName, " service") + g.P() + + // Client interface. + g.P("type ", servName, "Client interface {") + for i, method := range service.Method { + g.gen.PrintComments(fmt.Sprintf("%s,2,%d", path, i)) // 2 means method in a service. + g.P(g.generateClientSignature(servName, method)) + } + g.P("}") + g.P() + + // Client structure. + g.P("type ", unexport(servName), "Client struct {") + g.P("cc *", grpcPkg, ".ClientConn") + g.P("}") + g.P() + + // NewClient factory. + g.P("func New", servName, "Client (cc *", grpcPkg, ".ClientConn) ", servName, "Client {") + g.P("return &", unexport(servName), "Client{cc}") + g.P("}") + g.P() + + var methodIndex, streamIndex int + serviceDescVar := "_" + servName + "_serviceDesc" + // Client method implementations. + for _, method := range service.Method { + var descExpr string + if !method.GetServerStreaming() && !method.GetClientStreaming() { + // Unary RPC method + descExpr = fmt.Sprintf("&%s.Methods[%d]", serviceDescVar, methodIndex) + methodIndex++ + } else { + // Streaming RPC method + descExpr = fmt.Sprintf("&%s.Streams[%d]", serviceDescVar, streamIndex) + streamIndex++ + } + g.generateClientMethod(servName, fullServName, serviceDescVar, method, descExpr) + } + + g.P("// Server API for ", servName, " service") + g.P() + + // Server interface. + serverType := servName + "Server" + g.P("type ", serverType, " interface {") + for i, method := range service.Method { + g.gen.PrintComments(fmt.Sprintf("%s,2,%d", path, i)) // 2 means method in a service. + g.P(g.generateServerSignature(servName, method)) + } + g.P("}") + g.P() + + // Server registration. + g.P("func Register", servName, "Server(s *", grpcPkg, ".Server, srv ", serverType, ") {") + g.P("s.RegisterService(&", serviceDescVar, `, srv)`) + g.P("}") + g.P() + + // Server handler implementations. + var handlerNames []string + for _, method := range service.Method { + hname := g.generateServerMethod(servName, fullServName, method) + handlerNames = append(handlerNames, hname) + } + + // Service descriptor. + g.P("var ", serviceDescVar, " = ", grpcPkg, ".ServiceDesc {") + g.P("ServiceName: ", strconv.Quote(fullServName), ",") + g.P("HandlerType: (*", serverType, ")(nil),") + g.P("Methods: []", grpcPkg, ".MethodDesc{") + for i, method := range service.Method { + if method.GetServerStreaming() || method.GetClientStreaming() { + continue + } + g.P("{") + g.P("MethodName: ", strconv.Quote(method.GetName()), ",") + g.P("Handler: ", handlerNames[i], ",") + g.P("},") + } + g.P("},") + g.P("Streams: []", grpcPkg, ".StreamDesc{") + for i, method := range service.Method { + if !method.GetServerStreaming() && !method.GetClientStreaming() { + continue + } + g.P("{") + g.P("StreamName: ", strconv.Quote(method.GetName()), ",") + g.P("Handler: ", handlerNames[i], ",") + if method.GetServerStreaming() { + g.P("ServerStreams: true,") + } + if method.GetClientStreaming() { + g.P("ClientStreams: true,") + } + g.P("},") + } + g.P("},") + g.P("Metadata: \"", file.GetName(), "\",") + g.P("}") + g.P() +} + +// generateClientSignature returns the client-side signature for a method. +func (g *grpc) generateClientSignature(servName string, method *pb.MethodDescriptorProto) string { + origMethName := method.GetName() + methName := generator.CamelCase(origMethName) + if reservedClientName[methName] { + methName += "_" + } + reqArg := ", in *" + g.typeName(method.GetInputType()) + if method.GetClientStreaming() { + reqArg = "" + } + respName := "*" + g.typeName(method.GetOutputType()) + if method.GetServerStreaming() || method.GetClientStreaming() { + respName = servName + "_" + generator.CamelCase(origMethName) + "Client" + } + return fmt.Sprintf("%s(ctx %s.Context%s, opts ...%s.CallOption) (%s, error)", methName, contextPkg, reqArg, grpcPkg, respName) +} + +func (g *grpc) generateClientMethod(servName, fullServName, serviceDescVar string, method *pb.MethodDescriptorProto, descExpr string) { + sname := fmt.Sprintf("/%s/%s", fullServName, method.GetName()) + methName := generator.CamelCase(method.GetName()) + inType := g.typeName(method.GetInputType()) + outType := g.typeName(method.GetOutputType()) + + g.P("func (c *", unexport(servName), "Client) ", g.generateClientSignature(servName, method), "{") + if !method.GetServerStreaming() && !method.GetClientStreaming() { + g.P("out := new(", outType, ")") + // TODO: Pass descExpr to Invoke. + g.P("err := ", grpcPkg, `.Invoke(ctx, "`, sname, `", in, out, c.cc, opts...)`) + g.P("if err != nil { return nil, err }") + g.P("return out, nil") + g.P("}") + g.P() + return + } + streamType := unexport(servName) + methName + "Client" + g.P("stream, err := ", grpcPkg, ".NewClientStream(ctx, ", descExpr, `, c.cc, "`, sname, `", opts...)`) + g.P("if err != nil { return nil, err }") + g.P("x := &", streamType, "{stream}") + if !method.GetClientStreaming() { + g.P("if err := x.ClientStream.SendMsg(in); err != nil { return nil, err }") + g.P("if err := x.ClientStream.CloseSend(); err != nil { return nil, err }") + } + g.P("return x, nil") + g.P("}") + g.P() + + genSend := method.GetClientStreaming() + genRecv := method.GetServerStreaming() + genCloseAndRecv := !method.GetServerStreaming() + + // Stream auxiliary types and methods. + g.P("type ", servName, "_", methName, "Client interface {") + if genSend { + g.P("Send(*", inType, ") error") + } + if genRecv { + g.P("Recv() (*", outType, ", error)") + } + if genCloseAndRecv { + g.P("CloseAndRecv() (*", outType, ", error)") + } + g.P(grpcPkg, ".ClientStream") + g.P("}") + g.P() + + g.P("type ", streamType, " struct {") + g.P(grpcPkg, ".ClientStream") + g.P("}") + g.P() + + if genSend { + g.P("func (x *", streamType, ") Send(m *", inType, ") error {") + g.P("return x.ClientStream.SendMsg(m)") + g.P("}") + g.P() + } + if genRecv { + g.P("func (x *", streamType, ") Recv() (*", outType, ", error) {") + g.P("m := new(", outType, ")") + g.P("if err := x.ClientStream.RecvMsg(m); err != nil { return nil, err }") + g.P("return m, nil") + g.P("}") + g.P() + } + if genCloseAndRecv { + g.P("func (x *", streamType, ") CloseAndRecv() (*", outType, ", error) {") + g.P("if err := x.ClientStream.CloseSend(); err != nil { return nil, err }") + g.P("m := new(", outType, ")") + g.P("if err := x.ClientStream.RecvMsg(m); err != nil { return nil, err }") + g.P("return m, nil") + g.P("}") + g.P() + } +} + +// generateServerSignature returns the server-side signature for a method. +func (g *grpc) generateServerSignature(servName string, method *pb.MethodDescriptorProto) string { + origMethName := method.GetName() + methName := generator.CamelCase(origMethName) + if reservedClientName[methName] { + methName += "_" + } + + var reqArgs []string + ret := "error" + if !method.GetServerStreaming() && !method.GetClientStreaming() { + reqArgs = append(reqArgs, contextPkg+".Context") + ret = "(*" + g.typeName(method.GetOutputType()) + ", error)" + } + if !method.GetClientStreaming() { + reqArgs = append(reqArgs, "*"+g.typeName(method.GetInputType())) + } + if method.GetServerStreaming() || method.GetClientStreaming() { + reqArgs = append(reqArgs, servName+"_"+generator.CamelCase(origMethName)+"Server") + } + + return methName + "(" + strings.Join(reqArgs, ", ") + ") " + ret +} + +func (g *grpc) generateServerMethod(servName, fullServName string, method *pb.MethodDescriptorProto) string { + methName := generator.CamelCase(method.GetName()) + hname := fmt.Sprintf("_%s_%s_Handler", servName, methName) + inType := g.typeName(method.GetInputType()) + outType := g.typeName(method.GetOutputType()) + + if !method.GetServerStreaming() && !method.GetClientStreaming() { + g.P("func ", hname, "(srv interface{}, ctx ", contextPkg, ".Context, dec func(interface{}) error, interceptor ", grpcPkg, ".UnaryServerInterceptor) (interface{}, error) {") + g.P("in := new(", inType, ")") + g.P("if err := dec(in); err != nil { return nil, err }") + g.P("if interceptor == nil { return srv.(", servName, "Server).", methName, "(ctx, in) }") + g.P("info := &", grpcPkg, ".UnaryServerInfo{") + g.P("Server: srv,") + g.P("FullMethod: ", strconv.Quote(fmt.Sprintf("/%s/%s", fullServName, methName)), ",") + g.P("}") + g.P("handler := func(ctx ", contextPkg, ".Context, req interface{}) (interface{}, error) {") + g.P("return srv.(", servName, "Server).", methName, "(ctx, req.(*", inType, "))") + g.P("}") + g.P("return interceptor(ctx, in, info, handler)") + g.P("}") + g.P() + return hname + } + streamType := unexport(servName) + methName + "Server" + g.P("func ", hname, "(srv interface{}, stream ", grpcPkg, ".ServerStream) error {") + if !method.GetClientStreaming() { + g.P("m := new(", inType, ")") + g.P("if err := stream.RecvMsg(m); err != nil { return err }") + g.P("return srv.(", servName, "Server).", methName, "(m, &", streamType, "{stream})") + } else { + g.P("return srv.(", servName, "Server).", methName, "(&", streamType, "{stream})") + } + g.P("}") + g.P() + + genSend := method.GetServerStreaming() + genSendAndClose := !method.GetServerStreaming() + genRecv := method.GetClientStreaming() + + // Stream auxiliary types and methods. + g.P("type ", servName, "_", methName, "Server interface {") + if genSend { + g.P("Send(*", outType, ") error") + } + if genSendAndClose { + g.P("SendAndClose(*", outType, ") error") + } + if genRecv { + g.P("Recv() (*", inType, ", error)") + } + g.P(grpcPkg, ".ServerStream") + g.P("}") + g.P() + + g.P("type ", streamType, " struct {") + g.P(grpcPkg, ".ServerStream") + g.P("}") + g.P() + + if genSend { + g.P("func (x *", streamType, ") Send(m *", outType, ") error {") + g.P("return x.ServerStream.SendMsg(m)") + g.P("}") + g.P() + } + if genSendAndClose { + g.P("func (x *", streamType, ") SendAndClose(m *", outType, ") error {") + g.P("return x.ServerStream.SendMsg(m)") + g.P("}") + g.P() + } + if genRecv { + g.P("func (x *", streamType, ") Recv() (*", inType, ", error) {") + g.P("m := new(", inType, ")") + g.P("if err := x.ServerStream.RecvMsg(m); err != nil { return nil, err }") + g.P("return m, nil") + g.P("}") + g.P() + } + + return hname +} diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/link_grpc.go b/vendor/github.com/golang/protobuf/protoc-gen-go/link_grpc.go new file mode 100644 index 00000000..532a5500 --- /dev/null +++ b/vendor/github.com/golang/protobuf/protoc-gen-go/link_grpc.go @@ -0,0 +1,34 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2015 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// 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 +// OWNER 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. + +package main + +import _ "github.com/golang/protobuf/protoc-gen-go/grpc" diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/main.go b/vendor/github.com/golang/protobuf/protoc-gen-go/main.go new file mode 100644 index 00000000..8e2486de --- /dev/null +++ b/vendor/github.com/golang/protobuf/protoc-gen-go/main.go @@ -0,0 +1,98 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2010 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// 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 +// OWNER 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. + +// protoc-gen-go is a plugin for the Google protocol buffer compiler to generate +// Go code. Run it by building this program and putting it in your path with +// the name +// protoc-gen-go +// That word 'go' at the end becomes part of the option string set for the +// protocol compiler, so once the protocol compiler (protoc) is installed +// you can run +// protoc --go_out=output_directory input_directory/file.proto +// to generate Go bindings for the protocol defined by file.proto. +// With that input, the output will be written to +// output_directory/file.pb.go +// +// The generated code is documented in the package comment for +// the library. +// +// See the README and documentation for protocol buffers to learn more: +// https://developers.google.com/protocol-buffers/ +package main + +import ( + "io/ioutil" + "os" + + "github.com/golang/protobuf/proto" + "github.com/golang/protobuf/protoc-gen-go/generator" +) + +func main() { + // Begin by allocating a generator. The request and response structures are stored there + // so we can do error handling easily - the response structure contains the field to + // report failure. + g := generator.New() + + data, err := ioutil.ReadAll(os.Stdin) + if err != nil { + g.Error(err, "reading input") + } + + if err := proto.Unmarshal(data, g.Request); err != nil { + g.Error(err, "parsing input proto") + } + + if len(g.Request.FileToGenerate) == 0 { + g.Fail("no files to generate") + } + + g.CommandLineParameters(g.Request.GetParameter()) + + // Create a wrapped version of the Descriptors and EnumDescriptors that + // point to the file that defines them. + g.WrapTypes() + + g.SetPackageNames() + g.BuildTypeNameMap() + + g.GenerateAllFiles() + + // Send back the results. + data, err = proto.Marshal(g.Response) + if err != nil { + g.Error(err, "failed to marshal output proto") + } + _, err = os.Stdout.Write(data) + if err != nil { + g.Error(err, "failed to write output proto") + } +} diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/plugin/Makefile b/vendor/github.com/golang/protobuf/protoc-gen-go/plugin/Makefile new file mode 100644 index 00000000..bc0463d5 --- /dev/null +++ b/vendor/github.com/golang/protobuf/protoc-gen-go/plugin/Makefile @@ -0,0 +1,45 @@ +# Go support for Protocol Buffers - Google's data interchange format +# +# Copyright 2010 The Go Authors. All rights reserved. +# https://github.com/golang/protobuf +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# 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 +# OWNER 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. + +# Not stored here, but plugin.proto is in https://github.com/google/protobuf/ +# at src/google/protobuf/compiler/plugin.proto +# Also we need to fix an import. +regenerate: + @echo WARNING! THIS RULE IS PROBABLY NOT RIGHT FOR YOUR INSTALLATION + cp $(HOME)/src/protobuf/include/google/protobuf/compiler/plugin.proto . + protoc --go_out=Mgoogle/protobuf/descriptor.proto=github.com/golang/protobuf/protoc-gen-go/descriptor:../../../../.. \ + -I$(HOME)/src/protobuf/include $(HOME)/src/protobuf/include/google/protobuf/compiler/plugin.proto + +restore: + cp plugin.pb.golden plugin.pb.go + +preserve: + cp plugin.pb.go plugin.pb.golden diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/plugin/plugin.pb.go b/vendor/github.com/golang/protobuf/protoc-gen-go/plugin/plugin.pb.go new file mode 100644 index 00000000..c608a248 --- /dev/null +++ b/vendor/github.com/golang/protobuf/protoc-gen-go/plugin/plugin.pb.go @@ -0,0 +1,293 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: google/protobuf/compiler/plugin.proto + +/* +Package plugin_go is a generated protocol buffer package. + +It is generated from these files: + google/protobuf/compiler/plugin.proto + +It has these top-level messages: + Version + CodeGeneratorRequest + CodeGeneratorResponse +*/ +package plugin_go + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" +import google_protobuf "github.com/golang/protobuf/protoc-gen-go/descriptor" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package + +// The version number of protocol compiler. +type Version struct { + Major *int32 `protobuf:"varint,1,opt,name=major" json:"major,omitempty"` + Minor *int32 `protobuf:"varint,2,opt,name=minor" json:"minor,omitempty"` + Patch *int32 `protobuf:"varint,3,opt,name=patch" json:"patch,omitempty"` + // A suffix for alpha, beta or rc release, e.g., "alpha-1", "rc2". It should + // be empty for mainline stable releases. + Suffix *string `protobuf:"bytes,4,opt,name=suffix" json:"suffix,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *Version) Reset() { *m = Version{} } +func (m *Version) String() string { return proto.CompactTextString(m) } +func (*Version) ProtoMessage() {} +func (*Version) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } + +func (m *Version) GetMajor() int32 { + if m != nil && m.Major != nil { + return *m.Major + } + return 0 +} + +func (m *Version) GetMinor() int32 { + if m != nil && m.Minor != nil { + return *m.Minor + } + return 0 +} + +func (m *Version) GetPatch() int32 { + if m != nil && m.Patch != nil { + return *m.Patch + } + return 0 +} + +func (m *Version) GetSuffix() string { + if m != nil && m.Suffix != nil { + return *m.Suffix + } + return "" +} + +// An encoded CodeGeneratorRequest is written to the plugin's stdin. +type CodeGeneratorRequest struct { + // The .proto files that were explicitly listed on the command-line. The + // code generator should generate code only for these files. Each file's + // descriptor will be included in proto_file, below. + FileToGenerate []string `protobuf:"bytes,1,rep,name=file_to_generate,json=fileToGenerate" json:"file_to_generate,omitempty"` + // The generator parameter passed on the command-line. + Parameter *string `protobuf:"bytes,2,opt,name=parameter" json:"parameter,omitempty"` + // FileDescriptorProtos for all files in files_to_generate and everything + // they import. The files will appear in topological order, so each file + // appears before any file that imports it. + // + // protoc guarantees that all proto_files will be written after + // the fields above, even though this is not technically guaranteed by the + // protobuf wire format. This theoretically could allow a plugin to stream + // in the FileDescriptorProtos and handle them one by one rather than read + // the entire set into memory at once. However, as of this writing, this + // is not similarly optimized on protoc's end -- it will store all fields in + // memory at once before sending them to the plugin. + // + // Type names of fields and extensions in the FileDescriptorProto are always + // fully qualified. + ProtoFile []*google_protobuf.FileDescriptorProto `protobuf:"bytes,15,rep,name=proto_file,json=protoFile" json:"proto_file,omitempty"` + // The version number of protocol compiler. + CompilerVersion *Version `protobuf:"bytes,3,opt,name=compiler_version,json=compilerVersion" json:"compiler_version,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *CodeGeneratorRequest) Reset() { *m = CodeGeneratorRequest{} } +func (m *CodeGeneratorRequest) String() string { return proto.CompactTextString(m) } +func (*CodeGeneratorRequest) ProtoMessage() {} +func (*CodeGeneratorRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } + +func (m *CodeGeneratorRequest) GetFileToGenerate() []string { + if m != nil { + return m.FileToGenerate + } + return nil +} + +func (m *CodeGeneratorRequest) GetParameter() string { + if m != nil && m.Parameter != nil { + return *m.Parameter + } + return "" +} + +func (m *CodeGeneratorRequest) GetProtoFile() []*google_protobuf.FileDescriptorProto { + if m != nil { + return m.ProtoFile + } + return nil +} + +func (m *CodeGeneratorRequest) GetCompilerVersion() *Version { + if m != nil { + return m.CompilerVersion + } + return nil +} + +// The plugin writes an encoded CodeGeneratorResponse to stdout. +type CodeGeneratorResponse struct { + // Error message. If non-empty, code generation failed. The plugin process + // should exit with status code zero even if it reports an error in this way. + // + // This should be used to indicate errors in .proto files which prevent the + // code generator from generating correct code. Errors which indicate a + // problem in protoc itself -- such as the input CodeGeneratorRequest being + // unparseable -- should be reported by writing a message to stderr and + // exiting with a non-zero status code. + Error *string `protobuf:"bytes,1,opt,name=error" json:"error,omitempty"` + File []*CodeGeneratorResponse_File `protobuf:"bytes,15,rep,name=file" json:"file,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *CodeGeneratorResponse) Reset() { *m = CodeGeneratorResponse{} } +func (m *CodeGeneratorResponse) String() string { return proto.CompactTextString(m) } +func (*CodeGeneratorResponse) ProtoMessage() {} +func (*CodeGeneratorResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } + +func (m *CodeGeneratorResponse) GetError() string { + if m != nil && m.Error != nil { + return *m.Error + } + return "" +} + +func (m *CodeGeneratorResponse) GetFile() []*CodeGeneratorResponse_File { + if m != nil { + return m.File + } + return nil +} + +// Represents a single generated file. +type CodeGeneratorResponse_File struct { + // The file name, relative to the output directory. The name must not + // contain "." or ".." components and must be relative, not be absolute (so, + // the file cannot lie outside the output directory). "/" must be used as + // the path separator, not "\". + // + // If the name is omitted, the content will be appended to the previous + // file. This allows the generator to break large files into small chunks, + // and allows the generated text to be streamed back to protoc so that large + // files need not reside completely in memory at one time. Note that as of + // this writing protoc does not optimize for this -- it will read the entire + // CodeGeneratorResponse before writing files to disk. + Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + // If non-empty, indicates that the named file should already exist, and the + // content here is to be inserted into that file at a defined insertion + // point. This feature allows a code generator to extend the output + // produced by another code generator. The original generator may provide + // insertion points by placing special annotations in the file that look + // like: + // @@protoc_insertion_point(NAME) + // The annotation can have arbitrary text before and after it on the line, + // which allows it to be placed in a comment. NAME should be replaced with + // an identifier naming the point -- this is what other generators will use + // as the insertion_point. Code inserted at this point will be placed + // immediately above the line containing the insertion point (thus multiple + // insertions to the same point will come out in the order they were added). + // The double-@ is intended to make it unlikely that the generated code + // could contain things that look like insertion points by accident. + // + // For example, the C++ code generator places the following line in the + // .pb.h files that it generates: + // // @@protoc_insertion_point(namespace_scope) + // This line appears within the scope of the file's package namespace, but + // outside of any particular class. Another plugin can then specify the + // insertion_point "namespace_scope" to generate additional classes or + // other declarations that should be placed in this scope. + // + // Note that if the line containing the insertion point begins with + // whitespace, the same whitespace will be added to every line of the + // inserted text. This is useful for languages like Python, where + // indentation matters. In these languages, the insertion point comment + // should be indented the same amount as any inserted code will need to be + // in order to work correctly in that context. + // + // The code generator that generates the initial file and the one which + // inserts into it must both run as part of a single invocation of protoc. + // Code generators are executed in the order in which they appear on the + // command line. + // + // If |insertion_point| is present, |name| must also be present. + InsertionPoint *string `protobuf:"bytes,2,opt,name=insertion_point,json=insertionPoint" json:"insertion_point,omitempty"` + // The file contents. + Content *string `protobuf:"bytes,15,opt,name=content" json:"content,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *CodeGeneratorResponse_File) Reset() { *m = CodeGeneratorResponse_File{} } +func (m *CodeGeneratorResponse_File) String() string { return proto.CompactTextString(m) } +func (*CodeGeneratorResponse_File) ProtoMessage() {} +func (*CodeGeneratorResponse_File) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2, 0} } + +func (m *CodeGeneratorResponse_File) GetName() string { + if m != nil && m.Name != nil { + return *m.Name + } + return "" +} + +func (m *CodeGeneratorResponse_File) GetInsertionPoint() string { + if m != nil && m.InsertionPoint != nil { + return *m.InsertionPoint + } + return "" +} + +func (m *CodeGeneratorResponse_File) GetContent() string { + if m != nil && m.Content != nil { + return *m.Content + } + return "" +} + +func init() { + proto.RegisterType((*Version)(nil), "google.protobuf.compiler.Version") + proto.RegisterType((*CodeGeneratorRequest)(nil), "google.protobuf.compiler.CodeGeneratorRequest") + proto.RegisterType((*CodeGeneratorResponse)(nil), "google.protobuf.compiler.CodeGeneratorResponse") + proto.RegisterType((*CodeGeneratorResponse_File)(nil), "google.protobuf.compiler.CodeGeneratorResponse.File") +} + +func init() { proto.RegisterFile("google/protobuf/compiler/plugin.proto", fileDescriptor0) } + +var fileDescriptor0 = []byte{ + // 417 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x92, 0xcf, 0x6a, 0x14, 0x41, + 0x10, 0xc6, 0x19, 0x77, 0x63, 0x98, 0x8a, 0x64, 0x43, 0x13, 0xa5, 0x09, 0x39, 0x8c, 0x8b, 0xe2, + 0x5c, 0x32, 0x0b, 0xc1, 0x8b, 0x78, 0x4b, 0x44, 0x3d, 0x78, 0x58, 0x1a, 0xf1, 0x20, 0xc8, 0x30, + 0x99, 0xd4, 0x74, 0x5a, 0x66, 0xba, 0xc6, 0xee, 0x1e, 0xf1, 0x49, 0x7d, 0x0f, 0xdf, 0x40, 0xfa, + 0xcf, 0x24, 0xb2, 0xb8, 0xa7, 0xee, 0xef, 0x57, 0xd5, 0xd5, 0x55, 0x1f, 0x05, 0x2f, 0x25, 0x91, + 0xec, 0x71, 0x33, 0x1a, 0x72, 0x74, 0x33, 0x75, 0x9b, 0x96, 0x86, 0x51, 0xf5, 0x68, 0x36, 0x63, + 0x3f, 0x49, 0xa5, 0xab, 0x10, 0x60, 0x3c, 0xa6, 0x55, 0x73, 0x5a, 0x35, 0xa7, 0x9d, 0x15, 0xbb, + 0x05, 0x6e, 0xd1, 0xb6, 0x46, 0x8d, 0x8e, 0x4c, 0xcc, 0x5e, 0xb7, 0x70, 0xf8, 0x05, 0x8d, 0x55, + 0xa4, 0xd9, 0x29, 0x1c, 0x0c, 0xcd, 0x77, 0x32, 0x3c, 0x2b, 0xb2, 0xf2, 0x40, 0x44, 0x11, 0xa8, + 0xd2, 0x64, 0xf8, 0xa3, 0x44, 0xbd, 0xf0, 0x74, 0x6c, 0x5c, 0x7b, 0xc7, 0x17, 0x91, 0x06, 0xc1, + 0x9e, 0xc1, 0x63, 0x3b, 0x75, 0x9d, 0xfa, 0xc5, 0x97, 0x45, 0x56, 0xe6, 0x22, 0xa9, 0xf5, 0x9f, + 0x0c, 0x4e, 0xaf, 0xe9, 0x16, 0x3f, 0xa0, 0x46, 0xd3, 0x38, 0x32, 0x02, 0x7f, 0x4c, 0x68, 0x1d, + 0x2b, 0xe1, 0xa4, 0x53, 0x3d, 0xd6, 0x8e, 0x6a, 0x19, 0x63, 0xc8, 0xb3, 0x62, 0x51, 0xe6, 0xe2, + 0xd8, 0xf3, 0xcf, 0x94, 0x5e, 0x20, 0x3b, 0x87, 0x7c, 0x6c, 0x4c, 0x33, 0xa0, 0xc3, 0xd8, 0x4a, + 0x2e, 0x1e, 0x00, 0xbb, 0x06, 0x08, 0xe3, 0xd4, 0xfe, 0x15, 0x5f, 0x15, 0x8b, 0xf2, 0xe8, 0xf2, + 0x45, 0xb5, 0x6b, 0xcb, 0x7b, 0xd5, 0xe3, 0xbb, 0x7b, 0x03, 0xb6, 0x1e, 0x8b, 0x3c, 0x44, 0x7d, + 0x84, 0x7d, 0x82, 0x93, 0xd9, 0xb8, 0xfa, 0x67, 0xf4, 0x24, 0x8c, 0x77, 0x74, 0xf9, 0xbc, 0xda, + 0xe7, 0x70, 0x95, 0xcc, 0x13, 0xab, 0x99, 0x24, 0xb0, 0xfe, 0x9d, 0xc1, 0xd3, 0x9d, 0x99, 0xed, + 0x48, 0xda, 0xa2, 0xf7, 0x0e, 0x8d, 0x49, 0x3e, 0xe7, 0x22, 0x0a, 0xf6, 0x11, 0x96, 0xff, 0x34, + 0xff, 0x7a, 0xff, 0x8f, 0xff, 0x2d, 0x1a, 0x66, 0x13, 0xa1, 0xc2, 0xd9, 0x37, 0x58, 0x86, 0x79, + 0x18, 0x2c, 0x75, 0x33, 0x60, 0xfa, 0x26, 0xdc, 0xd9, 0x2b, 0x58, 0x29, 0x6d, 0xd1, 0x38, 0x45, + 0xba, 0x1e, 0x49, 0x69, 0x97, 0xcc, 0x3c, 0xbe, 0xc7, 0x5b, 0x4f, 0x19, 0x87, 0xc3, 0x96, 0xb4, + 0x43, 0xed, 0xf8, 0x2a, 0x24, 0xcc, 0xf2, 0x4a, 0xc2, 0x79, 0x4b, 0xc3, 0xde, 0xfe, 0xae, 0x9e, + 0x6c, 0xc3, 0x6e, 0x06, 0x7b, 0xed, 0xd7, 0x37, 0x52, 0xb9, 0xbb, 0xe9, 0xc6, 0x87, 0x37, 0x92, + 0xfa, 0x46, 0xcb, 0x87, 0x65, 0x0c, 0x97, 0xf6, 0x42, 0xa2, 0xbe, 0x90, 0x94, 0x56, 0xfa, 0x6d, + 0x3c, 0x6a, 0x49, 0x7f, 0x03, 0x00, 0x00, 0xff, 0xff, 0xf7, 0x15, 0x40, 0xc5, 0xfe, 0x02, 0x00, + 0x00, +} diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/plugin/plugin.pb.golden b/vendor/github.com/golang/protobuf/protoc-gen-go/plugin/plugin.pb.golden new file mode 100644 index 00000000..8953d0ff --- /dev/null +++ b/vendor/github.com/golang/protobuf/protoc-gen-go/plugin/plugin.pb.golden @@ -0,0 +1,83 @@ +// Code generated by protoc-gen-go. +// source: google/protobuf/compiler/plugin.proto +// DO NOT EDIT! + +package google_protobuf_compiler + +import proto "github.com/golang/protobuf/proto" +import "math" +import google_protobuf "github.com/golang/protobuf/protoc-gen-go/descriptor" + +// Reference proto and math imports to suppress error if they are not otherwise used. +var _ = proto.GetString +var _ = math.Inf + +type CodeGeneratorRequest struct { + FileToGenerate []string `protobuf:"bytes,1,rep,name=file_to_generate" json:"file_to_generate,omitempty"` + Parameter *string `protobuf:"bytes,2,opt,name=parameter" json:"parameter,omitempty"` + ProtoFile []*google_protobuf.FileDescriptorProto `protobuf:"bytes,15,rep,name=proto_file" json:"proto_file,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (this *CodeGeneratorRequest) Reset() { *this = CodeGeneratorRequest{} } +func (this *CodeGeneratorRequest) String() string { return proto.CompactTextString(this) } +func (*CodeGeneratorRequest) ProtoMessage() {} + +func (this *CodeGeneratorRequest) GetParameter() string { + if this != nil && this.Parameter != nil { + return *this.Parameter + } + return "" +} + +type CodeGeneratorResponse struct { + Error *string `protobuf:"bytes,1,opt,name=error" json:"error,omitempty"` + File []*CodeGeneratorResponse_File `protobuf:"bytes,15,rep,name=file" json:"file,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (this *CodeGeneratorResponse) Reset() { *this = CodeGeneratorResponse{} } +func (this *CodeGeneratorResponse) String() string { return proto.CompactTextString(this) } +func (*CodeGeneratorResponse) ProtoMessage() {} + +func (this *CodeGeneratorResponse) GetError() string { + if this != nil && this.Error != nil { + return *this.Error + } + return "" +} + +type CodeGeneratorResponse_File struct { + Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + InsertionPoint *string `protobuf:"bytes,2,opt,name=insertion_point" json:"insertion_point,omitempty"` + Content *string `protobuf:"bytes,15,opt,name=content" json:"content,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (this *CodeGeneratorResponse_File) Reset() { *this = CodeGeneratorResponse_File{} } +func (this *CodeGeneratorResponse_File) String() string { return proto.CompactTextString(this) } +func (*CodeGeneratorResponse_File) ProtoMessage() {} + +func (this *CodeGeneratorResponse_File) GetName() string { + if this != nil && this.Name != nil { + return *this.Name + } + return "" +} + +func (this *CodeGeneratorResponse_File) GetInsertionPoint() string { + if this != nil && this.InsertionPoint != nil { + return *this.InsertionPoint + } + return "" +} + +func (this *CodeGeneratorResponse_File) GetContent() string { + if this != nil && this.Content != nil { + return *this.Content + } + return "" +} + +func init() { +} diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/plugin/plugin.proto b/vendor/github.com/golang/protobuf/protoc-gen-go/plugin/plugin.proto new file mode 100644 index 00000000..5b557452 --- /dev/null +++ b/vendor/github.com/golang/protobuf/protoc-gen-go/plugin/plugin.proto @@ -0,0 +1,167 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// 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 +// OWNER 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. + +// Author: kenton@google.com (Kenton Varda) +// +// WARNING: The plugin interface is currently EXPERIMENTAL and is subject to +// change. +// +// protoc (aka the Protocol Compiler) can be extended via plugins. A plugin is +// just a program that reads a CodeGeneratorRequest from stdin and writes a +// CodeGeneratorResponse to stdout. +// +// Plugins written using C++ can use google/protobuf/compiler/plugin.h instead +// of dealing with the raw protocol defined here. +// +// A plugin executable needs only to be placed somewhere in the path. The +// plugin should be named "protoc-gen-$NAME", and will then be used when the +// flag "--${NAME}_out" is passed to protoc. + +syntax = "proto2"; +package google.protobuf.compiler; +option java_package = "com.google.protobuf.compiler"; +option java_outer_classname = "PluginProtos"; + +option go_package = "github.com/golang/protobuf/protoc-gen-go/plugin;plugin_go"; + +import "google/protobuf/descriptor.proto"; + +// The version number of protocol compiler. +message Version { + optional int32 major = 1; + optional int32 minor = 2; + optional int32 patch = 3; + // A suffix for alpha, beta or rc release, e.g., "alpha-1", "rc2". It should + // be empty for mainline stable releases. + optional string suffix = 4; +} + +// An encoded CodeGeneratorRequest is written to the plugin's stdin. +message CodeGeneratorRequest { + // The .proto files that were explicitly listed on the command-line. The + // code generator should generate code only for these files. Each file's + // descriptor will be included in proto_file, below. + repeated string file_to_generate = 1; + + // The generator parameter passed on the command-line. + optional string parameter = 2; + + // FileDescriptorProtos for all files in files_to_generate and everything + // they import. The files will appear in topological order, so each file + // appears before any file that imports it. + // + // protoc guarantees that all proto_files will be written after + // the fields above, even though this is not technically guaranteed by the + // protobuf wire format. This theoretically could allow a plugin to stream + // in the FileDescriptorProtos and handle them one by one rather than read + // the entire set into memory at once. However, as of this writing, this + // is not similarly optimized on protoc's end -- it will store all fields in + // memory at once before sending them to the plugin. + // + // Type names of fields and extensions in the FileDescriptorProto are always + // fully qualified. + repeated FileDescriptorProto proto_file = 15; + + // The version number of protocol compiler. + optional Version compiler_version = 3; + +} + +// The plugin writes an encoded CodeGeneratorResponse to stdout. +message CodeGeneratorResponse { + // Error message. If non-empty, code generation failed. The plugin process + // should exit with status code zero even if it reports an error in this way. + // + // This should be used to indicate errors in .proto files which prevent the + // code generator from generating correct code. Errors which indicate a + // problem in protoc itself -- such as the input CodeGeneratorRequest being + // unparseable -- should be reported by writing a message to stderr and + // exiting with a non-zero status code. + optional string error = 1; + + // Represents a single generated file. + message File { + // The file name, relative to the output directory. The name must not + // contain "." or ".." components and must be relative, not be absolute (so, + // the file cannot lie outside the output directory). "/" must be used as + // the path separator, not "\". + // + // If the name is omitted, the content will be appended to the previous + // file. This allows the generator to break large files into small chunks, + // and allows the generated text to be streamed back to protoc so that large + // files need not reside completely in memory at one time. Note that as of + // this writing protoc does not optimize for this -- it will read the entire + // CodeGeneratorResponse before writing files to disk. + optional string name = 1; + + // If non-empty, indicates that the named file should already exist, and the + // content here is to be inserted into that file at a defined insertion + // point. This feature allows a code generator to extend the output + // produced by another code generator. The original generator may provide + // insertion points by placing special annotations in the file that look + // like: + // @@protoc_insertion_point(NAME) + // The annotation can have arbitrary text before and after it on the line, + // which allows it to be placed in a comment. NAME should be replaced with + // an identifier naming the point -- this is what other generators will use + // as the insertion_point. Code inserted at this point will be placed + // immediately above the line containing the insertion point (thus multiple + // insertions to the same point will come out in the order they were added). + // The double-@ is intended to make it unlikely that the generated code + // could contain things that look like insertion points by accident. + // + // For example, the C++ code generator places the following line in the + // .pb.h files that it generates: + // // @@protoc_insertion_point(namespace_scope) + // This line appears within the scope of the file's package namespace, but + // outside of any particular class. Another plugin can then specify the + // insertion_point "namespace_scope" to generate additional classes or + // other declarations that should be placed in this scope. + // + // Note that if the line containing the insertion point begins with + // whitespace, the same whitespace will be added to every line of the + // inserted text. This is useful for languages like Python, where + // indentation matters. In these languages, the insertion point comment + // should be indented the same amount as any inserted code will need to be + // in order to work correctly in that context. + // + // The code generator that generates the initial file and the one which + // inserts into it must both run as part of a single invocation of protoc. + // Code generators are executed in the order in which they appear on the + // command line. + // + // If |insertion_point| is present, |name| must also be present. + optional string insertion_point = 2; + + // The file contents. + optional string content = 15; + } + repeated File file = 15; +} diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/Makefile b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/Makefile new file mode 100644 index 00000000..a0bf9fef --- /dev/null +++ b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/Makefile @@ -0,0 +1,73 @@ +# Go support for Protocol Buffers - Google's data interchange format +# +# Copyright 2010 The Go Authors. All rights reserved. +# https://github.com/golang/protobuf +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# 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 +# OWNER 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. + +all: + @echo run make test + +include ../../Make.protobuf + +test: golden testbuild + +#test: golden testbuild extension_test +# ./extension_test +# @echo PASS + +my_test/test.pb.go: my_test/test.proto + protoc --go_out=Mmulti/multi1.proto=github.com/golang/protobuf/protoc-gen-go/testdata/multi:. $< + +golden: + make -B my_test/test.pb.go + sed -i -e '/return.*fileDescriptor/d' my_test/test.pb.go + sed -i -e '/^var fileDescriptor/,/^}/d' my_test/test.pb.go + sed -i -e '/proto.RegisterFile.*fileDescriptor/d' my_test/test.pb.go + gofmt -w my_test/test.pb.go + diff -w my_test/test.pb.go my_test/test.pb.go.golden + +nuke: clean + +testbuild: regenerate + go test + +regenerate: + # Invoke protoc once to generate three independent .pb.go files in the same package. + protoc --go_out=. multi/multi1.proto multi/multi2.proto multi/multi3.proto + +#extension_test: extension_test.$O +# $(LD) -L. -o $@ $< + +#multi.a: multi3.pb.$O multi2.pb.$O multi1.pb.$O +# rm -f multi.a +# $(QUOTED_GOBIN)/gopack grc $@ $< + +#test.pb.go: imp.pb.go +#multi1.pb.go: multi2.pb.go multi3.pb.go +#main.$O: imp.pb.$O test.pb.$O multi.a +#extension_test.$O: extension_base.pb.$O extension_extra.pb.$O extension_user.pb.$O diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/extension_base.proto b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/extension_base.proto new file mode 100644 index 00000000..94acfc1b --- /dev/null +++ b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/extension_base.proto @@ -0,0 +1,46 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2010 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// 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 +// OWNER 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. + +syntax = "proto2"; + +package extension_base; + +message BaseMessage { + optional int32 height = 1; + extensions 4 to 9; + extensions 16 to max; +} + +// Another message that may be extended, using message_set_wire_format. +message OldStyleMessage { + option message_set_wire_format = true; + extensions 100 to max; +} diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/extension_extra.proto b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/extension_extra.proto new file mode 100644 index 00000000..fca7f600 --- /dev/null +++ b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/extension_extra.proto @@ -0,0 +1,38 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2011 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// 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 +// OWNER 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. + +syntax = "proto2"; + +package extension_extra; + +message ExtraMessage { + optional int32 width = 1; +} diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/extension_test.go b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/extension_test.go new file mode 100644 index 00000000..86e9c118 --- /dev/null +++ b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/extension_test.go @@ -0,0 +1,210 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2010 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// 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 +// OWNER 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. + +// Test that we can use protocol buffers that use extensions. + +package testdata + +/* + +import ( + "bytes" + "regexp" + "testing" + + "github.com/golang/protobuf/proto" + base "extension_base.pb" + user "extension_user.pb" +) + +func TestSingleFieldExtension(t *testing.T) { + bm := &base.BaseMessage{ + Height: proto.Int32(178), + } + + // Use extension within scope of another type. + vol := proto.Uint32(11) + err := proto.SetExtension(bm, user.E_LoudMessage_Volume, vol) + if err != nil { + t.Fatal("Failed setting extension:", err) + } + buf, err := proto.Marshal(bm) + if err != nil { + t.Fatal("Failed encoding message with extension:", err) + } + bm_new := new(base.BaseMessage) + if err := proto.Unmarshal(buf, bm_new); err != nil { + t.Fatal("Failed decoding message with extension:", err) + } + if !proto.HasExtension(bm_new, user.E_LoudMessage_Volume) { + t.Fatal("Decoded message didn't contain extension.") + } + vol_out, err := proto.GetExtension(bm_new, user.E_LoudMessage_Volume) + if err != nil { + t.Fatal("Failed getting extension:", err) + } + if v := vol_out.(*uint32); *v != *vol { + t.Errorf("vol_out = %v, expected %v", *v, *vol) + } + proto.ClearExtension(bm_new, user.E_LoudMessage_Volume) + if proto.HasExtension(bm_new, user.E_LoudMessage_Volume) { + t.Fatal("Failed clearing extension.") + } +} + +func TestMessageExtension(t *testing.T) { + bm := &base.BaseMessage{ + Height: proto.Int32(179), + } + + // Use extension that is itself a message. + um := &user.UserMessage{ + Name: proto.String("Dave"), + Rank: proto.String("Major"), + } + err := proto.SetExtension(bm, user.E_LoginMessage_UserMessage, um) + if err != nil { + t.Fatal("Failed setting extension:", err) + } + buf, err := proto.Marshal(bm) + if err != nil { + t.Fatal("Failed encoding message with extension:", err) + } + bm_new := new(base.BaseMessage) + if err := proto.Unmarshal(buf, bm_new); err != nil { + t.Fatal("Failed decoding message with extension:", err) + } + if !proto.HasExtension(bm_new, user.E_LoginMessage_UserMessage) { + t.Fatal("Decoded message didn't contain extension.") + } + um_out, err := proto.GetExtension(bm_new, user.E_LoginMessage_UserMessage) + if err != nil { + t.Fatal("Failed getting extension:", err) + } + if n := um_out.(*user.UserMessage).Name; *n != *um.Name { + t.Errorf("um_out.Name = %q, expected %q", *n, *um.Name) + } + if r := um_out.(*user.UserMessage).Rank; *r != *um.Rank { + t.Errorf("um_out.Rank = %q, expected %q", *r, *um.Rank) + } + proto.ClearExtension(bm_new, user.E_LoginMessage_UserMessage) + if proto.HasExtension(bm_new, user.E_LoginMessage_UserMessage) { + t.Fatal("Failed clearing extension.") + } +} + +func TestTopLevelExtension(t *testing.T) { + bm := &base.BaseMessage{ + Height: proto.Int32(179), + } + + width := proto.Int32(17) + err := proto.SetExtension(bm, user.E_Width, width) + if err != nil { + t.Fatal("Failed setting extension:", err) + } + buf, err := proto.Marshal(bm) + if err != nil { + t.Fatal("Failed encoding message with extension:", err) + } + bm_new := new(base.BaseMessage) + if err := proto.Unmarshal(buf, bm_new); err != nil { + t.Fatal("Failed decoding message with extension:", err) + } + if !proto.HasExtension(bm_new, user.E_Width) { + t.Fatal("Decoded message didn't contain extension.") + } + width_out, err := proto.GetExtension(bm_new, user.E_Width) + if err != nil { + t.Fatal("Failed getting extension:", err) + } + if w := width_out.(*int32); *w != *width { + t.Errorf("width_out = %v, expected %v", *w, *width) + } + proto.ClearExtension(bm_new, user.E_Width) + if proto.HasExtension(bm_new, user.E_Width) { + t.Fatal("Failed clearing extension.") + } +} + +func TestMessageSetWireFormat(t *testing.T) { + osm := new(base.OldStyleMessage) + osp := &user.OldStyleParcel{ + Name: proto.String("Dave"), + Height: proto.Int32(178), + } + + err := proto.SetExtension(osm, user.E_OldStyleParcel_MessageSetExtension, osp) + if err != nil { + t.Fatal("Failed setting extension:", err) + } + + buf, err := proto.Marshal(osm) + if err != nil { + t.Fatal("Failed encoding message:", err) + } + + // Data generated from Python implementation. + expected := []byte{ + 11, 16, 209, 15, 26, 9, 10, 4, 68, 97, 118, 101, 16, 178, 1, 12, + } + + if !bytes.Equal(expected, buf) { + t.Errorf("Encoding mismatch.\nwant %+v\n got %+v", expected, buf) + } + + // Check that it is restored correctly. + osm = new(base.OldStyleMessage) + if err := proto.Unmarshal(buf, osm); err != nil { + t.Fatal("Failed decoding message:", err) + } + osp_out, err := proto.GetExtension(osm, user.E_OldStyleParcel_MessageSetExtension) + if err != nil { + t.Fatal("Failed getting extension:", err) + } + osp = osp_out.(*user.OldStyleParcel) + if *osp.Name != "Dave" || *osp.Height != 178 { + t.Errorf("Retrieved extension from decoded message is not correct: %+v", osp) + } +} + +func main() { + // simpler than rigging up gotest + testing.Main(regexp.MatchString, []testing.InternalTest{ + {"TestSingleFieldExtension", TestSingleFieldExtension}, + {"TestMessageExtension", TestMessageExtension}, + {"TestTopLevelExtension", TestTopLevelExtension}, + }, + []testing.InternalBenchmark{}, + []testing.InternalExample{}) +} + +*/ diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/extension_user.proto b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/extension_user.proto new file mode 100644 index 00000000..ff65873d --- /dev/null +++ b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/extension_user.proto @@ -0,0 +1,100 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2010 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// 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 +// OWNER 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. + +syntax = "proto2"; + +import "extension_base.proto"; +import "extension_extra.proto"; + +package extension_user; + +message UserMessage { + optional string name = 1; + optional string rank = 2; +} + +// Extend with a message +extend extension_base.BaseMessage { + optional UserMessage user_message = 5; +} + +// Extend with a foreign message +extend extension_base.BaseMessage { + optional extension_extra.ExtraMessage extra_message = 9; +} + +// Extend with some primitive types +extend extension_base.BaseMessage { + optional int32 width = 6; + optional int64 area = 7; +} + +// Extend inside the scope of another type +message LoudMessage { + extend extension_base.BaseMessage { + optional uint32 volume = 8; + } + extensions 100 to max; +} + +// Extend inside the scope of another type, using a message. +message LoginMessage { + extend extension_base.BaseMessage { + optional UserMessage user_message = 16; + } +} + +// Extend with a repeated field +extend extension_base.BaseMessage { + repeated Detail detail = 17; +} + +message Detail { + optional string color = 1; +} + +// An extension of an extension +message Announcement { + optional string words = 1; + extend LoudMessage { + optional Announcement loud_ext = 100; + } +} + +// Something that can be put in a message set. +message OldStyleParcel { + extend extension_base.OldStyleMessage { + optional OldStyleParcel message_set_extension = 2001; + } + + required string name = 1; + optional int32 height = 2; +} diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/grpc.proto b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/grpc.proto new file mode 100644 index 00000000..b8bc41ac --- /dev/null +++ b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/grpc.proto @@ -0,0 +1,59 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2015 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// 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 +// OWNER 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. + +syntax = "proto3"; + +package grpc.testing; + +message SimpleRequest { +} + +message SimpleResponse { +} + +message StreamMsg { +} + +message StreamMsg2 { +} + +service Test { + rpc UnaryCall(SimpleRequest) returns (SimpleResponse); + + // This RPC streams from the server only. + rpc Downstream(SimpleRequest) returns (stream StreamMsg); + + // This RPC streams from the client. + rpc Upstream(stream StreamMsg) returns (SimpleResponse); + + // This one streams in both directions. + rpc Bidi(stream StreamMsg) returns (stream StreamMsg2); +} diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/imp.pb.go.golden b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/imp.pb.go.golden new file mode 100644 index 00000000..784a4f86 --- /dev/null +++ b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/imp.pb.go.golden @@ -0,0 +1,113 @@ +// Code generated by protoc-gen-go. +// source: imp.proto +// DO NOT EDIT! + +package imp + +import proto "github.com/golang/protobuf/proto" +import "math" +import "os" +import imp1 "imp2.pb" + +// Reference proto & math imports to suppress error if they are not otherwise used. +var _ = proto.GetString +var _ = math.Inf + +// Types from public import imp2.proto +type PubliclyImportedMessage imp1.PubliclyImportedMessage + +func (this *PubliclyImportedMessage) Reset() { (*imp1.PubliclyImportedMessage)(this).Reset() } +func (this *PubliclyImportedMessage) String() string { + return (*imp1.PubliclyImportedMessage)(this).String() +} + +// PubliclyImportedMessage from public import imp.proto + +type ImportedMessage_Owner int32 + +const ( + ImportedMessage_DAVE ImportedMessage_Owner = 1 + ImportedMessage_MIKE ImportedMessage_Owner = 2 +) + +var ImportedMessage_Owner_name = map[int32]string{ + 1: "DAVE", + 2: "MIKE", +} +var ImportedMessage_Owner_value = map[string]int32{ + "DAVE": 1, + "MIKE": 2, +} + +// NewImportedMessage_Owner is deprecated. Use x.Enum() instead. +func NewImportedMessage_Owner(x ImportedMessage_Owner) *ImportedMessage_Owner { + e := ImportedMessage_Owner(x) + return &e +} +func (x ImportedMessage_Owner) Enum() *ImportedMessage_Owner { + p := new(ImportedMessage_Owner) + *p = x + return p +} +func (x ImportedMessage_Owner) String() string { + return proto.EnumName(ImportedMessage_Owner_name, int32(x)) +} + +type ImportedMessage struct { + Field *int64 `protobuf:"varint,1,req,name=field" json:"field,omitempty"` + XXX_extensions map[int32][]byte `json:",omitempty"` + XXX_unrecognized []byte `json:",omitempty"` +} + +func (this *ImportedMessage) Reset() { *this = ImportedMessage{} } +func (this *ImportedMessage) String() string { return proto.CompactTextString(this) } + +var extRange_ImportedMessage = []proto.ExtensionRange{ + proto.ExtensionRange{90, 100}, +} + +func (*ImportedMessage) ExtensionRangeArray() []proto.ExtensionRange { + return extRange_ImportedMessage +} +func (this *ImportedMessage) ExtensionMap() map[int32][]byte { + if this.XXX_extensions == nil { + this.XXX_extensions = make(map[int32][]byte) + } + return this.XXX_extensions +} + +type ImportedExtendable struct { + XXX_extensions map[int32][]byte `json:",omitempty"` + XXX_unrecognized []byte `json:",omitempty"` +} + +func (this *ImportedExtendable) Reset() { *this = ImportedExtendable{} } +func (this *ImportedExtendable) String() string { return proto.CompactTextString(this) } + +func (this *ImportedExtendable) Marshal() ([]byte, error) { + return proto.MarshalMessageSet(this.ExtensionMap()) +} +func (this *ImportedExtendable) Unmarshal(buf []byte) error { + return proto.UnmarshalMessageSet(buf, this.ExtensionMap()) +} +// ensure ImportedExtendable satisfies proto.Marshaler and proto.Unmarshaler +var _ proto.Marshaler = (*ImportedExtendable)(nil) +var _ proto.Unmarshaler = (*ImportedExtendable)(nil) + +var extRange_ImportedExtendable = []proto.ExtensionRange{ + proto.ExtensionRange{100, 536870911}, +} + +func (*ImportedExtendable) ExtensionRangeArray() []proto.ExtensionRange { + return extRange_ImportedExtendable +} +func (this *ImportedExtendable) ExtensionMap() map[int32][]byte { + if this.XXX_extensions == nil { + this.XXX_extensions = make(map[int32][]byte) + } + return this.XXX_extensions +} + +func init() { + proto.RegisterEnum("imp.ImportedMessage_Owner", ImportedMessage_Owner_name, ImportedMessage_Owner_value) +} diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/imp.proto b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/imp.proto new file mode 100644 index 00000000..156e078d --- /dev/null +++ b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/imp.proto @@ -0,0 +1,70 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2010 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// 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 +// OWNER 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. + +syntax = "proto2"; + +package imp; + +import "imp2.proto"; +import "imp3.proto"; + +message ImportedMessage { + required int64 field = 1; + + // The forwarded getters for these fields are fiddly to get right. + optional ImportedMessage2 local_msg = 2; + optional ForeignImportedMessage foreign_msg = 3; // in imp3.proto + optional Owner enum_field = 4; + oneof union { + int32 state = 9; + } + + repeated string name = 5; + repeated Owner boss = 6; + repeated ImportedMessage2 memo = 7; + + map msg_map = 8; + + enum Owner { + DAVE = 1; + MIKE = 2; + } + + extensions 90 to 100; +} + +message ImportedMessage2 { +} + +message ImportedExtendable { + option message_set_wire_format = true; + extensions 100 to max; +} diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/imp2.proto b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/imp2.proto new file mode 100644 index 00000000..3bb0632b --- /dev/null +++ b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/imp2.proto @@ -0,0 +1,43 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2011 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// 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 +// OWNER 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. + +syntax = "proto2"; + +package imp; + +message PubliclyImportedMessage { + optional int64 field = 1; +} + +enum PubliclyImportedEnum { + GLASSES = 1; + HAIR = 2; +} diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/imp3.proto b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/imp3.proto new file mode 100644 index 00000000..58fc7598 --- /dev/null +++ b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/imp3.proto @@ -0,0 +1,38 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2012 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// 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 +// OWNER 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. + +syntax = "proto2"; + +package imp; + +message ForeignImportedMessage { + optional string tuber = 1; +} diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/main_test.go b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/main_test.go new file mode 100644 index 00000000..f9b5ccf2 --- /dev/null +++ b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/main_test.go @@ -0,0 +1,46 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2010 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// 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 +// OWNER 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. + +// A simple binary to link together the protocol buffers in this test. + +package testdata + +import ( + "testing" + + mytestpb "./my_test" + multipb "github.com/golang/protobuf/protoc-gen-go/testdata/multi" +) + +func TestLink(t *testing.T) { + _ = &multipb.Multi1{} + _ = &mytestpb.Request{} +} diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/multi/multi1.proto b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/multi/multi1.proto new file mode 100644 index 00000000..0da6e0af --- /dev/null +++ b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/multi/multi1.proto @@ -0,0 +1,44 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2010 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// 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 +// OWNER 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. + +syntax = "proto2"; + +import "multi/multi2.proto"; +import "multi/multi3.proto"; + +package multitest; + +message Multi1 { + required Multi2 multi2 = 1; + optional Multi2.Color color = 2; + optional Multi3.HatType hat_type = 3; +} + diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/multi/multi2.proto b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/multi/multi2.proto new file mode 100644 index 00000000..e6bfc71b --- /dev/null +++ b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/multi/multi2.proto @@ -0,0 +1,46 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2010 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// 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 +// OWNER 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. + +syntax = "proto2"; + +package multitest; + +message Multi2 { + required int32 required_value = 1; + + enum Color { + BLUE = 1; + GREEN = 2; + RED = 3; + }; + optional Color color = 2; +} + diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/multi/multi3.proto b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/multi/multi3.proto new file mode 100644 index 00000000..146c255b --- /dev/null +++ b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/multi/multi3.proto @@ -0,0 +1,43 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2010 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// 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 +// OWNER 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. + +syntax = "proto2"; + +package multitest; + +message Multi3 { + enum HatType { + FEDORA = 1; + FEZ = 2; + }; + optional HatType hat_type = 1; +} + diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/my_test/test.pb.go b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/my_test/test.pb.go new file mode 100644 index 00000000..1954e3fb --- /dev/null +++ b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/my_test/test.pb.go @@ -0,0 +1,870 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: my_test/test.proto + +/* +Package my_test is a generated protocol buffer package. + +This package holds interesting messages. + +It is generated from these files: + my_test/test.proto + +It has these top-level messages: + Request + Reply + OtherBase + ReplyExtensions + OtherReplyExtensions + OldReply + Communique +*/ +package my_test + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" +import _ "github.com/golang/protobuf/protoc-gen-go/testdata/multi" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package + +type HatType int32 + +const ( + // deliberately skipping 0 + HatType_FEDORA HatType = 1 + HatType_FEZ HatType = 2 +) + +var HatType_name = map[int32]string{ + 1: "FEDORA", + 2: "FEZ", +} +var HatType_value = map[string]int32{ + "FEDORA": 1, + "FEZ": 2, +} + +func (x HatType) Enum() *HatType { + p := new(HatType) + *p = x + return p +} +func (x HatType) String() string { + return proto.EnumName(HatType_name, int32(x)) +} +func (x *HatType) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(HatType_value, data, "HatType") + if err != nil { + return err + } + *x = HatType(value) + return nil +} + +// This enum represents days of the week. +type Days int32 + +const ( + Days_MONDAY Days = 1 + Days_TUESDAY Days = 2 + Days_LUNDI Days = 1 +) + +var Days_name = map[int32]string{ + 1: "MONDAY", + 2: "TUESDAY", + // Duplicate value: 1: "LUNDI", +} +var Days_value = map[string]int32{ + "MONDAY": 1, + "TUESDAY": 2, + "LUNDI": 1, +} + +func (x Days) Enum() *Days { + p := new(Days) + *p = x + return p +} +func (x Days) String() string { + return proto.EnumName(Days_name, int32(x)) +} +func (x *Days) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(Days_value, data, "Days") + if err != nil { + return err + } + *x = Days(value) + return nil +} + +type Request_Color int32 + +const ( + Request_RED Request_Color = 0 + Request_GREEN Request_Color = 1 + Request_BLUE Request_Color = 2 +) + +var Request_Color_name = map[int32]string{ + 0: "RED", + 1: "GREEN", + 2: "BLUE", +} +var Request_Color_value = map[string]int32{ + "RED": 0, + "GREEN": 1, + "BLUE": 2, +} + +func (x Request_Color) Enum() *Request_Color { + p := new(Request_Color) + *p = x + return p +} +func (x Request_Color) String() string { + return proto.EnumName(Request_Color_name, int32(x)) +} +func (x *Request_Color) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(Request_Color_value, data, "Request_Color") + if err != nil { + return err + } + *x = Request_Color(value) + return nil +} + +type Reply_Entry_Game int32 + +const ( + Reply_Entry_FOOTBALL Reply_Entry_Game = 1 + Reply_Entry_TENNIS Reply_Entry_Game = 2 +) + +var Reply_Entry_Game_name = map[int32]string{ + 1: "FOOTBALL", + 2: "TENNIS", +} +var Reply_Entry_Game_value = map[string]int32{ + "FOOTBALL": 1, + "TENNIS": 2, +} + +func (x Reply_Entry_Game) Enum() *Reply_Entry_Game { + p := new(Reply_Entry_Game) + *p = x + return p +} +func (x Reply_Entry_Game) String() string { + return proto.EnumName(Reply_Entry_Game_name, int32(x)) +} +func (x *Reply_Entry_Game) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(Reply_Entry_Game_value, data, "Reply_Entry_Game") + if err != nil { + return err + } + *x = Reply_Entry_Game(value) + return nil +} + +// This is a message that might be sent somewhere. +type Request struct { + Key []int64 `protobuf:"varint,1,rep,name=key" json:"key,omitempty"` + // optional imp.ImportedMessage imported_message = 2; + Hue *Request_Color `protobuf:"varint,3,opt,name=hue,enum=my.test.Request_Color" json:"hue,omitempty"` + Hat *HatType `protobuf:"varint,4,opt,name=hat,enum=my.test.HatType,def=1" json:"hat,omitempty"` + // optional imp.ImportedMessage.Owner owner = 6; + Deadline *float32 `protobuf:"fixed32,7,opt,name=deadline,def=inf" json:"deadline,omitempty"` + Somegroup *Request_SomeGroup `protobuf:"group,8,opt,name=SomeGroup,json=somegroup" json:"somegroup,omitempty"` + // This is a map field. It will generate map[int32]string. + NameMapping map[int32]string `protobuf:"bytes,14,rep,name=name_mapping,json=nameMapping" json:"name_mapping,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + // This is a map field whose value type is a message. + MsgMapping map[int64]*Reply `protobuf:"bytes,15,rep,name=msg_mapping,json=msgMapping" json:"msg_mapping,omitempty" protobuf_key:"zigzag64,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + Reset_ *int32 `protobuf:"varint,12,opt,name=reset" json:"reset,omitempty"` + // This field should not conflict with any getters. + GetKey_ *string `protobuf:"bytes,16,opt,name=get_key,json=getKey" json:"get_key,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *Request) Reset() { *m = Request{} } +func (m *Request) String() string { return proto.CompactTextString(m) } +func (*Request) ProtoMessage() {} + +const Default_Request_Hat HatType = HatType_FEDORA + +var Default_Request_Deadline float32 = float32(math.Inf(1)) + +func (m *Request) GetKey() []int64 { + if m != nil { + return m.Key + } + return nil +} + +func (m *Request) GetHue() Request_Color { + if m != nil && m.Hue != nil { + return *m.Hue + } + return Request_RED +} + +func (m *Request) GetHat() HatType { + if m != nil && m.Hat != nil { + return *m.Hat + } + return Default_Request_Hat +} + +func (m *Request) GetDeadline() float32 { + if m != nil && m.Deadline != nil { + return *m.Deadline + } + return Default_Request_Deadline +} + +func (m *Request) GetSomegroup() *Request_SomeGroup { + if m != nil { + return m.Somegroup + } + return nil +} + +func (m *Request) GetNameMapping() map[int32]string { + if m != nil { + return m.NameMapping + } + return nil +} + +func (m *Request) GetMsgMapping() map[int64]*Reply { + if m != nil { + return m.MsgMapping + } + return nil +} + +func (m *Request) GetReset_() int32 { + if m != nil && m.Reset_ != nil { + return *m.Reset_ + } + return 0 +} + +func (m *Request) GetGetKey_() string { + if m != nil && m.GetKey_ != nil { + return *m.GetKey_ + } + return "" +} + +type Request_SomeGroup struct { + GroupField *int32 `protobuf:"varint,9,opt,name=group_field,json=groupField" json:"group_field,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *Request_SomeGroup) Reset() { *m = Request_SomeGroup{} } +func (m *Request_SomeGroup) String() string { return proto.CompactTextString(m) } +func (*Request_SomeGroup) ProtoMessage() {} + +func (m *Request_SomeGroup) GetGroupField() int32 { + if m != nil && m.GroupField != nil { + return *m.GroupField + } + return 0 +} + +type Reply struct { + Found []*Reply_Entry `protobuf:"bytes,1,rep,name=found" json:"found,omitempty"` + CompactKeys []int32 `protobuf:"varint,2,rep,packed,name=compact_keys,json=compactKeys" json:"compact_keys,omitempty"` + proto.XXX_InternalExtensions `json:"-"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *Reply) Reset() { *m = Reply{} } +func (m *Reply) String() string { return proto.CompactTextString(m) } +func (*Reply) ProtoMessage() {} + +var extRange_Reply = []proto.ExtensionRange{ + {100, 536870911}, +} + +func (*Reply) ExtensionRangeArray() []proto.ExtensionRange { + return extRange_Reply +} + +func (m *Reply) GetFound() []*Reply_Entry { + if m != nil { + return m.Found + } + return nil +} + +func (m *Reply) GetCompactKeys() []int32 { + if m != nil { + return m.CompactKeys + } + return nil +} + +type Reply_Entry struct { + KeyThatNeeds_1234Camel_CasIng *int64 `protobuf:"varint,1,req,name=key_that_needs_1234camel_CasIng,json=keyThatNeeds1234camelCasIng" json:"key_that_needs_1234camel_CasIng,omitempty"` + Value *int64 `protobuf:"varint,2,opt,name=value,def=7" json:"value,omitempty"` + XMyFieldName_2 *int64 `protobuf:"varint,3,opt,name=_my_field_name_2,json=MyFieldName2" json:"_my_field_name_2,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *Reply_Entry) Reset() { *m = Reply_Entry{} } +func (m *Reply_Entry) String() string { return proto.CompactTextString(m) } +func (*Reply_Entry) ProtoMessage() {} + +const Default_Reply_Entry_Value int64 = 7 + +func (m *Reply_Entry) GetKeyThatNeeds_1234Camel_CasIng() int64 { + if m != nil && m.KeyThatNeeds_1234Camel_CasIng != nil { + return *m.KeyThatNeeds_1234Camel_CasIng + } + return 0 +} + +func (m *Reply_Entry) GetValue() int64 { + if m != nil && m.Value != nil { + return *m.Value + } + return Default_Reply_Entry_Value +} + +func (m *Reply_Entry) GetXMyFieldName_2() int64 { + if m != nil && m.XMyFieldName_2 != nil { + return *m.XMyFieldName_2 + } + return 0 +} + +type OtherBase struct { + Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + proto.XXX_InternalExtensions `json:"-"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *OtherBase) Reset() { *m = OtherBase{} } +func (m *OtherBase) String() string { return proto.CompactTextString(m) } +func (*OtherBase) ProtoMessage() {} + +var extRange_OtherBase = []proto.ExtensionRange{ + {100, 536870911}, +} + +func (*OtherBase) ExtensionRangeArray() []proto.ExtensionRange { + return extRange_OtherBase +} + +func (m *OtherBase) GetName() string { + if m != nil && m.Name != nil { + return *m.Name + } + return "" +} + +type ReplyExtensions struct { + XXX_unrecognized []byte `json:"-"` +} + +func (m *ReplyExtensions) Reset() { *m = ReplyExtensions{} } +func (m *ReplyExtensions) String() string { return proto.CompactTextString(m) } +func (*ReplyExtensions) ProtoMessage() {} + +var E_ReplyExtensions_Time = &proto.ExtensionDesc{ + ExtendedType: (*Reply)(nil), + ExtensionType: (*float64)(nil), + Field: 101, + Name: "my.test.ReplyExtensions.time", + Tag: "fixed64,101,opt,name=time", + Filename: "my_test/test.proto", +} + +var E_ReplyExtensions_Carrot = &proto.ExtensionDesc{ + ExtendedType: (*Reply)(nil), + ExtensionType: (*ReplyExtensions)(nil), + Field: 105, + Name: "my.test.ReplyExtensions.carrot", + Tag: "bytes,105,opt,name=carrot", + Filename: "my_test/test.proto", +} + +var E_ReplyExtensions_Donut = &proto.ExtensionDesc{ + ExtendedType: (*OtherBase)(nil), + ExtensionType: (*ReplyExtensions)(nil), + Field: 101, + Name: "my.test.ReplyExtensions.donut", + Tag: "bytes,101,opt,name=donut", + Filename: "my_test/test.proto", +} + +type OtherReplyExtensions struct { + Key *int32 `protobuf:"varint,1,opt,name=key" json:"key,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *OtherReplyExtensions) Reset() { *m = OtherReplyExtensions{} } +func (m *OtherReplyExtensions) String() string { return proto.CompactTextString(m) } +func (*OtherReplyExtensions) ProtoMessage() {} + +func (m *OtherReplyExtensions) GetKey() int32 { + if m != nil && m.Key != nil { + return *m.Key + } + return 0 +} + +type OldReply struct { + proto.XXX_InternalExtensions `json:"-"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *OldReply) Reset() { *m = OldReply{} } +func (m *OldReply) String() string { return proto.CompactTextString(m) } +func (*OldReply) ProtoMessage() {} + +func (m *OldReply) Marshal() ([]byte, error) { + return proto.MarshalMessageSet(&m.XXX_InternalExtensions) +} +func (m *OldReply) Unmarshal(buf []byte) error { + return proto.UnmarshalMessageSet(buf, &m.XXX_InternalExtensions) +} +func (m *OldReply) MarshalJSON() ([]byte, error) { + return proto.MarshalMessageSetJSON(&m.XXX_InternalExtensions) +} +func (m *OldReply) UnmarshalJSON(buf []byte) error { + return proto.UnmarshalMessageSetJSON(buf, &m.XXX_InternalExtensions) +} + +// ensure OldReply satisfies proto.Marshaler and proto.Unmarshaler +var _ proto.Marshaler = (*OldReply)(nil) +var _ proto.Unmarshaler = (*OldReply)(nil) + +var extRange_OldReply = []proto.ExtensionRange{ + {100, 2147483646}, +} + +func (*OldReply) ExtensionRangeArray() []proto.ExtensionRange { + return extRange_OldReply +} + +type Communique struct { + MakeMeCry *bool `protobuf:"varint,1,opt,name=make_me_cry,json=makeMeCry" json:"make_me_cry,omitempty"` + // This is a oneof, called "union". + // + // Types that are valid to be assigned to Union: + // *Communique_Number + // *Communique_Name + // *Communique_Data + // *Communique_TempC + // *Communique_Height + // *Communique_Today + // *Communique_Maybe + // *Communique_Delta_ + // *Communique_Msg + // *Communique_Somegroup + Union isCommunique_Union `protobuf_oneof:"union"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *Communique) Reset() { *m = Communique{} } +func (m *Communique) String() string { return proto.CompactTextString(m) } +func (*Communique) ProtoMessage() {} + +type isCommunique_Union interface { + isCommunique_Union() +} + +type Communique_Number struct { + Number int32 `protobuf:"varint,5,opt,name=number,oneof"` +} +type Communique_Name struct { + Name string `protobuf:"bytes,6,opt,name=name,oneof"` +} +type Communique_Data struct { + Data []byte `protobuf:"bytes,7,opt,name=data,oneof"` +} +type Communique_TempC struct { + TempC float64 `protobuf:"fixed64,8,opt,name=temp_c,json=tempC,oneof"` +} +type Communique_Height struct { + Height float32 `protobuf:"fixed32,9,opt,name=height,oneof"` +} +type Communique_Today struct { + Today Days `protobuf:"varint,10,opt,name=today,enum=my.test.Days,oneof"` +} +type Communique_Maybe struct { + Maybe bool `protobuf:"varint,11,opt,name=maybe,oneof"` +} +type Communique_Delta_ struct { + Delta int32 `protobuf:"zigzag32,12,opt,name=delta,oneof"` +} +type Communique_Msg struct { + Msg *Reply `protobuf:"bytes,13,opt,name=msg,oneof"` +} +type Communique_Somegroup struct { + Somegroup *Communique_SomeGroup `protobuf:"group,14,opt,name=SomeGroup,json=somegroup,oneof"` +} + +func (*Communique_Number) isCommunique_Union() {} +func (*Communique_Name) isCommunique_Union() {} +func (*Communique_Data) isCommunique_Union() {} +func (*Communique_TempC) isCommunique_Union() {} +func (*Communique_Height) isCommunique_Union() {} +func (*Communique_Today) isCommunique_Union() {} +func (*Communique_Maybe) isCommunique_Union() {} +func (*Communique_Delta_) isCommunique_Union() {} +func (*Communique_Msg) isCommunique_Union() {} +func (*Communique_Somegroup) isCommunique_Union() {} + +func (m *Communique) GetUnion() isCommunique_Union { + if m != nil { + return m.Union + } + return nil +} + +func (m *Communique) GetMakeMeCry() bool { + if m != nil && m.MakeMeCry != nil { + return *m.MakeMeCry + } + return false +} + +func (m *Communique) GetNumber() int32 { + if x, ok := m.GetUnion().(*Communique_Number); ok { + return x.Number + } + return 0 +} + +func (m *Communique) GetName() string { + if x, ok := m.GetUnion().(*Communique_Name); ok { + return x.Name + } + return "" +} + +func (m *Communique) GetData() []byte { + if x, ok := m.GetUnion().(*Communique_Data); ok { + return x.Data + } + return nil +} + +func (m *Communique) GetTempC() float64 { + if x, ok := m.GetUnion().(*Communique_TempC); ok { + return x.TempC + } + return 0 +} + +func (m *Communique) GetHeight() float32 { + if x, ok := m.GetUnion().(*Communique_Height); ok { + return x.Height + } + return 0 +} + +func (m *Communique) GetToday() Days { + if x, ok := m.GetUnion().(*Communique_Today); ok { + return x.Today + } + return Days_MONDAY +} + +func (m *Communique) GetMaybe() bool { + if x, ok := m.GetUnion().(*Communique_Maybe); ok { + return x.Maybe + } + return false +} + +func (m *Communique) GetDelta() int32 { + if x, ok := m.GetUnion().(*Communique_Delta_); ok { + return x.Delta + } + return 0 +} + +func (m *Communique) GetMsg() *Reply { + if x, ok := m.GetUnion().(*Communique_Msg); ok { + return x.Msg + } + return nil +} + +func (m *Communique) GetSomegroup() *Communique_SomeGroup { + if x, ok := m.GetUnion().(*Communique_Somegroup); ok { + return x.Somegroup + } + return nil +} + +// XXX_OneofFuncs is for the internal use of the proto package. +func (*Communique) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { + return _Communique_OneofMarshaler, _Communique_OneofUnmarshaler, _Communique_OneofSizer, []interface{}{ + (*Communique_Number)(nil), + (*Communique_Name)(nil), + (*Communique_Data)(nil), + (*Communique_TempC)(nil), + (*Communique_Height)(nil), + (*Communique_Today)(nil), + (*Communique_Maybe)(nil), + (*Communique_Delta_)(nil), + (*Communique_Msg)(nil), + (*Communique_Somegroup)(nil), + } +} + +func _Communique_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { + m := msg.(*Communique) + // union + switch x := m.Union.(type) { + case *Communique_Number: + b.EncodeVarint(5<<3 | proto.WireVarint) + b.EncodeVarint(uint64(x.Number)) + case *Communique_Name: + b.EncodeVarint(6<<3 | proto.WireBytes) + b.EncodeStringBytes(x.Name) + case *Communique_Data: + b.EncodeVarint(7<<3 | proto.WireBytes) + b.EncodeRawBytes(x.Data) + case *Communique_TempC: + b.EncodeVarint(8<<3 | proto.WireFixed64) + b.EncodeFixed64(math.Float64bits(x.TempC)) + case *Communique_Height: + b.EncodeVarint(9<<3 | proto.WireFixed32) + b.EncodeFixed32(uint64(math.Float32bits(x.Height))) + case *Communique_Today: + b.EncodeVarint(10<<3 | proto.WireVarint) + b.EncodeVarint(uint64(x.Today)) + case *Communique_Maybe: + t := uint64(0) + if x.Maybe { + t = 1 + } + b.EncodeVarint(11<<3 | proto.WireVarint) + b.EncodeVarint(t) + case *Communique_Delta_: + b.EncodeVarint(12<<3 | proto.WireVarint) + b.EncodeZigzag32(uint64(x.Delta)) + case *Communique_Msg: + b.EncodeVarint(13<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.Msg); err != nil { + return err + } + case *Communique_Somegroup: + b.EncodeVarint(14<<3 | proto.WireStartGroup) + if err := b.Marshal(x.Somegroup); err != nil { + return err + } + b.EncodeVarint(14<<3 | proto.WireEndGroup) + case nil: + default: + return fmt.Errorf("Communique.Union has unexpected type %T", x) + } + return nil +} + +func _Communique_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { + m := msg.(*Communique) + switch tag { + case 5: // union.number + if wire != proto.WireVarint { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeVarint() + m.Union = &Communique_Number{int32(x)} + return true, err + case 6: // union.name + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeStringBytes() + m.Union = &Communique_Name{x} + return true, err + case 7: // union.data + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeRawBytes(true) + m.Union = &Communique_Data{x} + return true, err + case 8: // union.temp_c + if wire != proto.WireFixed64 { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeFixed64() + m.Union = &Communique_TempC{math.Float64frombits(x)} + return true, err + case 9: // union.height + if wire != proto.WireFixed32 { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeFixed32() + m.Union = &Communique_Height{math.Float32frombits(uint32(x))} + return true, err + case 10: // union.today + if wire != proto.WireVarint { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeVarint() + m.Union = &Communique_Today{Days(x)} + return true, err + case 11: // union.maybe + if wire != proto.WireVarint { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeVarint() + m.Union = &Communique_Maybe{x != 0} + return true, err + case 12: // union.delta + if wire != proto.WireVarint { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeZigzag32() + m.Union = &Communique_Delta_{int32(x)} + return true, err + case 13: // union.msg + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(Reply) + err := b.DecodeMessage(msg) + m.Union = &Communique_Msg{msg} + return true, err + case 14: // union.somegroup + if wire != proto.WireStartGroup { + return true, proto.ErrInternalBadWireType + } + msg := new(Communique_SomeGroup) + err := b.DecodeGroup(msg) + m.Union = &Communique_Somegroup{msg} + return true, err + default: + return false, nil + } +} + +func _Communique_OneofSizer(msg proto.Message) (n int) { + m := msg.(*Communique) + // union + switch x := m.Union.(type) { + case *Communique_Number: + n += proto.SizeVarint(5<<3 | proto.WireVarint) + n += proto.SizeVarint(uint64(x.Number)) + case *Communique_Name: + n += proto.SizeVarint(6<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(len(x.Name))) + n += len(x.Name) + case *Communique_Data: + n += proto.SizeVarint(7<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(len(x.Data))) + n += len(x.Data) + case *Communique_TempC: + n += proto.SizeVarint(8<<3 | proto.WireFixed64) + n += 8 + case *Communique_Height: + n += proto.SizeVarint(9<<3 | proto.WireFixed32) + n += 4 + case *Communique_Today: + n += proto.SizeVarint(10<<3 | proto.WireVarint) + n += proto.SizeVarint(uint64(x.Today)) + case *Communique_Maybe: + n += proto.SizeVarint(11<<3 | proto.WireVarint) + n += 1 + case *Communique_Delta_: + n += proto.SizeVarint(12<<3 | proto.WireVarint) + n += proto.SizeVarint(uint64((uint32(x.Delta) << 1) ^ uint32((int32(x.Delta) >> 31)))) + case *Communique_Msg: + s := proto.Size(x.Msg) + n += proto.SizeVarint(13<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *Communique_Somegroup: + n += proto.SizeVarint(14<<3 | proto.WireStartGroup) + n += proto.Size(x.Somegroup) + n += proto.SizeVarint(14<<3 | proto.WireEndGroup) + case nil: + default: + panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) + } + return n +} + +type Communique_SomeGroup struct { + Member *string `protobuf:"bytes,15,opt,name=member" json:"member,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *Communique_SomeGroup) Reset() { *m = Communique_SomeGroup{} } +func (m *Communique_SomeGroup) String() string { return proto.CompactTextString(m) } +func (*Communique_SomeGroup) ProtoMessage() {} + +func (m *Communique_SomeGroup) GetMember() string { + if m != nil && m.Member != nil { + return *m.Member + } + return "" +} + +type Communique_Delta struct { + XXX_unrecognized []byte `json:"-"` +} + +func (m *Communique_Delta) Reset() { *m = Communique_Delta{} } +func (m *Communique_Delta) String() string { return proto.CompactTextString(m) } +func (*Communique_Delta) ProtoMessage() {} + +var E_Tag = &proto.ExtensionDesc{ + ExtendedType: (*Reply)(nil), + ExtensionType: (*string)(nil), + Field: 103, + Name: "my.test.tag", + Tag: "bytes,103,opt,name=tag", + Filename: "my_test/test.proto", +} + +var E_Donut = &proto.ExtensionDesc{ + ExtendedType: (*Reply)(nil), + ExtensionType: (*OtherReplyExtensions)(nil), + Field: 106, + Name: "my.test.donut", + Tag: "bytes,106,opt,name=donut", + Filename: "my_test/test.proto", +} + +func init() { + proto.RegisterType((*Request)(nil), "my.test.Request") + proto.RegisterType((*Request_SomeGroup)(nil), "my.test.Request.SomeGroup") + proto.RegisterType((*Reply)(nil), "my.test.Reply") + proto.RegisterType((*Reply_Entry)(nil), "my.test.Reply.Entry") + proto.RegisterType((*OtherBase)(nil), "my.test.OtherBase") + proto.RegisterType((*ReplyExtensions)(nil), "my.test.ReplyExtensions") + proto.RegisterType((*OtherReplyExtensions)(nil), "my.test.OtherReplyExtensions") + proto.RegisterType((*OldReply)(nil), "my.test.OldReply") + proto.RegisterType((*Communique)(nil), "my.test.Communique") + proto.RegisterType((*Communique_SomeGroup)(nil), "my.test.Communique.SomeGroup") + proto.RegisterType((*Communique_Delta)(nil), "my.test.Communique.Delta") + proto.RegisterEnum("my.test.HatType", HatType_name, HatType_value) + proto.RegisterEnum("my.test.Days", Days_name, Days_value) + proto.RegisterEnum("my.test.Request_Color", Request_Color_name, Request_Color_value) + proto.RegisterEnum("my.test.Reply_Entry_Game", Reply_Entry_Game_name, Reply_Entry_Game_value) + proto.RegisterExtension(E_ReplyExtensions_Time) + proto.RegisterExtension(E_ReplyExtensions_Carrot) + proto.RegisterExtension(E_ReplyExtensions_Donut) + proto.RegisterExtension(E_Tag) + proto.RegisterExtension(E_Donut) +} diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/my_test/test.pb.go.golden b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/my_test/test.pb.go.golden new file mode 100644 index 00000000..1954e3fb --- /dev/null +++ b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/my_test/test.pb.go.golden @@ -0,0 +1,870 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: my_test/test.proto + +/* +Package my_test is a generated protocol buffer package. + +This package holds interesting messages. + +It is generated from these files: + my_test/test.proto + +It has these top-level messages: + Request + Reply + OtherBase + ReplyExtensions + OtherReplyExtensions + OldReply + Communique +*/ +package my_test + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" +import _ "github.com/golang/protobuf/protoc-gen-go/testdata/multi" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package + +type HatType int32 + +const ( + // deliberately skipping 0 + HatType_FEDORA HatType = 1 + HatType_FEZ HatType = 2 +) + +var HatType_name = map[int32]string{ + 1: "FEDORA", + 2: "FEZ", +} +var HatType_value = map[string]int32{ + "FEDORA": 1, + "FEZ": 2, +} + +func (x HatType) Enum() *HatType { + p := new(HatType) + *p = x + return p +} +func (x HatType) String() string { + return proto.EnumName(HatType_name, int32(x)) +} +func (x *HatType) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(HatType_value, data, "HatType") + if err != nil { + return err + } + *x = HatType(value) + return nil +} + +// This enum represents days of the week. +type Days int32 + +const ( + Days_MONDAY Days = 1 + Days_TUESDAY Days = 2 + Days_LUNDI Days = 1 +) + +var Days_name = map[int32]string{ + 1: "MONDAY", + 2: "TUESDAY", + // Duplicate value: 1: "LUNDI", +} +var Days_value = map[string]int32{ + "MONDAY": 1, + "TUESDAY": 2, + "LUNDI": 1, +} + +func (x Days) Enum() *Days { + p := new(Days) + *p = x + return p +} +func (x Days) String() string { + return proto.EnumName(Days_name, int32(x)) +} +func (x *Days) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(Days_value, data, "Days") + if err != nil { + return err + } + *x = Days(value) + return nil +} + +type Request_Color int32 + +const ( + Request_RED Request_Color = 0 + Request_GREEN Request_Color = 1 + Request_BLUE Request_Color = 2 +) + +var Request_Color_name = map[int32]string{ + 0: "RED", + 1: "GREEN", + 2: "BLUE", +} +var Request_Color_value = map[string]int32{ + "RED": 0, + "GREEN": 1, + "BLUE": 2, +} + +func (x Request_Color) Enum() *Request_Color { + p := new(Request_Color) + *p = x + return p +} +func (x Request_Color) String() string { + return proto.EnumName(Request_Color_name, int32(x)) +} +func (x *Request_Color) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(Request_Color_value, data, "Request_Color") + if err != nil { + return err + } + *x = Request_Color(value) + return nil +} + +type Reply_Entry_Game int32 + +const ( + Reply_Entry_FOOTBALL Reply_Entry_Game = 1 + Reply_Entry_TENNIS Reply_Entry_Game = 2 +) + +var Reply_Entry_Game_name = map[int32]string{ + 1: "FOOTBALL", + 2: "TENNIS", +} +var Reply_Entry_Game_value = map[string]int32{ + "FOOTBALL": 1, + "TENNIS": 2, +} + +func (x Reply_Entry_Game) Enum() *Reply_Entry_Game { + p := new(Reply_Entry_Game) + *p = x + return p +} +func (x Reply_Entry_Game) String() string { + return proto.EnumName(Reply_Entry_Game_name, int32(x)) +} +func (x *Reply_Entry_Game) UnmarshalJSON(data []byte) error { + value, err := proto.UnmarshalJSONEnum(Reply_Entry_Game_value, data, "Reply_Entry_Game") + if err != nil { + return err + } + *x = Reply_Entry_Game(value) + return nil +} + +// This is a message that might be sent somewhere. +type Request struct { + Key []int64 `protobuf:"varint,1,rep,name=key" json:"key,omitempty"` + // optional imp.ImportedMessage imported_message = 2; + Hue *Request_Color `protobuf:"varint,3,opt,name=hue,enum=my.test.Request_Color" json:"hue,omitempty"` + Hat *HatType `protobuf:"varint,4,opt,name=hat,enum=my.test.HatType,def=1" json:"hat,omitempty"` + // optional imp.ImportedMessage.Owner owner = 6; + Deadline *float32 `protobuf:"fixed32,7,opt,name=deadline,def=inf" json:"deadline,omitempty"` + Somegroup *Request_SomeGroup `protobuf:"group,8,opt,name=SomeGroup,json=somegroup" json:"somegroup,omitempty"` + // This is a map field. It will generate map[int32]string. + NameMapping map[int32]string `protobuf:"bytes,14,rep,name=name_mapping,json=nameMapping" json:"name_mapping,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + // This is a map field whose value type is a message. + MsgMapping map[int64]*Reply `protobuf:"bytes,15,rep,name=msg_mapping,json=msgMapping" json:"msg_mapping,omitempty" protobuf_key:"zigzag64,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + Reset_ *int32 `protobuf:"varint,12,opt,name=reset" json:"reset,omitempty"` + // This field should not conflict with any getters. + GetKey_ *string `protobuf:"bytes,16,opt,name=get_key,json=getKey" json:"get_key,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *Request) Reset() { *m = Request{} } +func (m *Request) String() string { return proto.CompactTextString(m) } +func (*Request) ProtoMessage() {} + +const Default_Request_Hat HatType = HatType_FEDORA + +var Default_Request_Deadline float32 = float32(math.Inf(1)) + +func (m *Request) GetKey() []int64 { + if m != nil { + return m.Key + } + return nil +} + +func (m *Request) GetHue() Request_Color { + if m != nil && m.Hue != nil { + return *m.Hue + } + return Request_RED +} + +func (m *Request) GetHat() HatType { + if m != nil && m.Hat != nil { + return *m.Hat + } + return Default_Request_Hat +} + +func (m *Request) GetDeadline() float32 { + if m != nil && m.Deadline != nil { + return *m.Deadline + } + return Default_Request_Deadline +} + +func (m *Request) GetSomegroup() *Request_SomeGroup { + if m != nil { + return m.Somegroup + } + return nil +} + +func (m *Request) GetNameMapping() map[int32]string { + if m != nil { + return m.NameMapping + } + return nil +} + +func (m *Request) GetMsgMapping() map[int64]*Reply { + if m != nil { + return m.MsgMapping + } + return nil +} + +func (m *Request) GetReset_() int32 { + if m != nil && m.Reset_ != nil { + return *m.Reset_ + } + return 0 +} + +func (m *Request) GetGetKey_() string { + if m != nil && m.GetKey_ != nil { + return *m.GetKey_ + } + return "" +} + +type Request_SomeGroup struct { + GroupField *int32 `protobuf:"varint,9,opt,name=group_field,json=groupField" json:"group_field,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *Request_SomeGroup) Reset() { *m = Request_SomeGroup{} } +func (m *Request_SomeGroup) String() string { return proto.CompactTextString(m) } +func (*Request_SomeGroup) ProtoMessage() {} + +func (m *Request_SomeGroup) GetGroupField() int32 { + if m != nil && m.GroupField != nil { + return *m.GroupField + } + return 0 +} + +type Reply struct { + Found []*Reply_Entry `protobuf:"bytes,1,rep,name=found" json:"found,omitempty"` + CompactKeys []int32 `protobuf:"varint,2,rep,packed,name=compact_keys,json=compactKeys" json:"compact_keys,omitempty"` + proto.XXX_InternalExtensions `json:"-"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *Reply) Reset() { *m = Reply{} } +func (m *Reply) String() string { return proto.CompactTextString(m) } +func (*Reply) ProtoMessage() {} + +var extRange_Reply = []proto.ExtensionRange{ + {100, 536870911}, +} + +func (*Reply) ExtensionRangeArray() []proto.ExtensionRange { + return extRange_Reply +} + +func (m *Reply) GetFound() []*Reply_Entry { + if m != nil { + return m.Found + } + return nil +} + +func (m *Reply) GetCompactKeys() []int32 { + if m != nil { + return m.CompactKeys + } + return nil +} + +type Reply_Entry struct { + KeyThatNeeds_1234Camel_CasIng *int64 `protobuf:"varint,1,req,name=key_that_needs_1234camel_CasIng,json=keyThatNeeds1234camelCasIng" json:"key_that_needs_1234camel_CasIng,omitempty"` + Value *int64 `protobuf:"varint,2,opt,name=value,def=7" json:"value,omitempty"` + XMyFieldName_2 *int64 `protobuf:"varint,3,opt,name=_my_field_name_2,json=MyFieldName2" json:"_my_field_name_2,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *Reply_Entry) Reset() { *m = Reply_Entry{} } +func (m *Reply_Entry) String() string { return proto.CompactTextString(m) } +func (*Reply_Entry) ProtoMessage() {} + +const Default_Reply_Entry_Value int64 = 7 + +func (m *Reply_Entry) GetKeyThatNeeds_1234Camel_CasIng() int64 { + if m != nil && m.KeyThatNeeds_1234Camel_CasIng != nil { + return *m.KeyThatNeeds_1234Camel_CasIng + } + return 0 +} + +func (m *Reply_Entry) GetValue() int64 { + if m != nil && m.Value != nil { + return *m.Value + } + return Default_Reply_Entry_Value +} + +func (m *Reply_Entry) GetXMyFieldName_2() int64 { + if m != nil && m.XMyFieldName_2 != nil { + return *m.XMyFieldName_2 + } + return 0 +} + +type OtherBase struct { + Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + proto.XXX_InternalExtensions `json:"-"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *OtherBase) Reset() { *m = OtherBase{} } +func (m *OtherBase) String() string { return proto.CompactTextString(m) } +func (*OtherBase) ProtoMessage() {} + +var extRange_OtherBase = []proto.ExtensionRange{ + {100, 536870911}, +} + +func (*OtherBase) ExtensionRangeArray() []proto.ExtensionRange { + return extRange_OtherBase +} + +func (m *OtherBase) GetName() string { + if m != nil && m.Name != nil { + return *m.Name + } + return "" +} + +type ReplyExtensions struct { + XXX_unrecognized []byte `json:"-"` +} + +func (m *ReplyExtensions) Reset() { *m = ReplyExtensions{} } +func (m *ReplyExtensions) String() string { return proto.CompactTextString(m) } +func (*ReplyExtensions) ProtoMessage() {} + +var E_ReplyExtensions_Time = &proto.ExtensionDesc{ + ExtendedType: (*Reply)(nil), + ExtensionType: (*float64)(nil), + Field: 101, + Name: "my.test.ReplyExtensions.time", + Tag: "fixed64,101,opt,name=time", + Filename: "my_test/test.proto", +} + +var E_ReplyExtensions_Carrot = &proto.ExtensionDesc{ + ExtendedType: (*Reply)(nil), + ExtensionType: (*ReplyExtensions)(nil), + Field: 105, + Name: "my.test.ReplyExtensions.carrot", + Tag: "bytes,105,opt,name=carrot", + Filename: "my_test/test.proto", +} + +var E_ReplyExtensions_Donut = &proto.ExtensionDesc{ + ExtendedType: (*OtherBase)(nil), + ExtensionType: (*ReplyExtensions)(nil), + Field: 101, + Name: "my.test.ReplyExtensions.donut", + Tag: "bytes,101,opt,name=donut", + Filename: "my_test/test.proto", +} + +type OtherReplyExtensions struct { + Key *int32 `protobuf:"varint,1,opt,name=key" json:"key,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *OtherReplyExtensions) Reset() { *m = OtherReplyExtensions{} } +func (m *OtherReplyExtensions) String() string { return proto.CompactTextString(m) } +func (*OtherReplyExtensions) ProtoMessage() {} + +func (m *OtherReplyExtensions) GetKey() int32 { + if m != nil && m.Key != nil { + return *m.Key + } + return 0 +} + +type OldReply struct { + proto.XXX_InternalExtensions `json:"-"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *OldReply) Reset() { *m = OldReply{} } +func (m *OldReply) String() string { return proto.CompactTextString(m) } +func (*OldReply) ProtoMessage() {} + +func (m *OldReply) Marshal() ([]byte, error) { + return proto.MarshalMessageSet(&m.XXX_InternalExtensions) +} +func (m *OldReply) Unmarshal(buf []byte) error { + return proto.UnmarshalMessageSet(buf, &m.XXX_InternalExtensions) +} +func (m *OldReply) MarshalJSON() ([]byte, error) { + return proto.MarshalMessageSetJSON(&m.XXX_InternalExtensions) +} +func (m *OldReply) UnmarshalJSON(buf []byte) error { + return proto.UnmarshalMessageSetJSON(buf, &m.XXX_InternalExtensions) +} + +// ensure OldReply satisfies proto.Marshaler and proto.Unmarshaler +var _ proto.Marshaler = (*OldReply)(nil) +var _ proto.Unmarshaler = (*OldReply)(nil) + +var extRange_OldReply = []proto.ExtensionRange{ + {100, 2147483646}, +} + +func (*OldReply) ExtensionRangeArray() []proto.ExtensionRange { + return extRange_OldReply +} + +type Communique struct { + MakeMeCry *bool `protobuf:"varint,1,opt,name=make_me_cry,json=makeMeCry" json:"make_me_cry,omitempty"` + // This is a oneof, called "union". + // + // Types that are valid to be assigned to Union: + // *Communique_Number + // *Communique_Name + // *Communique_Data + // *Communique_TempC + // *Communique_Height + // *Communique_Today + // *Communique_Maybe + // *Communique_Delta_ + // *Communique_Msg + // *Communique_Somegroup + Union isCommunique_Union `protobuf_oneof:"union"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *Communique) Reset() { *m = Communique{} } +func (m *Communique) String() string { return proto.CompactTextString(m) } +func (*Communique) ProtoMessage() {} + +type isCommunique_Union interface { + isCommunique_Union() +} + +type Communique_Number struct { + Number int32 `protobuf:"varint,5,opt,name=number,oneof"` +} +type Communique_Name struct { + Name string `protobuf:"bytes,6,opt,name=name,oneof"` +} +type Communique_Data struct { + Data []byte `protobuf:"bytes,7,opt,name=data,oneof"` +} +type Communique_TempC struct { + TempC float64 `protobuf:"fixed64,8,opt,name=temp_c,json=tempC,oneof"` +} +type Communique_Height struct { + Height float32 `protobuf:"fixed32,9,opt,name=height,oneof"` +} +type Communique_Today struct { + Today Days `protobuf:"varint,10,opt,name=today,enum=my.test.Days,oneof"` +} +type Communique_Maybe struct { + Maybe bool `protobuf:"varint,11,opt,name=maybe,oneof"` +} +type Communique_Delta_ struct { + Delta int32 `protobuf:"zigzag32,12,opt,name=delta,oneof"` +} +type Communique_Msg struct { + Msg *Reply `protobuf:"bytes,13,opt,name=msg,oneof"` +} +type Communique_Somegroup struct { + Somegroup *Communique_SomeGroup `protobuf:"group,14,opt,name=SomeGroup,json=somegroup,oneof"` +} + +func (*Communique_Number) isCommunique_Union() {} +func (*Communique_Name) isCommunique_Union() {} +func (*Communique_Data) isCommunique_Union() {} +func (*Communique_TempC) isCommunique_Union() {} +func (*Communique_Height) isCommunique_Union() {} +func (*Communique_Today) isCommunique_Union() {} +func (*Communique_Maybe) isCommunique_Union() {} +func (*Communique_Delta_) isCommunique_Union() {} +func (*Communique_Msg) isCommunique_Union() {} +func (*Communique_Somegroup) isCommunique_Union() {} + +func (m *Communique) GetUnion() isCommunique_Union { + if m != nil { + return m.Union + } + return nil +} + +func (m *Communique) GetMakeMeCry() bool { + if m != nil && m.MakeMeCry != nil { + return *m.MakeMeCry + } + return false +} + +func (m *Communique) GetNumber() int32 { + if x, ok := m.GetUnion().(*Communique_Number); ok { + return x.Number + } + return 0 +} + +func (m *Communique) GetName() string { + if x, ok := m.GetUnion().(*Communique_Name); ok { + return x.Name + } + return "" +} + +func (m *Communique) GetData() []byte { + if x, ok := m.GetUnion().(*Communique_Data); ok { + return x.Data + } + return nil +} + +func (m *Communique) GetTempC() float64 { + if x, ok := m.GetUnion().(*Communique_TempC); ok { + return x.TempC + } + return 0 +} + +func (m *Communique) GetHeight() float32 { + if x, ok := m.GetUnion().(*Communique_Height); ok { + return x.Height + } + return 0 +} + +func (m *Communique) GetToday() Days { + if x, ok := m.GetUnion().(*Communique_Today); ok { + return x.Today + } + return Days_MONDAY +} + +func (m *Communique) GetMaybe() bool { + if x, ok := m.GetUnion().(*Communique_Maybe); ok { + return x.Maybe + } + return false +} + +func (m *Communique) GetDelta() int32 { + if x, ok := m.GetUnion().(*Communique_Delta_); ok { + return x.Delta + } + return 0 +} + +func (m *Communique) GetMsg() *Reply { + if x, ok := m.GetUnion().(*Communique_Msg); ok { + return x.Msg + } + return nil +} + +func (m *Communique) GetSomegroup() *Communique_SomeGroup { + if x, ok := m.GetUnion().(*Communique_Somegroup); ok { + return x.Somegroup + } + return nil +} + +// XXX_OneofFuncs is for the internal use of the proto package. +func (*Communique) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { + return _Communique_OneofMarshaler, _Communique_OneofUnmarshaler, _Communique_OneofSizer, []interface{}{ + (*Communique_Number)(nil), + (*Communique_Name)(nil), + (*Communique_Data)(nil), + (*Communique_TempC)(nil), + (*Communique_Height)(nil), + (*Communique_Today)(nil), + (*Communique_Maybe)(nil), + (*Communique_Delta_)(nil), + (*Communique_Msg)(nil), + (*Communique_Somegroup)(nil), + } +} + +func _Communique_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { + m := msg.(*Communique) + // union + switch x := m.Union.(type) { + case *Communique_Number: + b.EncodeVarint(5<<3 | proto.WireVarint) + b.EncodeVarint(uint64(x.Number)) + case *Communique_Name: + b.EncodeVarint(6<<3 | proto.WireBytes) + b.EncodeStringBytes(x.Name) + case *Communique_Data: + b.EncodeVarint(7<<3 | proto.WireBytes) + b.EncodeRawBytes(x.Data) + case *Communique_TempC: + b.EncodeVarint(8<<3 | proto.WireFixed64) + b.EncodeFixed64(math.Float64bits(x.TempC)) + case *Communique_Height: + b.EncodeVarint(9<<3 | proto.WireFixed32) + b.EncodeFixed32(uint64(math.Float32bits(x.Height))) + case *Communique_Today: + b.EncodeVarint(10<<3 | proto.WireVarint) + b.EncodeVarint(uint64(x.Today)) + case *Communique_Maybe: + t := uint64(0) + if x.Maybe { + t = 1 + } + b.EncodeVarint(11<<3 | proto.WireVarint) + b.EncodeVarint(t) + case *Communique_Delta_: + b.EncodeVarint(12<<3 | proto.WireVarint) + b.EncodeZigzag32(uint64(x.Delta)) + case *Communique_Msg: + b.EncodeVarint(13<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.Msg); err != nil { + return err + } + case *Communique_Somegroup: + b.EncodeVarint(14<<3 | proto.WireStartGroup) + if err := b.Marshal(x.Somegroup); err != nil { + return err + } + b.EncodeVarint(14<<3 | proto.WireEndGroup) + case nil: + default: + return fmt.Errorf("Communique.Union has unexpected type %T", x) + } + return nil +} + +func _Communique_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { + m := msg.(*Communique) + switch tag { + case 5: // union.number + if wire != proto.WireVarint { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeVarint() + m.Union = &Communique_Number{int32(x)} + return true, err + case 6: // union.name + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeStringBytes() + m.Union = &Communique_Name{x} + return true, err + case 7: // union.data + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeRawBytes(true) + m.Union = &Communique_Data{x} + return true, err + case 8: // union.temp_c + if wire != proto.WireFixed64 { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeFixed64() + m.Union = &Communique_TempC{math.Float64frombits(x)} + return true, err + case 9: // union.height + if wire != proto.WireFixed32 { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeFixed32() + m.Union = &Communique_Height{math.Float32frombits(uint32(x))} + return true, err + case 10: // union.today + if wire != proto.WireVarint { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeVarint() + m.Union = &Communique_Today{Days(x)} + return true, err + case 11: // union.maybe + if wire != proto.WireVarint { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeVarint() + m.Union = &Communique_Maybe{x != 0} + return true, err + case 12: // union.delta + if wire != proto.WireVarint { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeZigzag32() + m.Union = &Communique_Delta_{int32(x)} + return true, err + case 13: // union.msg + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(Reply) + err := b.DecodeMessage(msg) + m.Union = &Communique_Msg{msg} + return true, err + case 14: // union.somegroup + if wire != proto.WireStartGroup { + return true, proto.ErrInternalBadWireType + } + msg := new(Communique_SomeGroup) + err := b.DecodeGroup(msg) + m.Union = &Communique_Somegroup{msg} + return true, err + default: + return false, nil + } +} + +func _Communique_OneofSizer(msg proto.Message) (n int) { + m := msg.(*Communique) + // union + switch x := m.Union.(type) { + case *Communique_Number: + n += proto.SizeVarint(5<<3 | proto.WireVarint) + n += proto.SizeVarint(uint64(x.Number)) + case *Communique_Name: + n += proto.SizeVarint(6<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(len(x.Name))) + n += len(x.Name) + case *Communique_Data: + n += proto.SizeVarint(7<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(len(x.Data))) + n += len(x.Data) + case *Communique_TempC: + n += proto.SizeVarint(8<<3 | proto.WireFixed64) + n += 8 + case *Communique_Height: + n += proto.SizeVarint(9<<3 | proto.WireFixed32) + n += 4 + case *Communique_Today: + n += proto.SizeVarint(10<<3 | proto.WireVarint) + n += proto.SizeVarint(uint64(x.Today)) + case *Communique_Maybe: + n += proto.SizeVarint(11<<3 | proto.WireVarint) + n += 1 + case *Communique_Delta_: + n += proto.SizeVarint(12<<3 | proto.WireVarint) + n += proto.SizeVarint(uint64((uint32(x.Delta) << 1) ^ uint32((int32(x.Delta) >> 31)))) + case *Communique_Msg: + s := proto.Size(x.Msg) + n += proto.SizeVarint(13<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *Communique_Somegroup: + n += proto.SizeVarint(14<<3 | proto.WireStartGroup) + n += proto.Size(x.Somegroup) + n += proto.SizeVarint(14<<3 | proto.WireEndGroup) + case nil: + default: + panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) + } + return n +} + +type Communique_SomeGroup struct { + Member *string `protobuf:"bytes,15,opt,name=member" json:"member,omitempty"` + XXX_unrecognized []byte `json:"-"` +} + +func (m *Communique_SomeGroup) Reset() { *m = Communique_SomeGroup{} } +func (m *Communique_SomeGroup) String() string { return proto.CompactTextString(m) } +func (*Communique_SomeGroup) ProtoMessage() {} + +func (m *Communique_SomeGroup) GetMember() string { + if m != nil && m.Member != nil { + return *m.Member + } + return "" +} + +type Communique_Delta struct { + XXX_unrecognized []byte `json:"-"` +} + +func (m *Communique_Delta) Reset() { *m = Communique_Delta{} } +func (m *Communique_Delta) String() string { return proto.CompactTextString(m) } +func (*Communique_Delta) ProtoMessage() {} + +var E_Tag = &proto.ExtensionDesc{ + ExtendedType: (*Reply)(nil), + ExtensionType: (*string)(nil), + Field: 103, + Name: "my.test.tag", + Tag: "bytes,103,opt,name=tag", + Filename: "my_test/test.proto", +} + +var E_Donut = &proto.ExtensionDesc{ + ExtendedType: (*Reply)(nil), + ExtensionType: (*OtherReplyExtensions)(nil), + Field: 106, + Name: "my.test.donut", + Tag: "bytes,106,opt,name=donut", + Filename: "my_test/test.proto", +} + +func init() { + proto.RegisterType((*Request)(nil), "my.test.Request") + proto.RegisterType((*Request_SomeGroup)(nil), "my.test.Request.SomeGroup") + proto.RegisterType((*Reply)(nil), "my.test.Reply") + proto.RegisterType((*Reply_Entry)(nil), "my.test.Reply.Entry") + proto.RegisterType((*OtherBase)(nil), "my.test.OtherBase") + proto.RegisterType((*ReplyExtensions)(nil), "my.test.ReplyExtensions") + proto.RegisterType((*OtherReplyExtensions)(nil), "my.test.OtherReplyExtensions") + proto.RegisterType((*OldReply)(nil), "my.test.OldReply") + proto.RegisterType((*Communique)(nil), "my.test.Communique") + proto.RegisterType((*Communique_SomeGroup)(nil), "my.test.Communique.SomeGroup") + proto.RegisterType((*Communique_Delta)(nil), "my.test.Communique.Delta") + proto.RegisterEnum("my.test.HatType", HatType_name, HatType_value) + proto.RegisterEnum("my.test.Days", Days_name, Days_value) + proto.RegisterEnum("my.test.Request_Color", Request_Color_name, Request_Color_value) + proto.RegisterEnum("my.test.Reply_Entry_Game", Reply_Entry_Game_name, Reply_Entry_Game_value) + proto.RegisterExtension(E_ReplyExtensions_Time) + proto.RegisterExtension(E_ReplyExtensions_Carrot) + proto.RegisterExtension(E_ReplyExtensions_Donut) + proto.RegisterExtension(E_Tag) + proto.RegisterExtension(E_Donut) +} diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/my_test/test.proto b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/my_test/test.proto new file mode 100644 index 00000000..8e709463 --- /dev/null +++ b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/my_test/test.proto @@ -0,0 +1,156 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2010 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// 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 +// OWNER 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. + +syntax = "proto2"; + +// This package holds interesting messages. +package my.test; // dotted package name + +//import "imp.proto"; +import "multi/multi1.proto"; // unused import + +enum HatType { + // deliberately skipping 0 + FEDORA = 1; + FEZ = 2; +} + +// This enum represents days of the week. +enum Days { + option allow_alias = true; + + MONDAY = 1; + TUESDAY = 2; + LUNDI = 1; // same value as MONDAY +} + +// This is a message that might be sent somewhere. +message Request { + enum Color { + RED = 0; + GREEN = 1; + BLUE = 2; + } + repeated int64 key = 1; +// optional imp.ImportedMessage imported_message = 2; + optional Color hue = 3; // no default + optional HatType hat = 4 [default=FEDORA]; +// optional imp.ImportedMessage.Owner owner = 6; + optional float deadline = 7 [default=inf]; + optional group SomeGroup = 8 { + optional int32 group_field = 9; + } + + // These foreign types are in imp2.proto, + // which is publicly imported by imp.proto. +// optional imp.PubliclyImportedMessage pub = 10; +// optional imp.PubliclyImportedEnum pub_enum = 13 [default=HAIR]; + + + // This is a map field. It will generate map[int32]string. + map name_mapping = 14; + // This is a map field whose value type is a message. + map msg_mapping = 15; + + optional int32 reset = 12; + // This field should not conflict with any getters. + optional string get_key = 16; +} + +message Reply { + message Entry { + required int64 key_that_needs_1234camel_CasIng = 1; + optional int64 value = 2 [default=7]; + optional int64 _my_field_name_2 = 3; + enum Game { + FOOTBALL = 1; + TENNIS = 2; + } + } + repeated Entry found = 1; + repeated int32 compact_keys = 2 [packed=true]; + extensions 100 to max; +} + +message OtherBase { + optional string name = 1; + extensions 100 to max; +} + +message ReplyExtensions { + extend Reply { + optional double time = 101; + optional ReplyExtensions carrot = 105; + } + extend OtherBase { + optional ReplyExtensions donut = 101; + } +} + +message OtherReplyExtensions { + optional int32 key = 1; +} + +// top-level extension +extend Reply { + optional string tag = 103; + optional OtherReplyExtensions donut = 106; +// optional imp.ImportedMessage elephant = 107; // extend with message from another file. +} + +message OldReply { + // Extensions will be encoded in MessageSet wire format. + option message_set_wire_format = true; + extensions 100 to max; +} + +message Communique { + optional bool make_me_cry = 1; + + // This is a oneof, called "union". + oneof union { + int32 number = 5; + string name = 6; + bytes data = 7; + double temp_c = 8; + float height = 9; + Days today = 10; + bool maybe = 11; + sint32 delta = 12; // name will conflict with Delta below + Reply msg = 13; + group SomeGroup = 14 { + optional string member = 15; + } + } + + message Delta {} +} + diff --git a/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/proto3.proto b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/proto3.proto new file mode 100644 index 00000000..869b9af5 --- /dev/null +++ b/vendor/github.com/golang/protobuf/protoc-gen-go/testdata/proto3.proto @@ -0,0 +1,53 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2014 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// 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 +// OWNER 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. + +syntax = "proto3"; + +package proto3; + +message Request { + enum Flavour { + SWEET = 0; + SOUR = 1; + UMAMI = 2; + GOPHERLICIOUS = 3; + } + string name = 1; + repeated int64 key = 2; + Flavour taste = 3; + Book book = 4; + repeated int64 unpacked = 5 [packed=false]; +} + +message Book { + string title = 1; + bytes raw_data = 2; +} diff --git a/vendor/github.com/golang/protobuf/ptypes/any.go b/vendor/github.com/golang/protobuf/ptypes/any.go new file mode 100644 index 00000000..b2af97f4 --- /dev/null +++ b/vendor/github.com/golang/protobuf/ptypes/any.go @@ -0,0 +1,139 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2016 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// 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 +// OWNER 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. + +package ptypes + +// This file implements functions to marshal proto.Message to/from +// google.protobuf.Any message. + +import ( + "fmt" + "reflect" + "strings" + + "github.com/golang/protobuf/proto" + "github.com/golang/protobuf/ptypes/any" +) + +const googleApis = "type.googleapis.com/" + +// AnyMessageName returns the name of the message contained in a google.protobuf.Any message. +// +// Note that regular type assertions should be done using the Is +// function. AnyMessageName is provided for less common use cases like filtering a +// sequence of Any messages based on a set of allowed message type names. +func AnyMessageName(any *any.Any) (string, error) { + if any == nil { + return "", fmt.Errorf("message is nil") + } + slash := strings.LastIndex(any.TypeUrl, "/") + if slash < 0 { + return "", fmt.Errorf("message type url %q is invalid", any.TypeUrl) + } + return any.TypeUrl[slash+1:], nil +} + +// MarshalAny takes the protocol buffer and encodes it into google.protobuf.Any. +func MarshalAny(pb proto.Message) (*any.Any, error) { + value, err := proto.Marshal(pb) + if err != nil { + return nil, err + } + return &any.Any{TypeUrl: googleApis + proto.MessageName(pb), Value: value}, nil +} + +// DynamicAny is a value that can be passed to UnmarshalAny to automatically +// allocate a proto.Message for the type specified in a google.protobuf.Any +// message. The allocated message is stored in the embedded proto.Message. +// +// Example: +// +// var x ptypes.DynamicAny +// if err := ptypes.UnmarshalAny(a, &x); err != nil { ... } +// fmt.Printf("unmarshaled message: %v", x.Message) +type DynamicAny struct { + proto.Message +} + +// Empty returns a new proto.Message of the type specified in a +// google.protobuf.Any message. It returns an error if corresponding message +// type isn't linked in. +func Empty(any *any.Any) (proto.Message, error) { + aname, err := AnyMessageName(any) + if err != nil { + return nil, err + } + + t := proto.MessageType(aname) + if t == nil { + return nil, fmt.Errorf("any: message type %q isn't linked in", aname) + } + return reflect.New(t.Elem()).Interface().(proto.Message), nil +} + +// UnmarshalAny parses the protocol buffer representation in a google.protobuf.Any +// message and places the decoded result in pb. It returns an error if type of +// contents of Any message does not match type of pb message. +// +// pb can be a proto.Message, or a *DynamicAny. +func UnmarshalAny(any *any.Any, pb proto.Message) error { + if d, ok := pb.(*DynamicAny); ok { + if d.Message == nil { + var err error + d.Message, err = Empty(any) + if err != nil { + return err + } + } + return UnmarshalAny(any, d.Message) + } + + aname, err := AnyMessageName(any) + if err != nil { + return err + } + + mname := proto.MessageName(pb) + if aname != mname { + return fmt.Errorf("mismatched message type: got %q want %q", aname, mname) + } + return proto.Unmarshal(any.Value, pb) +} + +// Is returns true if any value contains a given message type. +func Is(any *any.Any, pb proto.Message) bool { + aname, err := AnyMessageName(any) + if err != nil { + return false + } + + return aname == proto.MessageName(pb) +} diff --git a/vendor/github.com/golang/protobuf/ptypes/any/any.pb.go b/vendor/github.com/golang/protobuf/ptypes/any/any.pb.go new file mode 100644 index 00000000..f3460172 --- /dev/null +++ b/vendor/github.com/golang/protobuf/ptypes/any/any.pb.go @@ -0,0 +1,178 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: google/protobuf/any.proto + +/* +Package any is a generated protocol buffer package. + +It is generated from these files: + google/protobuf/any.proto + +It has these top-level messages: + Any +*/ +package any + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package + +// `Any` contains an arbitrary serialized protocol buffer message along with a +// URL that describes the type of the serialized message. +// +// Protobuf library provides support to pack/unpack Any values in the form +// of utility functions or additional generated methods of the Any type. +// +// Example 1: Pack and unpack a message in C++. +// +// Foo foo = ...; +// Any any; +// any.PackFrom(foo); +// ... +// if (any.UnpackTo(&foo)) { +// ... +// } +// +// Example 2: Pack and unpack a message in Java. +// +// Foo foo = ...; +// Any any = Any.pack(foo); +// ... +// if (any.is(Foo.class)) { +// foo = any.unpack(Foo.class); +// } +// +// Example 3: Pack and unpack a message in Python. +// +// foo = Foo(...) +// any = Any() +// any.Pack(foo) +// ... +// if any.Is(Foo.DESCRIPTOR): +// any.Unpack(foo) +// ... +// +// Example 4: Pack and unpack a message in Go +// +// foo := &pb.Foo{...} +// any, err := ptypes.MarshalAny(foo) +// ... +// foo := &pb.Foo{} +// if err := ptypes.UnmarshalAny(any, foo); err != nil { +// ... +// } +// +// The pack methods provided by protobuf library will by default use +// 'type.googleapis.com/full.type.name' as the type URL and the unpack +// methods only use the fully qualified type name after the last '/' +// in the type URL, for example "foo.bar.com/x/y.z" will yield type +// name "y.z". +// +// +// JSON +// ==== +// The JSON representation of an `Any` value uses the regular +// representation of the deserialized, embedded message, with an +// additional field `@type` which contains the type URL. Example: +// +// package google.profile; +// message Person { +// string first_name = 1; +// string last_name = 2; +// } +// +// { +// "@type": "type.googleapis.com/google.profile.Person", +// "firstName": , +// "lastName": +// } +// +// If the embedded message type is well-known and has a custom JSON +// representation, that representation will be embedded adding a field +// `value` which holds the custom JSON in addition to the `@type` +// field. Example (for message [google.protobuf.Duration][]): +// +// { +// "@type": "type.googleapis.com/google.protobuf.Duration", +// "value": "1.212s" +// } +// +type Any struct { + // A URL/resource name whose content describes the type of the + // serialized protocol buffer message. + // + // For URLs which use the scheme `http`, `https`, or no scheme, the + // following restrictions and interpretations apply: + // + // * If no scheme is provided, `https` is assumed. + // * The last segment of the URL's path must represent the fully + // qualified name of the type (as in `path/google.protobuf.Duration`). + // The name should be in a canonical form (e.g., leading "." is + // not accepted). + // * An HTTP GET on the URL must yield a [google.protobuf.Type][] + // value in binary format, or produce an error. + // * Applications are allowed to cache lookup results based on the + // URL, or have them precompiled into a binary to avoid any + // lookup. Therefore, binary compatibility needs to be preserved + // on changes to types. (Use versioned type names to manage + // breaking changes.) + // + // Schemes other than `http`, `https` (or the empty scheme) might be + // used with implementation specific semantics. + // + TypeUrl string `protobuf:"bytes,1,opt,name=type_url,json=typeUrl" json:"type_url,omitempty"` + // Must be a valid serialized protocol buffer of the above specified type. + Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` +} + +func (m *Any) Reset() { *m = Any{} } +func (m *Any) String() string { return proto.CompactTextString(m) } +func (*Any) ProtoMessage() {} +func (*Any) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } +func (*Any) XXX_WellKnownType() string { return "Any" } + +func (m *Any) GetTypeUrl() string { + if m != nil { + return m.TypeUrl + } + return "" +} + +func (m *Any) GetValue() []byte { + if m != nil { + return m.Value + } + return nil +} + +func init() { + proto.RegisterType((*Any)(nil), "google.protobuf.Any") +} + +func init() { proto.RegisterFile("google/protobuf/any.proto", fileDescriptor0) } + +var fileDescriptor0 = []byte{ + // 185 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4c, 0xcf, 0xcf, 0x4f, + 0xcf, 0x49, 0xd5, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x4f, 0xcc, 0xab, 0xd4, + 0x03, 0x73, 0x84, 0xf8, 0x21, 0x52, 0x7a, 0x30, 0x29, 0x25, 0x33, 0x2e, 0x66, 0xc7, 0xbc, 0x4a, + 0x21, 0x49, 0x2e, 0x8e, 0x92, 0xca, 0x82, 0xd4, 0xf8, 0xd2, 0xa2, 0x1c, 0x09, 0x46, 0x05, 0x46, + 0x0d, 0xce, 0x20, 0x76, 0x10, 0x3f, 0xb4, 0x28, 0x47, 0x48, 0x84, 0x8b, 0xb5, 0x2c, 0x31, 0xa7, + 0x34, 0x55, 0x82, 0x49, 0x81, 0x51, 0x83, 0x27, 0x08, 0xc2, 0x71, 0xca, 0xe7, 0x12, 0x4e, 0xce, + 0xcf, 0xd5, 0x43, 0x33, 0xce, 0x89, 0xc3, 0x31, 0xaf, 0x32, 0x00, 0xc4, 0x09, 0x60, 0x8c, 0x52, + 0x4d, 0xcf, 0x2c, 0xc9, 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xcf, 0xcf, 0x49, 0xcc, + 0x4b, 0x47, 0xb8, 0xa8, 0x00, 0x64, 0x7a, 0x31, 0xc8, 0x61, 0x8b, 0x98, 0x98, 0xdd, 0x03, 0x9c, + 0x56, 0x31, 0xc9, 0xb9, 0x43, 0x8c, 0x0a, 0x80, 0x2a, 0xd1, 0x0b, 0x4f, 0xcd, 0xc9, 0xf1, 0xce, + 0xcb, 0x2f, 0xcf, 0x0b, 0x01, 0x29, 0x4d, 0x62, 0x03, 0xeb, 0x35, 0x06, 0x04, 0x00, 0x00, 0xff, + 0xff, 0x13, 0xf8, 0xe8, 0x42, 0xdd, 0x00, 0x00, 0x00, +} diff --git a/vendor/github.com/golang/protobuf/ptypes/any/any.proto b/vendor/github.com/golang/protobuf/ptypes/any/any.proto new file mode 100644 index 00000000..c7486676 --- /dev/null +++ b/vendor/github.com/golang/protobuf/ptypes/any/any.proto @@ -0,0 +1,149 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// 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 +// OWNER 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. + +syntax = "proto3"; + +package google.protobuf; + +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; +option go_package = "github.com/golang/protobuf/ptypes/any"; +option java_package = "com.google.protobuf"; +option java_outer_classname = "AnyProto"; +option java_multiple_files = true; +option objc_class_prefix = "GPB"; + +// `Any` contains an arbitrary serialized protocol buffer message along with a +// URL that describes the type of the serialized message. +// +// Protobuf library provides support to pack/unpack Any values in the form +// of utility functions or additional generated methods of the Any type. +// +// Example 1: Pack and unpack a message in C++. +// +// Foo foo = ...; +// Any any; +// any.PackFrom(foo); +// ... +// if (any.UnpackTo(&foo)) { +// ... +// } +// +// Example 2: Pack and unpack a message in Java. +// +// Foo foo = ...; +// Any any = Any.pack(foo); +// ... +// if (any.is(Foo.class)) { +// foo = any.unpack(Foo.class); +// } +// +// Example 3: Pack and unpack a message in Python. +// +// foo = Foo(...) +// any = Any() +// any.Pack(foo) +// ... +// if any.Is(Foo.DESCRIPTOR): +// any.Unpack(foo) +// ... +// +// Example 4: Pack and unpack a message in Go +// +// foo := &pb.Foo{...} +// any, err := ptypes.MarshalAny(foo) +// ... +// foo := &pb.Foo{} +// if err := ptypes.UnmarshalAny(any, foo); err != nil { +// ... +// } +// +// The pack methods provided by protobuf library will by default use +// 'type.googleapis.com/full.type.name' as the type URL and the unpack +// methods only use the fully qualified type name after the last '/' +// in the type URL, for example "foo.bar.com/x/y.z" will yield type +// name "y.z". +// +// +// JSON +// ==== +// The JSON representation of an `Any` value uses the regular +// representation of the deserialized, embedded message, with an +// additional field `@type` which contains the type URL. Example: +// +// package google.profile; +// message Person { +// string first_name = 1; +// string last_name = 2; +// } +// +// { +// "@type": "type.googleapis.com/google.profile.Person", +// "firstName": , +// "lastName": +// } +// +// If the embedded message type is well-known and has a custom JSON +// representation, that representation will be embedded adding a field +// `value` which holds the custom JSON in addition to the `@type` +// field. Example (for message [google.protobuf.Duration][]): +// +// { +// "@type": "type.googleapis.com/google.protobuf.Duration", +// "value": "1.212s" +// } +// +message Any { + // A URL/resource name whose content describes the type of the + // serialized protocol buffer message. + // + // For URLs which use the scheme `http`, `https`, or no scheme, the + // following restrictions and interpretations apply: + // + // * If no scheme is provided, `https` is assumed. + // * The last segment of the URL's path must represent the fully + // qualified name of the type (as in `path/google.protobuf.Duration`). + // The name should be in a canonical form (e.g., leading "." is + // not accepted). + // * An HTTP GET on the URL must yield a [google.protobuf.Type][] + // value in binary format, or produce an error. + // * Applications are allowed to cache lookup results based on the + // URL, or have them precompiled into a binary to avoid any + // lookup. Therefore, binary compatibility needs to be preserved + // on changes to types. (Use versioned type names to manage + // breaking changes.) + // + // Schemes other than `http`, `https` (or the empty scheme) might be + // used with implementation specific semantics. + // + string type_url = 1; + + // Must be a valid serialized protocol buffer of the above specified type. + bytes value = 2; +} diff --git a/vendor/github.com/golang/protobuf/ptypes/any_test.go b/vendor/github.com/golang/protobuf/ptypes/any_test.go new file mode 100644 index 00000000..ed675b48 --- /dev/null +++ b/vendor/github.com/golang/protobuf/ptypes/any_test.go @@ -0,0 +1,113 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2016 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// 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 +// OWNER 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. + +package ptypes + +import ( + "testing" + + "github.com/golang/protobuf/proto" + pb "github.com/golang/protobuf/protoc-gen-go/descriptor" + "github.com/golang/protobuf/ptypes/any" +) + +func TestMarshalUnmarshal(t *testing.T) { + orig := &any.Any{Value: []byte("test")} + + packed, err := MarshalAny(orig) + if err != nil { + t.Errorf("MarshalAny(%+v): got: _, %v exp: _, nil", orig, err) + } + + unpacked := &any.Any{} + err = UnmarshalAny(packed, unpacked) + if err != nil || !proto.Equal(unpacked, orig) { + t.Errorf("got: %v, %+v; want nil, %+v", err, unpacked, orig) + } +} + +func TestIs(t *testing.T) { + a, err := MarshalAny(&pb.FileDescriptorProto{}) + if err != nil { + t.Fatal(err) + } + if Is(a, &pb.DescriptorProto{}) { + t.Error("FileDescriptorProto is not a DescriptorProto, but Is says it is") + } + if !Is(a, &pb.FileDescriptorProto{}) { + t.Error("FileDescriptorProto is indeed a FileDescriptorProto, but Is says it is not") + } +} + +func TestIsDifferentUrlPrefixes(t *testing.T) { + m := &pb.FileDescriptorProto{} + a := &any.Any{TypeUrl: "foo/bar/" + proto.MessageName(m)} + if !Is(a, m) { + t.Errorf("message with type url %q didn't satisfy Is for type %q", a.TypeUrl, proto.MessageName(m)) + } +} + +func TestUnmarshalDynamic(t *testing.T) { + want := &pb.FileDescriptorProto{Name: proto.String("foo")} + a, err := MarshalAny(want) + if err != nil { + t.Fatal(err) + } + var got DynamicAny + if err := UnmarshalAny(a, &got); err != nil { + t.Fatal(err) + } + if !proto.Equal(got.Message, want) { + t.Errorf("invalid result from UnmarshalAny, got %q want %q", got.Message, want) + } +} + +func TestEmpty(t *testing.T) { + want := &pb.FileDescriptorProto{} + a, err := MarshalAny(want) + if err != nil { + t.Fatal(err) + } + got, err := Empty(a) + if err != nil { + t.Fatal(err) + } + if !proto.Equal(got, want) { + t.Errorf("unequal empty message, got %q, want %q", got, want) + } + + // that's a valid type_url for a message which shouldn't be linked into this + // test binary. We want an error. + a.TypeUrl = "type.googleapis.com/google.protobuf.FieldMask" + if _, err := Empty(a); err == nil { + t.Errorf("got no error for an attempt to create a message of type %q, which shouldn't be linked in", a.TypeUrl) + } +} diff --git a/vendor/github.com/golang/protobuf/ptypes/doc.go b/vendor/github.com/golang/protobuf/ptypes/doc.go new file mode 100644 index 00000000..c0d595da --- /dev/null +++ b/vendor/github.com/golang/protobuf/ptypes/doc.go @@ -0,0 +1,35 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2016 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// 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 +// OWNER 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. + +/* +Package ptypes contains code for interacting with well-known types. +*/ +package ptypes diff --git a/vendor/github.com/golang/protobuf/ptypes/duration.go b/vendor/github.com/golang/protobuf/ptypes/duration.go new file mode 100644 index 00000000..65cb0f8e --- /dev/null +++ b/vendor/github.com/golang/protobuf/ptypes/duration.go @@ -0,0 +1,102 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2016 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// 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 +// OWNER 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. + +package ptypes + +// This file implements conversions between google.protobuf.Duration +// and time.Duration. + +import ( + "errors" + "fmt" + "time" + + durpb "github.com/golang/protobuf/ptypes/duration" +) + +const ( + // Range of a durpb.Duration in seconds, as specified in + // google/protobuf/duration.proto. This is about 10,000 years in seconds. + maxSeconds = int64(10000 * 365.25 * 24 * 60 * 60) + minSeconds = -maxSeconds +) + +// validateDuration determines whether the durpb.Duration is valid according to the +// definition in google/protobuf/duration.proto. A valid durpb.Duration +// may still be too large to fit into a time.Duration (the range of durpb.Duration +// is about 10,000 years, and the range of time.Duration is about 290). +func validateDuration(d *durpb.Duration) error { + if d == nil { + return errors.New("duration: nil Duration") + } + if d.Seconds < minSeconds || d.Seconds > maxSeconds { + return fmt.Errorf("duration: %v: seconds out of range", d) + } + if d.Nanos <= -1e9 || d.Nanos >= 1e9 { + return fmt.Errorf("duration: %v: nanos out of range", d) + } + // Seconds and Nanos must have the same sign, unless d.Nanos is zero. + if (d.Seconds < 0 && d.Nanos > 0) || (d.Seconds > 0 && d.Nanos < 0) { + return fmt.Errorf("duration: %v: seconds and nanos have different signs", d) + } + return nil +} + +// Duration converts a durpb.Duration to a time.Duration. Duration +// returns an error if the durpb.Duration is invalid or is too large to be +// represented in a time.Duration. +func Duration(p *durpb.Duration) (time.Duration, error) { + if err := validateDuration(p); err != nil { + return 0, err + } + d := time.Duration(p.Seconds) * time.Second + if int64(d/time.Second) != p.Seconds { + return 0, fmt.Errorf("duration: %v is out of range for time.Duration", p) + } + if p.Nanos != 0 { + d += time.Duration(p.Nanos) + if (d < 0) != (p.Nanos < 0) { + return 0, fmt.Errorf("duration: %v is out of range for time.Duration", p) + } + } + return d, nil +} + +// DurationProto converts a time.Duration to a durpb.Duration. +func DurationProto(d time.Duration) *durpb.Duration { + nanos := d.Nanoseconds() + secs := nanos / 1e9 + nanos -= secs * 1e9 + return &durpb.Duration{ + Seconds: secs, + Nanos: int32(nanos), + } +} diff --git a/vendor/github.com/golang/protobuf/ptypes/duration/duration.pb.go b/vendor/github.com/golang/protobuf/ptypes/duration/duration.pb.go new file mode 100644 index 00000000..b2410a09 --- /dev/null +++ b/vendor/github.com/golang/protobuf/ptypes/duration/duration.pb.go @@ -0,0 +1,144 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: google/protobuf/duration.proto + +/* +Package duration is a generated protocol buffer package. + +It is generated from these files: + google/protobuf/duration.proto + +It has these top-level messages: + Duration +*/ +package duration + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package + +// A Duration represents a signed, fixed-length span of time represented +// as a count of seconds and fractions of seconds at nanosecond +// resolution. It is independent of any calendar and concepts like "day" +// or "month". It is related to Timestamp in that the difference between +// two Timestamp values is a Duration and it can be added or subtracted +// from a Timestamp. Range is approximately +-10,000 years. +// +// # Examples +// +// Example 1: Compute Duration from two Timestamps in pseudo code. +// +// Timestamp start = ...; +// Timestamp end = ...; +// Duration duration = ...; +// +// duration.seconds = end.seconds - start.seconds; +// duration.nanos = end.nanos - start.nanos; +// +// if (duration.seconds < 0 && duration.nanos > 0) { +// duration.seconds += 1; +// duration.nanos -= 1000000000; +// } else if (durations.seconds > 0 && duration.nanos < 0) { +// duration.seconds -= 1; +// duration.nanos += 1000000000; +// } +// +// Example 2: Compute Timestamp from Timestamp + Duration in pseudo code. +// +// Timestamp start = ...; +// Duration duration = ...; +// Timestamp end = ...; +// +// end.seconds = start.seconds + duration.seconds; +// end.nanos = start.nanos + duration.nanos; +// +// if (end.nanos < 0) { +// end.seconds -= 1; +// end.nanos += 1000000000; +// } else if (end.nanos >= 1000000000) { +// end.seconds += 1; +// end.nanos -= 1000000000; +// } +// +// Example 3: Compute Duration from datetime.timedelta in Python. +// +// td = datetime.timedelta(days=3, minutes=10) +// duration = Duration() +// duration.FromTimedelta(td) +// +// # JSON Mapping +// +// In JSON format, the Duration type is encoded as a string rather than an +// object, where the string ends in the suffix "s" (indicating seconds) and +// is preceded by the number of seconds, with nanoseconds expressed as +// fractional seconds. For example, 3 seconds with 0 nanoseconds should be +// encoded in JSON format as "3s", while 3 seconds and 1 nanosecond should +// be expressed in JSON format as "3.000000001s", and 3 seconds and 1 +// microsecond should be expressed in JSON format as "3.000001s". +// +// +type Duration struct { + // Signed seconds of the span of time. Must be from -315,576,000,000 + // to +315,576,000,000 inclusive. Note: these bounds are computed from: + // 60 sec/min * 60 min/hr * 24 hr/day * 365.25 days/year * 10000 years + Seconds int64 `protobuf:"varint,1,opt,name=seconds" json:"seconds,omitempty"` + // Signed fractions of a second at nanosecond resolution of the span + // of time. Durations less than one second are represented with a 0 + // `seconds` field and a positive or negative `nanos` field. For durations + // of one second or more, a non-zero value for the `nanos` field must be + // of the same sign as the `seconds` field. Must be from -999,999,999 + // to +999,999,999 inclusive. + Nanos int32 `protobuf:"varint,2,opt,name=nanos" json:"nanos,omitempty"` +} + +func (m *Duration) Reset() { *m = Duration{} } +func (m *Duration) String() string { return proto.CompactTextString(m) } +func (*Duration) ProtoMessage() {} +func (*Duration) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } +func (*Duration) XXX_WellKnownType() string { return "Duration" } + +func (m *Duration) GetSeconds() int64 { + if m != nil { + return m.Seconds + } + return 0 +} + +func (m *Duration) GetNanos() int32 { + if m != nil { + return m.Nanos + } + return 0 +} + +func init() { + proto.RegisterType((*Duration)(nil), "google.protobuf.Duration") +} + +func init() { proto.RegisterFile("google/protobuf/duration.proto", fileDescriptor0) } + +var fileDescriptor0 = []byte{ + // 190 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4b, 0xcf, 0xcf, 0x4f, + 0xcf, 0x49, 0xd5, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x4f, 0x29, 0x2d, 0x4a, + 0x2c, 0xc9, 0xcc, 0xcf, 0xd3, 0x03, 0x8b, 0x08, 0xf1, 0x43, 0xe4, 0xf5, 0x60, 0xf2, 0x4a, 0x56, + 0x5c, 0x1c, 0x2e, 0x50, 0x25, 0x42, 0x12, 0x5c, 0xec, 0xc5, 0xa9, 0xc9, 0xf9, 0x79, 0x29, 0xc5, + 0x12, 0x8c, 0x0a, 0x8c, 0x1a, 0xcc, 0x41, 0x30, 0xae, 0x90, 0x08, 0x17, 0x6b, 0x5e, 0x62, 0x5e, + 0x7e, 0xb1, 0x04, 0x93, 0x02, 0xa3, 0x06, 0x6b, 0x10, 0x84, 0xe3, 0x54, 0xc3, 0x25, 0x9c, 0x9c, + 0x9f, 0xab, 0x87, 0x66, 0xa4, 0x13, 0x2f, 0xcc, 0xc0, 0x00, 0x90, 0x48, 0x00, 0x63, 0x94, 0x56, + 0x7a, 0x66, 0x49, 0x46, 0x69, 0x92, 0x5e, 0x72, 0x7e, 0xae, 0x7e, 0x7a, 0x7e, 0x4e, 0x62, 0x5e, + 0x3a, 0xc2, 0x7d, 0x05, 0x25, 0x95, 0x05, 0xa9, 0xc5, 0x70, 0x67, 0xfe, 0x60, 0x64, 0x5c, 0xc4, + 0xc4, 0xec, 0x1e, 0xe0, 0xb4, 0x8a, 0x49, 0xce, 0x1d, 0x62, 0x6e, 0x00, 0x54, 0xa9, 0x5e, 0x78, + 0x6a, 0x4e, 0x8e, 0x77, 0x5e, 0x7e, 0x79, 0x5e, 0x08, 0x48, 0x4b, 0x12, 0x1b, 0xd8, 0x0c, 0x63, + 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0xdc, 0x84, 0x30, 0xff, 0xf3, 0x00, 0x00, 0x00, +} diff --git a/vendor/github.com/golang/protobuf/ptypes/duration/duration.proto b/vendor/github.com/golang/protobuf/ptypes/duration/duration.proto new file mode 100644 index 00000000..975fce41 --- /dev/null +++ b/vendor/github.com/golang/protobuf/ptypes/duration/duration.proto @@ -0,0 +1,117 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// 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 +// OWNER 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. + +syntax = "proto3"; + +package google.protobuf; + +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; +option cc_enable_arenas = true; +option go_package = "github.com/golang/protobuf/ptypes/duration"; +option java_package = "com.google.protobuf"; +option java_outer_classname = "DurationProto"; +option java_multiple_files = true; +option objc_class_prefix = "GPB"; + +// A Duration represents a signed, fixed-length span of time represented +// as a count of seconds and fractions of seconds at nanosecond +// resolution. It is independent of any calendar and concepts like "day" +// or "month". It is related to Timestamp in that the difference between +// two Timestamp values is a Duration and it can be added or subtracted +// from a Timestamp. Range is approximately +-10,000 years. +// +// # Examples +// +// Example 1: Compute Duration from two Timestamps in pseudo code. +// +// Timestamp start = ...; +// Timestamp end = ...; +// Duration duration = ...; +// +// duration.seconds = end.seconds - start.seconds; +// duration.nanos = end.nanos - start.nanos; +// +// if (duration.seconds < 0 && duration.nanos > 0) { +// duration.seconds += 1; +// duration.nanos -= 1000000000; +// } else if (durations.seconds > 0 && duration.nanos < 0) { +// duration.seconds -= 1; +// duration.nanos += 1000000000; +// } +// +// Example 2: Compute Timestamp from Timestamp + Duration in pseudo code. +// +// Timestamp start = ...; +// Duration duration = ...; +// Timestamp end = ...; +// +// end.seconds = start.seconds + duration.seconds; +// end.nanos = start.nanos + duration.nanos; +// +// if (end.nanos < 0) { +// end.seconds -= 1; +// end.nanos += 1000000000; +// } else if (end.nanos >= 1000000000) { +// end.seconds += 1; +// end.nanos -= 1000000000; +// } +// +// Example 3: Compute Duration from datetime.timedelta in Python. +// +// td = datetime.timedelta(days=3, minutes=10) +// duration = Duration() +// duration.FromTimedelta(td) +// +// # JSON Mapping +// +// In JSON format, the Duration type is encoded as a string rather than an +// object, where the string ends in the suffix "s" (indicating seconds) and +// is preceded by the number of seconds, with nanoseconds expressed as +// fractional seconds. For example, 3 seconds with 0 nanoseconds should be +// encoded in JSON format as "3s", while 3 seconds and 1 nanosecond should +// be expressed in JSON format as "3.000000001s", and 3 seconds and 1 +// microsecond should be expressed in JSON format as "3.000001s". +// +// +message Duration { + + // Signed seconds of the span of time. Must be from -315,576,000,000 + // to +315,576,000,000 inclusive. Note: these bounds are computed from: + // 60 sec/min * 60 min/hr * 24 hr/day * 365.25 days/year * 10000 years + int64 seconds = 1; + + // Signed fractions of a second at nanosecond resolution of the span + // of time. Durations less than one second are represented with a 0 + // `seconds` field and a positive or negative `nanos` field. For durations + // of one second or more, a non-zero value for the `nanos` field must be + // of the same sign as the `seconds` field. Must be from -999,999,999 + // to +999,999,999 inclusive. + int32 nanos = 2; +} diff --git a/vendor/github.com/golang/protobuf/ptypes/duration_test.go b/vendor/github.com/golang/protobuf/ptypes/duration_test.go new file mode 100644 index 00000000..e00491a3 --- /dev/null +++ b/vendor/github.com/golang/protobuf/ptypes/duration_test.go @@ -0,0 +1,121 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2016 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// 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 +// OWNER 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. + +package ptypes + +import ( + "math" + "testing" + "time" + + "github.com/golang/protobuf/proto" + durpb "github.com/golang/protobuf/ptypes/duration" +) + +const ( + minGoSeconds = math.MinInt64 / int64(1e9) + maxGoSeconds = math.MaxInt64 / int64(1e9) +) + +var durationTests = []struct { + proto *durpb.Duration + isValid bool + inRange bool + dur time.Duration +}{ + // The zero duration. + {&durpb.Duration{Seconds: 0, Nanos: 0}, true, true, 0}, + // Some ordinary non-zero durations. + {&durpb.Duration{Seconds: 100, Nanos: 0}, true, true, 100 * time.Second}, + {&durpb.Duration{Seconds: -100, Nanos: 0}, true, true, -100 * time.Second}, + {&durpb.Duration{Seconds: 100, Nanos: 987}, true, true, 100*time.Second + 987}, + {&durpb.Duration{Seconds: -100, Nanos: -987}, true, true, -(100*time.Second + 987)}, + // The largest duration representable in Go. + {&durpb.Duration{Seconds: maxGoSeconds, Nanos: int32(math.MaxInt64 - 1e9*maxGoSeconds)}, true, true, math.MaxInt64}, + // The smallest duration representable in Go. + {&durpb.Duration{Seconds: minGoSeconds, Nanos: int32(math.MinInt64 - 1e9*minGoSeconds)}, true, true, math.MinInt64}, + {nil, false, false, 0}, + {&durpb.Duration{Seconds: -100, Nanos: 987}, false, false, 0}, + {&durpb.Duration{Seconds: 100, Nanos: -987}, false, false, 0}, + {&durpb.Duration{Seconds: math.MinInt64, Nanos: 0}, false, false, 0}, + {&durpb.Duration{Seconds: math.MaxInt64, Nanos: 0}, false, false, 0}, + // The largest valid duration. + {&durpb.Duration{Seconds: maxSeconds, Nanos: 1e9 - 1}, true, false, 0}, + // The smallest valid duration. + {&durpb.Duration{Seconds: minSeconds, Nanos: -(1e9 - 1)}, true, false, 0}, + // The smallest invalid duration above the valid range. + {&durpb.Duration{Seconds: maxSeconds + 1, Nanos: 0}, false, false, 0}, + // The largest invalid duration below the valid range. + {&durpb.Duration{Seconds: minSeconds - 1, Nanos: -(1e9 - 1)}, false, false, 0}, + // One nanosecond past the largest duration representable in Go. + {&durpb.Duration{Seconds: maxGoSeconds, Nanos: int32(math.MaxInt64-1e9*maxGoSeconds) + 1}, true, false, 0}, + // One nanosecond past the smallest duration representable in Go. + {&durpb.Duration{Seconds: minGoSeconds, Nanos: int32(math.MinInt64-1e9*minGoSeconds) - 1}, true, false, 0}, + // One second past the largest duration representable in Go. + {&durpb.Duration{Seconds: maxGoSeconds + 1, Nanos: int32(math.MaxInt64 - 1e9*maxGoSeconds)}, true, false, 0}, + // One second past the smallest duration representable in Go. + {&durpb.Duration{Seconds: minGoSeconds - 1, Nanos: int32(math.MinInt64 - 1e9*minGoSeconds)}, true, false, 0}, +} + +func TestValidateDuration(t *testing.T) { + for _, test := range durationTests { + err := validateDuration(test.proto) + gotValid := (err == nil) + if gotValid != test.isValid { + t.Errorf("validateDuration(%v) = %t, want %t", test.proto, gotValid, test.isValid) + } + } +} + +func TestDuration(t *testing.T) { + for _, test := range durationTests { + got, err := Duration(test.proto) + gotOK := (err == nil) + wantOK := test.isValid && test.inRange + if gotOK != wantOK { + t.Errorf("Duration(%v) ok = %t, want %t", test.proto, gotOK, wantOK) + } + if err == nil && got != test.dur { + t.Errorf("Duration(%v) = %v, want %v", test.proto, got, test.dur) + } + } +} + +func TestDurationProto(t *testing.T) { + for _, test := range durationTests { + if test.isValid && test.inRange { + got := DurationProto(test.dur) + if !proto.Equal(got, test.proto) { + t.Errorf("DurationProto(%v) = %v, want %v", test.dur, got, test.proto) + } + } + } +} diff --git a/vendor/github.com/golang/protobuf/ptypes/empty/empty.pb.go b/vendor/github.com/golang/protobuf/ptypes/empty/empty.pb.go new file mode 100644 index 00000000..e877b72c --- /dev/null +++ b/vendor/github.com/golang/protobuf/ptypes/empty/empty.pb.go @@ -0,0 +1,66 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: google/protobuf/empty.proto + +/* +Package empty is a generated protocol buffer package. + +It is generated from these files: + google/protobuf/empty.proto + +It has these top-level messages: + Empty +*/ +package empty + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package + +// A generic empty message that you can re-use to avoid defining duplicated +// empty messages in your APIs. A typical example is to use it as the request +// or the response type of an API method. For instance: +// +// service Foo { +// rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty); +// } +// +// The JSON representation for `Empty` is empty JSON object `{}`. +type Empty struct { +} + +func (m *Empty) Reset() { *m = Empty{} } +func (m *Empty) String() string { return proto.CompactTextString(m) } +func (*Empty) ProtoMessage() {} +func (*Empty) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } +func (*Empty) XXX_WellKnownType() string { return "Empty" } + +func init() { + proto.RegisterType((*Empty)(nil), "google.protobuf.Empty") +} + +func init() { proto.RegisterFile("google/protobuf/empty.proto", fileDescriptor0) } + +var fileDescriptor0 = []byte{ + // 148 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4e, 0xcf, 0xcf, 0x4f, + 0xcf, 0x49, 0xd5, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x4f, 0xcd, 0x2d, 0x28, + 0xa9, 0xd4, 0x03, 0x73, 0x85, 0xf8, 0x21, 0x92, 0x7a, 0x30, 0x49, 0x25, 0x76, 0x2e, 0x56, 0x57, + 0x90, 0xbc, 0x53, 0x19, 0x97, 0x70, 0x72, 0x7e, 0xae, 0x1e, 0x9a, 0xbc, 0x13, 0x17, 0x58, 0x36, + 0x00, 0xc4, 0x0d, 0x60, 0x8c, 0x52, 0x4f, 0xcf, 0x2c, 0xc9, 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, + 0xd5, 0x4f, 0xcf, 0xcf, 0x49, 0xcc, 0x4b, 0x47, 0x58, 0x53, 0x50, 0x52, 0x59, 0x90, 0x5a, 0x0c, + 0xb1, 0xed, 0x07, 0x23, 0xe3, 0x22, 0x26, 0x66, 0xf7, 0x00, 0xa7, 0x55, 0x4c, 0x72, 0xee, 0x10, + 0x13, 0x03, 0xa0, 0xea, 0xf4, 0xc2, 0x53, 0x73, 0x72, 0xbc, 0xf3, 0xf2, 0xcb, 0xf3, 0x42, 0x40, + 0xea, 0x93, 0xd8, 0xc0, 0x06, 0x18, 0x03, 0x02, 0x00, 0x00, 0xff, 0xff, 0x64, 0xd4, 0xb3, 0xa6, + 0xb7, 0x00, 0x00, 0x00, +} diff --git a/vendor/github.com/golang/protobuf/ptypes/empty/empty.proto b/vendor/github.com/golang/protobuf/ptypes/empty/empty.proto new file mode 100644 index 00000000..03cacd23 --- /dev/null +++ b/vendor/github.com/golang/protobuf/ptypes/empty/empty.proto @@ -0,0 +1,52 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// 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 +// OWNER 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. + +syntax = "proto3"; + +package google.protobuf; + +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; +option go_package = "github.com/golang/protobuf/ptypes/empty"; +option java_package = "com.google.protobuf"; +option java_outer_classname = "EmptyProto"; +option java_multiple_files = true; +option objc_class_prefix = "GPB"; +option cc_enable_arenas = true; + +// A generic empty message that you can re-use to avoid defining duplicated +// empty messages in your APIs. A typical example is to use it as the request +// or the response type of an API method. For instance: +// +// service Foo { +// rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty); +// } +// +// The JSON representation for `Empty` is empty JSON object `{}`. +message Empty {} diff --git a/vendor/github.com/golang/protobuf/ptypes/regen.sh b/vendor/github.com/golang/protobuf/ptypes/regen.sh new file mode 100755 index 00000000..b50a9414 --- /dev/null +++ b/vendor/github.com/golang/protobuf/ptypes/regen.sh @@ -0,0 +1,43 @@ +#!/bin/bash -e +# +# This script fetches and rebuilds the "well-known types" protocol buffers. +# To run this you will need protoc and goprotobuf installed; +# see https://github.com/golang/protobuf for instructions. +# You also need Go and Git installed. + +PKG=github.com/golang/protobuf/ptypes +UPSTREAM=https://github.com/google/protobuf +UPSTREAM_SUBDIR=src/google/protobuf +PROTO_FILES=(any duration empty struct timestamp wrappers) + +function die() { + echo 1>&2 $* + exit 1 +} + +# Sanity check that the right tools are accessible. +for tool in go git protoc protoc-gen-go; do + q=$(which $tool) || die "didn't find $tool" + echo 1>&2 "$tool: $q" +done + +tmpdir=$(mktemp -d -t regen-wkt.XXXXXX) +trap 'rm -rf $tmpdir' EXIT + +echo -n 1>&2 "finding package dir... " +pkgdir=$(go list -f '{{.Dir}}' $PKG) +echo 1>&2 $pkgdir +base=$(echo $pkgdir | sed "s,/$PKG\$,,") +echo 1>&2 "base: $base" +cd "$base" + +echo 1>&2 "fetching latest protos... " +git clone -q $UPSTREAM $tmpdir + +for file in ${PROTO_FILES[@]}; do + echo 1>&2 "* $file" + protoc --go_out=. -I$tmpdir/src $tmpdir/src/google/protobuf/$file.proto || die + cp $tmpdir/src/google/protobuf/$file.proto $PKG/$file +done + +echo 1>&2 "All OK" diff --git a/vendor/github.com/golang/protobuf/ptypes/struct/struct.pb.go b/vendor/github.com/golang/protobuf/ptypes/struct/struct.pb.go new file mode 100644 index 00000000..4cfe6081 --- /dev/null +++ b/vendor/github.com/golang/protobuf/ptypes/struct/struct.pb.go @@ -0,0 +1,380 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: google/protobuf/struct.proto + +/* +Package structpb is a generated protocol buffer package. + +It is generated from these files: + google/protobuf/struct.proto + +It has these top-level messages: + Struct + Value + ListValue +*/ +package structpb + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package + +// `NullValue` is a singleton enumeration to represent the null value for the +// `Value` type union. +// +// The JSON representation for `NullValue` is JSON `null`. +type NullValue int32 + +const ( + // Null value. + NullValue_NULL_VALUE NullValue = 0 +) + +var NullValue_name = map[int32]string{ + 0: "NULL_VALUE", +} +var NullValue_value = map[string]int32{ + "NULL_VALUE": 0, +} + +func (x NullValue) String() string { + return proto.EnumName(NullValue_name, int32(x)) +} +func (NullValue) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } +func (NullValue) XXX_WellKnownType() string { return "NullValue" } + +// `Struct` represents a structured data value, consisting of fields +// which map to dynamically typed values. In some languages, `Struct` +// might be supported by a native representation. For example, in +// scripting languages like JS a struct is represented as an +// object. The details of that representation are described together +// with the proto support for the language. +// +// The JSON representation for `Struct` is JSON object. +type Struct struct { + // Unordered map of dynamically typed values. + Fields map[string]*Value `protobuf:"bytes,1,rep,name=fields" json:"fields,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` +} + +func (m *Struct) Reset() { *m = Struct{} } +func (m *Struct) String() string { return proto.CompactTextString(m) } +func (*Struct) ProtoMessage() {} +func (*Struct) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } +func (*Struct) XXX_WellKnownType() string { return "Struct" } + +func (m *Struct) GetFields() map[string]*Value { + if m != nil { + return m.Fields + } + return nil +} + +// `Value` represents a dynamically typed value which can be either +// null, a number, a string, a boolean, a recursive struct value, or a +// list of values. A producer of value is expected to set one of that +// variants, absence of any variant indicates an error. +// +// The JSON representation for `Value` is JSON value. +type Value struct { + // The kind of value. + // + // Types that are valid to be assigned to Kind: + // *Value_NullValue + // *Value_NumberValue + // *Value_StringValue + // *Value_BoolValue + // *Value_StructValue + // *Value_ListValue + Kind isValue_Kind `protobuf_oneof:"kind"` +} + +func (m *Value) Reset() { *m = Value{} } +func (m *Value) String() string { return proto.CompactTextString(m) } +func (*Value) ProtoMessage() {} +func (*Value) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } +func (*Value) XXX_WellKnownType() string { return "Value" } + +type isValue_Kind interface { + isValue_Kind() +} + +type Value_NullValue struct { + NullValue NullValue `protobuf:"varint,1,opt,name=null_value,json=nullValue,enum=google.protobuf.NullValue,oneof"` +} +type Value_NumberValue struct { + NumberValue float64 `protobuf:"fixed64,2,opt,name=number_value,json=numberValue,oneof"` +} +type Value_StringValue struct { + StringValue string `protobuf:"bytes,3,opt,name=string_value,json=stringValue,oneof"` +} +type Value_BoolValue struct { + BoolValue bool `protobuf:"varint,4,opt,name=bool_value,json=boolValue,oneof"` +} +type Value_StructValue struct { + StructValue *Struct `protobuf:"bytes,5,opt,name=struct_value,json=structValue,oneof"` +} +type Value_ListValue struct { + ListValue *ListValue `protobuf:"bytes,6,opt,name=list_value,json=listValue,oneof"` +} + +func (*Value_NullValue) isValue_Kind() {} +func (*Value_NumberValue) isValue_Kind() {} +func (*Value_StringValue) isValue_Kind() {} +func (*Value_BoolValue) isValue_Kind() {} +func (*Value_StructValue) isValue_Kind() {} +func (*Value_ListValue) isValue_Kind() {} + +func (m *Value) GetKind() isValue_Kind { + if m != nil { + return m.Kind + } + return nil +} + +func (m *Value) GetNullValue() NullValue { + if x, ok := m.GetKind().(*Value_NullValue); ok { + return x.NullValue + } + return NullValue_NULL_VALUE +} + +func (m *Value) GetNumberValue() float64 { + if x, ok := m.GetKind().(*Value_NumberValue); ok { + return x.NumberValue + } + return 0 +} + +func (m *Value) GetStringValue() string { + if x, ok := m.GetKind().(*Value_StringValue); ok { + return x.StringValue + } + return "" +} + +func (m *Value) GetBoolValue() bool { + if x, ok := m.GetKind().(*Value_BoolValue); ok { + return x.BoolValue + } + return false +} + +func (m *Value) GetStructValue() *Struct { + if x, ok := m.GetKind().(*Value_StructValue); ok { + return x.StructValue + } + return nil +} + +func (m *Value) GetListValue() *ListValue { + if x, ok := m.GetKind().(*Value_ListValue); ok { + return x.ListValue + } + return nil +} + +// XXX_OneofFuncs is for the internal use of the proto package. +func (*Value) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { + return _Value_OneofMarshaler, _Value_OneofUnmarshaler, _Value_OneofSizer, []interface{}{ + (*Value_NullValue)(nil), + (*Value_NumberValue)(nil), + (*Value_StringValue)(nil), + (*Value_BoolValue)(nil), + (*Value_StructValue)(nil), + (*Value_ListValue)(nil), + } +} + +func _Value_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { + m := msg.(*Value) + // kind + switch x := m.Kind.(type) { + case *Value_NullValue: + b.EncodeVarint(1<<3 | proto.WireVarint) + b.EncodeVarint(uint64(x.NullValue)) + case *Value_NumberValue: + b.EncodeVarint(2<<3 | proto.WireFixed64) + b.EncodeFixed64(math.Float64bits(x.NumberValue)) + case *Value_StringValue: + b.EncodeVarint(3<<3 | proto.WireBytes) + b.EncodeStringBytes(x.StringValue) + case *Value_BoolValue: + t := uint64(0) + if x.BoolValue { + t = 1 + } + b.EncodeVarint(4<<3 | proto.WireVarint) + b.EncodeVarint(t) + case *Value_StructValue: + b.EncodeVarint(5<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.StructValue); err != nil { + return err + } + case *Value_ListValue: + b.EncodeVarint(6<<3 | proto.WireBytes) + if err := b.EncodeMessage(x.ListValue); err != nil { + return err + } + case nil: + default: + return fmt.Errorf("Value.Kind has unexpected type %T", x) + } + return nil +} + +func _Value_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { + m := msg.(*Value) + switch tag { + case 1: // kind.null_value + if wire != proto.WireVarint { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeVarint() + m.Kind = &Value_NullValue{NullValue(x)} + return true, err + case 2: // kind.number_value + if wire != proto.WireFixed64 { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeFixed64() + m.Kind = &Value_NumberValue{math.Float64frombits(x)} + return true, err + case 3: // kind.string_value + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeStringBytes() + m.Kind = &Value_StringValue{x} + return true, err + case 4: // kind.bool_value + if wire != proto.WireVarint { + return true, proto.ErrInternalBadWireType + } + x, err := b.DecodeVarint() + m.Kind = &Value_BoolValue{x != 0} + return true, err + case 5: // kind.struct_value + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(Struct) + err := b.DecodeMessage(msg) + m.Kind = &Value_StructValue{msg} + return true, err + case 6: // kind.list_value + if wire != proto.WireBytes { + return true, proto.ErrInternalBadWireType + } + msg := new(ListValue) + err := b.DecodeMessage(msg) + m.Kind = &Value_ListValue{msg} + return true, err + default: + return false, nil + } +} + +func _Value_OneofSizer(msg proto.Message) (n int) { + m := msg.(*Value) + // kind + switch x := m.Kind.(type) { + case *Value_NullValue: + n += proto.SizeVarint(1<<3 | proto.WireVarint) + n += proto.SizeVarint(uint64(x.NullValue)) + case *Value_NumberValue: + n += proto.SizeVarint(2<<3 | proto.WireFixed64) + n += 8 + case *Value_StringValue: + n += proto.SizeVarint(3<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(len(x.StringValue))) + n += len(x.StringValue) + case *Value_BoolValue: + n += proto.SizeVarint(4<<3 | proto.WireVarint) + n += 1 + case *Value_StructValue: + s := proto.Size(x.StructValue) + n += proto.SizeVarint(5<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case *Value_ListValue: + s := proto.Size(x.ListValue) + n += proto.SizeVarint(6<<3 | proto.WireBytes) + n += proto.SizeVarint(uint64(s)) + n += s + case nil: + default: + panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) + } + return n +} + +// `ListValue` is a wrapper around a repeated field of values. +// +// The JSON representation for `ListValue` is JSON array. +type ListValue struct { + // Repeated field of dynamically typed values. + Values []*Value `protobuf:"bytes,1,rep,name=values" json:"values,omitempty"` +} + +func (m *ListValue) Reset() { *m = ListValue{} } +func (m *ListValue) String() string { return proto.CompactTextString(m) } +func (*ListValue) ProtoMessage() {} +func (*ListValue) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } +func (*ListValue) XXX_WellKnownType() string { return "ListValue" } + +func (m *ListValue) GetValues() []*Value { + if m != nil { + return m.Values + } + return nil +} + +func init() { + proto.RegisterType((*Struct)(nil), "google.protobuf.Struct") + proto.RegisterType((*Value)(nil), "google.protobuf.Value") + proto.RegisterType((*ListValue)(nil), "google.protobuf.ListValue") + proto.RegisterEnum("google.protobuf.NullValue", NullValue_name, NullValue_value) +} + +func init() { proto.RegisterFile("google/protobuf/struct.proto", fileDescriptor0) } + +var fileDescriptor0 = []byte{ + // 417 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x92, 0x41, 0x8b, 0xd3, 0x40, + 0x14, 0xc7, 0x3b, 0xc9, 0x36, 0x98, 0x17, 0x59, 0x97, 0x11, 0xb4, 0xac, 0xa2, 0xa1, 0x7b, 0x09, + 0x22, 0x29, 0xd6, 0x8b, 0x18, 0x2f, 0x06, 0xd6, 0x5d, 0x30, 0x2c, 0x31, 0xba, 0x15, 0xbc, 0x94, + 0x26, 0x4d, 0x63, 0xe8, 0x74, 0x26, 0x24, 0x33, 0x4a, 0x8f, 0x7e, 0x0b, 0xcf, 0x1e, 0x3d, 0xfa, + 0xe9, 0x3c, 0xca, 0xcc, 0x24, 0xa9, 0xb4, 0xf4, 0x94, 0xbc, 0xf7, 0x7e, 0xef, 0x3f, 0xef, 0xff, + 0x66, 0xe0, 0x71, 0xc1, 0x58, 0x41, 0xf2, 0x49, 0x55, 0x33, 0xce, 0x52, 0xb1, 0x9a, 0x34, 0xbc, + 0x16, 0x19, 0xf7, 0x55, 0x8c, 0xef, 0xe9, 0xaa, 0xdf, 0x55, 0xc7, 0x3f, 0x11, 0x58, 0x1f, 0x15, + 0x81, 0x03, 0xb0, 0x56, 0x65, 0x4e, 0x96, 0xcd, 0x08, 0xb9, 0xa6, 0xe7, 0x4c, 0x2f, 0xfc, 0x3d, + 0xd8, 0xd7, 0xa0, 0xff, 0x4e, 0x51, 0x97, 0x94, 0xd7, 0xdb, 0xa4, 0x6d, 0x39, 0xff, 0x00, 0xce, + 0x7f, 0x69, 0x7c, 0x06, 0xe6, 0x3a, 0xdf, 0x8e, 0x90, 0x8b, 0x3c, 0x3b, 0x91, 0xbf, 0xf8, 0x39, + 0x0c, 0xbf, 0x2d, 0x88, 0xc8, 0x47, 0x86, 0x8b, 0x3c, 0x67, 0xfa, 0xe0, 0x40, 0x7c, 0x26, 0xab, + 0x89, 0x86, 0x5e, 0x1b, 0xaf, 0xd0, 0xf8, 0x8f, 0x01, 0x43, 0x95, 0xc4, 0x01, 0x00, 0x15, 0x84, + 0xcc, 0xb5, 0x80, 0x14, 0x3d, 0x9d, 0x9e, 0x1f, 0x08, 0xdc, 0x08, 0x42, 0x14, 0x7f, 0x3d, 0x48, + 0x6c, 0xda, 0x05, 0xf8, 0x02, 0xee, 0x52, 0xb1, 0x49, 0xf3, 0x7a, 0xbe, 0x3b, 0x1f, 0x5d, 0x0f, + 0x12, 0x47, 0x67, 0x7b, 0xa8, 0xe1, 0x75, 0x49, 0x8b, 0x16, 0x32, 0xe5, 0xe0, 0x12, 0xd2, 0x59, + 0x0d, 0x3d, 0x05, 0x48, 0x19, 0xeb, 0xc6, 0x38, 0x71, 0x91, 0x77, 0x47, 0x1e, 0x25, 0x73, 0x1a, + 0x78, 0xa3, 0x54, 0x44, 0xc6, 0x5b, 0x64, 0xa8, 0xac, 0x3e, 0x3c, 0xb2, 0xc7, 0x56, 0x5e, 0x64, + 0xbc, 0x77, 0x49, 0xca, 0xa6, 0xeb, 0xb5, 0x54, 0xef, 0xa1, 0xcb, 0xa8, 0x6c, 0x78, 0xef, 0x92, + 0x74, 0x41, 0x68, 0xc1, 0xc9, 0xba, 0xa4, 0xcb, 0x71, 0x00, 0x76, 0x4f, 0x60, 0x1f, 0x2c, 0x25, + 0xd6, 0xdd, 0xe8, 0xb1, 0xa5, 0xb7, 0xd4, 0xb3, 0x47, 0x60, 0xf7, 0x4b, 0xc4, 0xa7, 0x00, 0x37, + 0xb7, 0x51, 0x34, 0x9f, 0xbd, 0x8d, 0x6e, 0x2f, 0xcf, 0x06, 0xe1, 0x0f, 0x04, 0xf7, 0x33, 0xb6, + 0xd9, 0x97, 0x08, 0x1d, 0xed, 0x26, 0x96, 0x71, 0x8c, 0xbe, 0xbc, 0x28, 0x4a, 0xfe, 0x55, 0xa4, + 0x7e, 0xc6, 0x36, 0x93, 0x82, 0x91, 0x05, 0x2d, 0x76, 0x4f, 0xb1, 0xe2, 0xdb, 0x2a, 0x6f, 0xda, + 0x17, 0x19, 0xe8, 0x4f, 0x95, 0xfe, 0x45, 0xe8, 0x97, 0x61, 0x5e, 0xc5, 0xe1, 0x6f, 0xe3, 0xc9, + 0x95, 0x16, 0x8f, 0xbb, 0xf9, 0x3e, 0xe7, 0x84, 0xbc, 0xa7, 0xec, 0x3b, 0xfd, 0x24, 0x3b, 0x53, + 0x4b, 0x49, 0xbd, 0xfc, 0x17, 0x00, 0x00, 0xff, 0xff, 0xe8, 0x1b, 0x59, 0xf8, 0xe5, 0x02, 0x00, + 0x00, +} diff --git a/vendor/github.com/golang/protobuf/ptypes/struct/struct.proto b/vendor/github.com/golang/protobuf/ptypes/struct/struct.proto new file mode 100644 index 00000000..7d7808e7 --- /dev/null +++ b/vendor/github.com/golang/protobuf/ptypes/struct/struct.proto @@ -0,0 +1,96 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// 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 +// OWNER 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. + +syntax = "proto3"; + +package google.protobuf; + +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; +option cc_enable_arenas = true; +option go_package = "github.com/golang/protobuf/ptypes/struct;structpb"; +option java_package = "com.google.protobuf"; +option java_outer_classname = "StructProto"; +option java_multiple_files = true; +option objc_class_prefix = "GPB"; + + +// `Struct` represents a structured data value, consisting of fields +// which map to dynamically typed values. In some languages, `Struct` +// might be supported by a native representation. For example, in +// scripting languages like JS a struct is represented as an +// object. The details of that representation are described together +// with the proto support for the language. +// +// The JSON representation for `Struct` is JSON object. +message Struct { + // Unordered map of dynamically typed values. + map fields = 1; +} + +// `Value` represents a dynamically typed value which can be either +// null, a number, a string, a boolean, a recursive struct value, or a +// list of values. A producer of value is expected to set one of that +// variants, absence of any variant indicates an error. +// +// The JSON representation for `Value` is JSON value. +message Value { + // The kind of value. + oneof kind { + // Represents a null value. + NullValue null_value = 1; + // Represents a double value. + double number_value = 2; + // Represents a string value. + string string_value = 3; + // Represents a boolean value. + bool bool_value = 4; + // Represents a structured value. + Struct struct_value = 5; + // Represents a repeated `Value`. + ListValue list_value = 6; + } +} + +// `NullValue` is a singleton enumeration to represent the null value for the +// `Value` type union. +// +// The JSON representation for `NullValue` is JSON `null`. +enum NullValue { + // Null value. + NULL_VALUE = 0; +} + +// `ListValue` is a wrapper around a repeated field of values. +// +// The JSON representation for `ListValue` is JSON array. +message ListValue { + // Repeated field of dynamically typed values. + repeated Value values = 1; +} diff --git a/vendor/github.com/golang/protobuf/ptypes/timestamp.go b/vendor/github.com/golang/protobuf/ptypes/timestamp.go new file mode 100644 index 00000000..47f10dbc --- /dev/null +++ b/vendor/github.com/golang/protobuf/ptypes/timestamp.go @@ -0,0 +1,134 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2016 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// 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 +// OWNER 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. + +package ptypes + +// This file implements operations on google.protobuf.Timestamp. + +import ( + "errors" + "fmt" + "time" + + tspb "github.com/golang/protobuf/ptypes/timestamp" +) + +const ( + // Seconds field of the earliest valid Timestamp. + // This is time.Date(1, 1, 1, 0, 0, 0, 0, time.UTC).Unix(). + minValidSeconds = -62135596800 + // Seconds field just after the latest valid Timestamp. + // This is time.Date(10000, 1, 1, 0, 0, 0, 0, time.UTC).Unix(). + maxValidSeconds = 253402300800 +) + +// validateTimestamp determines whether a Timestamp is valid. +// A valid timestamp represents a time in the range +// [0001-01-01, 10000-01-01) and has a Nanos field +// in the range [0, 1e9). +// +// If the Timestamp is valid, validateTimestamp returns nil. +// Otherwise, it returns an error that describes +// the problem. +// +// Every valid Timestamp can be represented by a time.Time, but the converse is not true. +func validateTimestamp(ts *tspb.Timestamp) error { + if ts == nil { + return errors.New("timestamp: nil Timestamp") + } + if ts.Seconds < minValidSeconds { + return fmt.Errorf("timestamp: %v before 0001-01-01", ts) + } + if ts.Seconds >= maxValidSeconds { + return fmt.Errorf("timestamp: %v after 10000-01-01", ts) + } + if ts.Nanos < 0 || ts.Nanos >= 1e9 { + return fmt.Errorf("timestamp: %v: nanos not in range [0, 1e9)", ts) + } + return nil +} + +// Timestamp converts a google.protobuf.Timestamp proto to a time.Time. +// It returns an error if the argument is invalid. +// +// Unlike most Go functions, if Timestamp returns an error, the first return value +// is not the zero time.Time. Instead, it is the value obtained from the +// time.Unix function when passed the contents of the Timestamp, in the UTC +// locale. This may or may not be a meaningful time; many invalid Timestamps +// do map to valid time.Times. +// +// A nil Timestamp returns an error. The first return value in that case is +// undefined. +func Timestamp(ts *tspb.Timestamp) (time.Time, error) { + // Don't return the zero value on error, because corresponds to a valid + // timestamp. Instead return whatever time.Unix gives us. + var t time.Time + if ts == nil { + t = time.Unix(0, 0).UTC() // treat nil like the empty Timestamp + } else { + t = time.Unix(ts.Seconds, int64(ts.Nanos)).UTC() + } + return t, validateTimestamp(ts) +} + +// TimestampNow returns a google.protobuf.Timestamp for the current time. +func TimestampNow() *tspb.Timestamp { + ts, err := TimestampProto(time.Now()) + if err != nil { + panic("ptypes: time.Now() out of Timestamp range") + } + return ts +} + +// TimestampProto converts the time.Time to a google.protobuf.Timestamp proto. +// It returns an error if the resulting Timestamp is invalid. +func TimestampProto(t time.Time) (*tspb.Timestamp, error) { + seconds := t.Unix() + nanos := int32(t.Sub(time.Unix(seconds, 0))) + ts := &tspb.Timestamp{ + Seconds: seconds, + Nanos: nanos, + } + if err := validateTimestamp(ts); err != nil { + return nil, err + } + return ts, nil +} + +// TimestampString returns the RFC 3339 string for valid Timestamps. For invalid +// Timestamps, it returns an error message in parentheses. +func TimestampString(ts *tspb.Timestamp) string { + t, err := Timestamp(ts) + if err != nil { + return fmt.Sprintf("(%v)", err) + } + return t.Format(time.RFC3339Nano) +} diff --git a/vendor/github.com/golang/protobuf/ptypes/timestamp/timestamp.pb.go b/vendor/github.com/golang/protobuf/ptypes/timestamp/timestamp.pb.go new file mode 100644 index 00000000..e23e4a25 --- /dev/null +++ b/vendor/github.com/golang/protobuf/ptypes/timestamp/timestamp.pb.go @@ -0,0 +1,160 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: google/protobuf/timestamp.proto + +/* +Package timestamp is a generated protocol buffer package. + +It is generated from these files: + google/protobuf/timestamp.proto + +It has these top-level messages: + Timestamp +*/ +package timestamp + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package + +// A Timestamp represents a point in time independent of any time zone +// or calendar, represented as seconds and fractions of seconds at +// nanosecond resolution in UTC Epoch time. It is encoded using the +// Proleptic Gregorian Calendar which extends the Gregorian calendar +// backwards to year one. It is encoded assuming all minutes are 60 +// seconds long, i.e. leap seconds are "smeared" so that no leap second +// table is needed for interpretation. Range is from +// 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. +// By restricting to that range, we ensure that we can convert to +// and from RFC 3339 date strings. +// See [https://www.ietf.org/rfc/rfc3339.txt](https://www.ietf.org/rfc/rfc3339.txt). +// +// # Examples +// +// Example 1: Compute Timestamp from POSIX `time()`. +// +// Timestamp timestamp; +// timestamp.set_seconds(time(NULL)); +// timestamp.set_nanos(0); +// +// Example 2: Compute Timestamp from POSIX `gettimeofday()`. +// +// struct timeval tv; +// gettimeofday(&tv, NULL); +// +// Timestamp timestamp; +// timestamp.set_seconds(tv.tv_sec); +// timestamp.set_nanos(tv.tv_usec * 1000); +// +// Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`. +// +// FILETIME ft; +// GetSystemTimeAsFileTime(&ft); +// UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime; +// +// // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z +// // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z. +// Timestamp timestamp; +// timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL)); +// timestamp.set_nanos((INT32) ((ticks % 10000000) * 100)); +// +// Example 4: Compute Timestamp from Java `System.currentTimeMillis()`. +// +// long millis = System.currentTimeMillis(); +// +// Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000) +// .setNanos((int) ((millis % 1000) * 1000000)).build(); +// +// +// Example 5: Compute Timestamp from current time in Python. +// +// timestamp = Timestamp() +// timestamp.GetCurrentTime() +// +// # JSON Mapping +// +// In JSON format, the Timestamp type is encoded as a string in the +// [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format. That is, the +// format is "{year}-{month}-{day}T{hour}:{min}:{sec}[.{frac_sec}]Z" +// where {year} is always expressed using four digits while {month}, {day}, +// {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional +// seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution), +// are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone +// is required, though only UTC (as indicated by "Z") is presently supported. +// +// For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past +// 01:30 UTC on January 15, 2017. +// +// In JavaScript, one can convert a Date object to this format using the +// standard [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString] +// method. In Python, a standard `datetime.datetime` object can be converted +// to this format using [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) +// with the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one +// can use the Joda Time's [`ISODateTimeFormat.dateTime()`]( +// http://joda-time.sourceforge.net/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime()) +// to obtain a formatter capable of generating timestamps in this format. +// +// +type Timestamp struct { + // Represents seconds of UTC time since Unix epoch + // 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to + // 9999-12-31T23:59:59Z inclusive. + Seconds int64 `protobuf:"varint,1,opt,name=seconds" json:"seconds,omitempty"` + // Non-negative fractions of a second at nanosecond resolution. Negative + // second values with fractions must still have non-negative nanos values + // that count forward in time. Must be from 0 to 999,999,999 + // inclusive. + Nanos int32 `protobuf:"varint,2,opt,name=nanos" json:"nanos,omitempty"` +} + +func (m *Timestamp) Reset() { *m = Timestamp{} } +func (m *Timestamp) String() string { return proto.CompactTextString(m) } +func (*Timestamp) ProtoMessage() {} +func (*Timestamp) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } +func (*Timestamp) XXX_WellKnownType() string { return "Timestamp" } + +func (m *Timestamp) GetSeconds() int64 { + if m != nil { + return m.Seconds + } + return 0 +} + +func (m *Timestamp) GetNanos() int32 { + if m != nil { + return m.Nanos + } + return 0 +} + +func init() { + proto.RegisterType((*Timestamp)(nil), "google.protobuf.Timestamp") +} + +func init() { proto.RegisterFile("google/protobuf/timestamp.proto", fileDescriptor0) } + +var fileDescriptor0 = []byte{ + // 191 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4f, 0xcf, 0xcf, 0x4f, + 0xcf, 0x49, 0xd5, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x2f, 0xc9, 0xcc, 0x4d, + 0x2d, 0x2e, 0x49, 0xcc, 0x2d, 0xd0, 0x03, 0x0b, 0x09, 0xf1, 0x43, 0x14, 0xe8, 0xc1, 0x14, 0x28, + 0x59, 0x73, 0x71, 0x86, 0xc0, 0xd4, 0x08, 0x49, 0x70, 0xb1, 0x17, 0xa7, 0x26, 0xe7, 0xe7, 0xa5, + 0x14, 0x4b, 0x30, 0x2a, 0x30, 0x6a, 0x30, 0x07, 0xc1, 0xb8, 0x42, 0x22, 0x5c, 0xac, 0x79, 0x89, + 0x79, 0xf9, 0xc5, 0x12, 0x4c, 0x0a, 0x8c, 0x1a, 0xac, 0x41, 0x10, 0x8e, 0x53, 0x1d, 0x97, 0x70, + 0x72, 0x7e, 0xae, 0x1e, 0x9a, 0x99, 0x4e, 0x7c, 0x70, 0x13, 0x03, 0x40, 0x42, 0x01, 0x8c, 0x51, + 0xda, 0xe9, 0x99, 0x25, 0x19, 0xa5, 0x49, 0x7a, 0xc9, 0xf9, 0xb9, 0xfa, 0xe9, 0xf9, 0x39, 0x89, + 0x79, 0xe9, 0x08, 0x27, 0x16, 0x94, 0x54, 0x16, 0xa4, 0x16, 0x23, 0x5c, 0xfa, 0x83, 0x91, 0x71, + 0x11, 0x13, 0xb3, 0x7b, 0x80, 0xd3, 0x2a, 0x26, 0x39, 0x77, 0x88, 0xc9, 0x01, 0x50, 0xb5, 0x7a, + 0xe1, 0xa9, 0x39, 0x39, 0xde, 0x79, 0xf9, 0xe5, 0x79, 0x21, 0x20, 0x3d, 0x49, 0x6c, 0x60, 0x43, + 0x8c, 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, 0xbc, 0x77, 0x4a, 0x07, 0xf7, 0x00, 0x00, 0x00, +} diff --git a/vendor/github.com/golang/protobuf/ptypes/timestamp/timestamp.proto b/vendor/github.com/golang/protobuf/ptypes/timestamp/timestamp.proto new file mode 100644 index 00000000..b7cbd175 --- /dev/null +++ b/vendor/github.com/golang/protobuf/ptypes/timestamp/timestamp.proto @@ -0,0 +1,133 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// 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 +// OWNER 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. + +syntax = "proto3"; + +package google.protobuf; + +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; +option cc_enable_arenas = true; +option go_package = "github.com/golang/protobuf/ptypes/timestamp"; +option java_package = "com.google.protobuf"; +option java_outer_classname = "TimestampProto"; +option java_multiple_files = true; +option objc_class_prefix = "GPB"; + +// A Timestamp represents a point in time independent of any time zone +// or calendar, represented as seconds and fractions of seconds at +// nanosecond resolution in UTC Epoch time. It is encoded using the +// Proleptic Gregorian Calendar which extends the Gregorian calendar +// backwards to year one. It is encoded assuming all minutes are 60 +// seconds long, i.e. leap seconds are "smeared" so that no leap second +// table is needed for interpretation. Range is from +// 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. +// By restricting to that range, we ensure that we can convert to +// and from RFC 3339 date strings. +// See [https://www.ietf.org/rfc/rfc3339.txt](https://www.ietf.org/rfc/rfc3339.txt). +// +// # Examples +// +// Example 1: Compute Timestamp from POSIX `time()`. +// +// Timestamp timestamp; +// timestamp.set_seconds(time(NULL)); +// timestamp.set_nanos(0); +// +// Example 2: Compute Timestamp from POSIX `gettimeofday()`. +// +// struct timeval tv; +// gettimeofday(&tv, NULL); +// +// Timestamp timestamp; +// timestamp.set_seconds(tv.tv_sec); +// timestamp.set_nanos(tv.tv_usec * 1000); +// +// Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`. +// +// FILETIME ft; +// GetSystemTimeAsFileTime(&ft); +// UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime; +// +// // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z +// // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z. +// Timestamp timestamp; +// timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL)); +// timestamp.set_nanos((INT32) ((ticks % 10000000) * 100)); +// +// Example 4: Compute Timestamp from Java `System.currentTimeMillis()`. +// +// long millis = System.currentTimeMillis(); +// +// Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000) +// .setNanos((int) ((millis % 1000) * 1000000)).build(); +// +// +// Example 5: Compute Timestamp from current time in Python. +// +// timestamp = Timestamp() +// timestamp.GetCurrentTime() +// +// # JSON Mapping +// +// In JSON format, the Timestamp type is encoded as a string in the +// [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format. That is, the +// format is "{year}-{month}-{day}T{hour}:{min}:{sec}[.{frac_sec}]Z" +// where {year} is always expressed using four digits while {month}, {day}, +// {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional +// seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution), +// are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone +// is required, though only UTC (as indicated by "Z") is presently supported. +// +// For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past +// 01:30 UTC on January 15, 2017. +// +// In JavaScript, one can convert a Date object to this format using the +// standard [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString] +// method. In Python, a standard `datetime.datetime` object can be converted +// to this format using [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) +// with the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one +// can use the Joda Time's [`ISODateTimeFormat.dateTime()`]( +// http://joda-time.sourceforge.net/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime()) +// to obtain a formatter capable of generating timestamps in this format. +// +// +message Timestamp { + + // Represents seconds of UTC time since Unix epoch + // 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to + // 9999-12-31T23:59:59Z inclusive. + int64 seconds = 1; + + // Non-negative fractions of a second at nanosecond resolution. Negative + // second values with fractions must still have non-negative nanos values + // that count forward in time. Must be from 0 to 999,999,999 + // inclusive. + int32 nanos = 2; +} diff --git a/vendor/github.com/golang/protobuf/ptypes/timestamp_test.go b/vendor/github.com/golang/protobuf/ptypes/timestamp_test.go new file mode 100644 index 00000000..6e3c969b --- /dev/null +++ b/vendor/github.com/golang/protobuf/ptypes/timestamp_test.go @@ -0,0 +1,153 @@ +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2016 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// 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 +// OWNER 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. + +package ptypes + +import ( + "math" + "testing" + "time" + + "github.com/golang/protobuf/proto" + tspb "github.com/golang/protobuf/ptypes/timestamp" +) + +var tests = []struct { + ts *tspb.Timestamp + valid bool + t time.Time +}{ + // The timestamp representing the Unix epoch date. + {&tspb.Timestamp{Seconds: 0, Nanos: 0}, true, utcDate(1970, 1, 1)}, + // The smallest representable timestamp. + {&tspb.Timestamp{Seconds: math.MinInt64, Nanos: math.MinInt32}, false, + time.Unix(math.MinInt64, math.MinInt32).UTC()}, + // The smallest representable timestamp with non-negative nanos. + {&tspb.Timestamp{Seconds: math.MinInt64, Nanos: 0}, false, time.Unix(math.MinInt64, 0).UTC()}, + // The earliest valid timestamp. + {&tspb.Timestamp{Seconds: minValidSeconds, Nanos: 0}, true, utcDate(1, 1, 1)}, + //"0001-01-01T00:00:00Z"}, + // The largest representable timestamp. + {&tspb.Timestamp{Seconds: math.MaxInt64, Nanos: math.MaxInt32}, false, + time.Unix(math.MaxInt64, math.MaxInt32).UTC()}, + // The largest representable timestamp with nanos in range. + {&tspb.Timestamp{Seconds: math.MaxInt64, Nanos: 1e9 - 1}, false, + time.Unix(math.MaxInt64, 1e9-1).UTC()}, + // The largest valid timestamp. + {&tspb.Timestamp{Seconds: maxValidSeconds - 1, Nanos: 1e9 - 1}, true, + time.Date(9999, 12, 31, 23, 59, 59, 1e9-1, time.UTC)}, + // The smallest invalid timestamp that is larger than the valid range. + {&tspb.Timestamp{Seconds: maxValidSeconds, Nanos: 0}, false, time.Unix(maxValidSeconds, 0).UTC()}, + // A date before the epoch. + {&tspb.Timestamp{Seconds: -281836800, Nanos: 0}, true, utcDate(1961, 1, 26)}, + // A date after the epoch. + {&tspb.Timestamp{Seconds: 1296000000, Nanos: 0}, true, utcDate(2011, 1, 26)}, + // A date after the epoch, in the middle of the day. + {&tspb.Timestamp{Seconds: 1296012345, Nanos: 940483}, true, + time.Date(2011, 1, 26, 3, 25, 45, 940483, time.UTC)}, +} + +func TestValidateTimestamp(t *testing.T) { + for _, s := range tests { + got := validateTimestamp(s.ts) + if (got == nil) != s.valid { + t.Errorf("validateTimestamp(%v) = %v, want %v", s.ts, got, s.valid) + } + } +} + +func TestTimestamp(t *testing.T) { + for _, s := range tests { + got, err := Timestamp(s.ts) + if (err == nil) != s.valid { + t.Errorf("Timestamp(%v) error = %v, but valid = %t", s.ts, err, s.valid) + } else if s.valid && got != s.t { + t.Errorf("Timestamp(%v) = %v, want %v", s.ts, got, s.t) + } + } + // Special case: a nil Timestamp is an error, but returns the 0 Unix time. + got, err := Timestamp(nil) + want := time.Unix(0, 0).UTC() + if got != want { + t.Errorf("Timestamp(nil) = %v, want %v", got, want) + } + if err == nil { + t.Errorf("Timestamp(nil) error = nil, expected error") + } +} + +func TestTimestampProto(t *testing.T) { + for _, s := range tests { + got, err := TimestampProto(s.t) + if (err == nil) != s.valid { + t.Errorf("TimestampProto(%v) error = %v, but valid = %t", s.t, err, s.valid) + } else if s.valid && !proto.Equal(got, s.ts) { + t.Errorf("TimestampProto(%v) = %v, want %v", s.t, got, s.ts) + } + } + // No corresponding special case here: no time.Time results in a nil Timestamp. +} + +func TestTimestampString(t *testing.T) { + for _, test := range []struct { + ts *tspb.Timestamp + want string + }{ + // Not much testing needed because presumably time.Format is + // well-tested. + {&tspb.Timestamp{Seconds: 0, Nanos: 0}, "1970-01-01T00:00:00Z"}, + {&tspb.Timestamp{Seconds: minValidSeconds - 1, Nanos: 0}, "(timestamp: seconds:-62135596801 before 0001-01-01)"}, + } { + got := TimestampString(test.ts) + if got != test.want { + t.Errorf("TimestampString(%v) = %q, want %q", test.ts, got, test.want) + } + } +} + +func utcDate(year, month, day int) time.Time { + return time.Date(year, time.Month(month), day, 0, 0, 0, 0, time.UTC) +} + +func TestTimestampNow(t *testing.T) { + // Bracket the expected time. + before := time.Now() + ts := TimestampNow() + after := time.Now() + + tm, err := Timestamp(ts) + if err != nil { + t.Errorf("between %v and %v\nTimestampNow() = %v\nwhich is invalid (%v)", before, after, ts, err) + } + if tm.Before(before) || tm.After(after) { + t.Errorf("between %v and %v\nTimestamp(TimestampNow()) = %v", before, after, tm) + } +} diff --git a/vendor/github.com/golang/protobuf/ptypes/wrappers/wrappers.pb.go b/vendor/github.com/golang/protobuf/ptypes/wrappers/wrappers.pb.go new file mode 100644 index 00000000..0ed59bf1 --- /dev/null +++ b/vendor/github.com/golang/protobuf/ptypes/wrappers/wrappers.pb.go @@ -0,0 +1,260 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: google/protobuf/wrappers.proto + +/* +Package wrappers is a generated protocol buffer package. + +It is generated from these files: + google/protobuf/wrappers.proto + +It has these top-level messages: + DoubleValue + FloatValue + Int64Value + UInt64Value + Int32Value + UInt32Value + BoolValue + StringValue + BytesValue +*/ +package wrappers + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package + +// Wrapper message for `double`. +// +// The JSON representation for `DoubleValue` is JSON number. +type DoubleValue struct { + // The double value. + Value float64 `protobuf:"fixed64,1,opt,name=value" json:"value,omitempty"` +} + +func (m *DoubleValue) Reset() { *m = DoubleValue{} } +func (m *DoubleValue) String() string { return proto.CompactTextString(m) } +func (*DoubleValue) ProtoMessage() {} +func (*DoubleValue) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } +func (*DoubleValue) XXX_WellKnownType() string { return "DoubleValue" } + +func (m *DoubleValue) GetValue() float64 { + if m != nil { + return m.Value + } + return 0 +} + +// Wrapper message for `float`. +// +// The JSON representation for `FloatValue` is JSON number. +type FloatValue struct { + // The float value. + Value float32 `protobuf:"fixed32,1,opt,name=value" json:"value,omitempty"` +} + +func (m *FloatValue) Reset() { *m = FloatValue{} } +func (m *FloatValue) String() string { return proto.CompactTextString(m) } +func (*FloatValue) ProtoMessage() {} +func (*FloatValue) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } +func (*FloatValue) XXX_WellKnownType() string { return "FloatValue" } + +func (m *FloatValue) GetValue() float32 { + if m != nil { + return m.Value + } + return 0 +} + +// Wrapper message for `int64`. +// +// The JSON representation for `Int64Value` is JSON string. +type Int64Value struct { + // The int64 value. + Value int64 `protobuf:"varint,1,opt,name=value" json:"value,omitempty"` +} + +func (m *Int64Value) Reset() { *m = Int64Value{} } +func (m *Int64Value) String() string { return proto.CompactTextString(m) } +func (*Int64Value) ProtoMessage() {} +func (*Int64Value) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } +func (*Int64Value) XXX_WellKnownType() string { return "Int64Value" } + +func (m *Int64Value) GetValue() int64 { + if m != nil { + return m.Value + } + return 0 +} + +// Wrapper message for `uint64`. +// +// The JSON representation for `UInt64Value` is JSON string. +type UInt64Value struct { + // The uint64 value. + Value uint64 `protobuf:"varint,1,opt,name=value" json:"value,omitempty"` +} + +func (m *UInt64Value) Reset() { *m = UInt64Value{} } +func (m *UInt64Value) String() string { return proto.CompactTextString(m) } +func (*UInt64Value) ProtoMessage() {} +func (*UInt64Value) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } +func (*UInt64Value) XXX_WellKnownType() string { return "UInt64Value" } + +func (m *UInt64Value) GetValue() uint64 { + if m != nil { + return m.Value + } + return 0 +} + +// Wrapper message for `int32`. +// +// The JSON representation for `Int32Value` is JSON number. +type Int32Value struct { + // The int32 value. + Value int32 `protobuf:"varint,1,opt,name=value" json:"value,omitempty"` +} + +func (m *Int32Value) Reset() { *m = Int32Value{} } +func (m *Int32Value) String() string { return proto.CompactTextString(m) } +func (*Int32Value) ProtoMessage() {} +func (*Int32Value) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} } +func (*Int32Value) XXX_WellKnownType() string { return "Int32Value" } + +func (m *Int32Value) GetValue() int32 { + if m != nil { + return m.Value + } + return 0 +} + +// Wrapper message for `uint32`. +// +// The JSON representation for `UInt32Value` is JSON number. +type UInt32Value struct { + // The uint32 value. + Value uint32 `protobuf:"varint,1,opt,name=value" json:"value,omitempty"` +} + +func (m *UInt32Value) Reset() { *m = UInt32Value{} } +func (m *UInt32Value) String() string { return proto.CompactTextString(m) } +func (*UInt32Value) ProtoMessage() {} +func (*UInt32Value) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} } +func (*UInt32Value) XXX_WellKnownType() string { return "UInt32Value" } + +func (m *UInt32Value) GetValue() uint32 { + if m != nil { + return m.Value + } + return 0 +} + +// Wrapper message for `bool`. +// +// The JSON representation for `BoolValue` is JSON `true` and `false`. +type BoolValue struct { + // The bool value. + Value bool `protobuf:"varint,1,opt,name=value" json:"value,omitempty"` +} + +func (m *BoolValue) Reset() { *m = BoolValue{} } +func (m *BoolValue) String() string { return proto.CompactTextString(m) } +func (*BoolValue) ProtoMessage() {} +func (*BoolValue) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} } +func (*BoolValue) XXX_WellKnownType() string { return "BoolValue" } + +func (m *BoolValue) GetValue() bool { + if m != nil { + return m.Value + } + return false +} + +// Wrapper message for `string`. +// +// The JSON representation for `StringValue` is JSON string. +type StringValue struct { + // The string value. + Value string `protobuf:"bytes,1,opt,name=value" json:"value,omitempty"` +} + +func (m *StringValue) Reset() { *m = StringValue{} } +func (m *StringValue) String() string { return proto.CompactTextString(m) } +func (*StringValue) ProtoMessage() {} +func (*StringValue) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} } +func (*StringValue) XXX_WellKnownType() string { return "StringValue" } + +func (m *StringValue) GetValue() string { + if m != nil { + return m.Value + } + return "" +} + +// Wrapper message for `bytes`. +// +// The JSON representation for `BytesValue` is JSON string. +type BytesValue struct { + // The bytes value. + Value []byte `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"` +} + +func (m *BytesValue) Reset() { *m = BytesValue{} } +func (m *BytesValue) String() string { return proto.CompactTextString(m) } +func (*BytesValue) ProtoMessage() {} +func (*BytesValue) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} } +func (*BytesValue) XXX_WellKnownType() string { return "BytesValue" } + +func (m *BytesValue) GetValue() []byte { + if m != nil { + return m.Value + } + return nil +} + +func init() { + proto.RegisterType((*DoubleValue)(nil), "google.protobuf.DoubleValue") + proto.RegisterType((*FloatValue)(nil), "google.protobuf.FloatValue") + proto.RegisterType((*Int64Value)(nil), "google.protobuf.Int64Value") + proto.RegisterType((*UInt64Value)(nil), "google.protobuf.UInt64Value") + proto.RegisterType((*Int32Value)(nil), "google.protobuf.Int32Value") + proto.RegisterType((*UInt32Value)(nil), "google.protobuf.UInt32Value") + proto.RegisterType((*BoolValue)(nil), "google.protobuf.BoolValue") + proto.RegisterType((*StringValue)(nil), "google.protobuf.StringValue") + proto.RegisterType((*BytesValue)(nil), "google.protobuf.BytesValue") +} + +func init() { proto.RegisterFile("google/protobuf/wrappers.proto", fileDescriptor0) } + +var fileDescriptor0 = []byte{ + // 259 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4b, 0xcf, 0xcf, 0x4f, + 0xcf, 0x49, 0xd5, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x2f, 0x2f, 0x4a, 0x2c, + 0x28, 0x48, 0x2d, 0x2a, 0xd6, 0x03, 0x8b, 0x08, 0xf1, 0x43, 0xe4, 0xf5, 0x60, 0xf2, 0x4a, 0xca, + 0x5c, 0xdc, 0x2e, 0xf9, 0xa5, 0x49, 0x39, 0xa9, 0x61, 0x89, 0x39, 0xa5, 0xa9, 0x42, 0x22, 0x5c, + 0xac, 0x65, 0x20, 0x86, 0x04, 0xa3, 0x02, 0xa3, 0x06, 0x63, 0x10, 0x84, 0xa3, 0xa4, 0xc4, 0xc5, + 0xe5, 0x96, 0x93, 0x9f, 0x58, 0x82, 0x45, 0x0d, 0x13, 0x92, 0x1a, 0xcf, 0xbc, 0x12, 0x33, 0x13, + 0x2c, 0x6a, 0x98, 0x61, 0x6a, 0x94, 0xb9, 0xb8, 0x43, 0x71, 0x29, 0x62, 0x41, 0x35, 0xc8, 0xd8, + 0x08, 0x8b, 0x1a, 0x56, 0x34, 0x83, 0xb0, 0x2a, 0xe2, 0x85, 0x29, 0x52, 0xe4, 0xe2, 0x74, 0xca, + 0xcf, 0xcf, 0xc1, 0xa2, 0x84, 0x03, 0xc9, 0x9c, 0xe0, 0x92, 0xa2, 0xcc, 0xbc, 0x74, 0x2c, 0x8a, + 0x38, 0x91, 0x1c, 0xe4, 0x54, 0x59, 0x92, 0x5a, 0x8c, 0x45, 0x0d, 0x0f, 0x54, 0x8d, 0x53, 0x0d, + 0x97, 0x70, 0x72, 0x7e, 0xae, 0x1e, 0x5a, 0xe8, 0x3a, 0xf1, 0x86, 0x43, 0x83, 0x3f, 0x00, 0x24, + 0x12, 0xc0, 0x18, 0xa5, 0x95, 0x9e, 0x59, 0x92, 0x51, 0x9a, 0xa4, 0x97, 0x9c, 0x9f, 0xab, 0x9f, + 0x9e, 0x9f, 0x93, 0x98, 0x97, 0x8e, 0x88, 0xaa, 0x82, 0x92, 0xca, 0x82, 0xd4, 0x62, 0x78, 0x8c, + 0xfd, 0x60, 0x64, 0x5c, 0xc4, 0xc4, 0xec, 0x1e, 0xe0, 0xb4, 0x8a, 0x49, 0xce, 0x1d, 0x62, 0x6e, + 0x00, 0x54, 0xa9, 0x5e, 0x78, 0x6a, 0x4e, 0x8e, 0x77, 0x5e, 0x7e, 0x79, 0x5e, 0x08, 0x48, 0x4b, + 0x12, 0x1b, 0xd8, 0x0c, 0x63, 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0x19, 0x6c, 0xb9, 0xb8, 0xfe, + 0x01, 0x00, 0x00, +} diff --git a/vendor/github.com/golang/protobuf/ptypes/wrappers/wrappers.proto b/vendor/github.com/golang/protobuf/ptypes/wrappers/wrappers.proto new file mode 100644 index 00000000..01947639 --- /dev/null +++ b/vendor/github.com/golang/protobuf/ptypes/wrappers/wrappers.proto @@ -0,0 +1,118 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// 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 +// OWNER 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. + +// Wrappers for primitive (non-message) types. These types are useful +// for embedding primitives in the `google.protobuf.Any` type and for places +// where we need to distinguish between the absence of a primitive +// typed field and its default value. + +syntax = "proto3"; + +package google.protobuf; + +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; +option cc_enable_arenas = true; +option go_package = "github.com/golang/protobuf/ptypes/wrappers"; +option java_package = "com.google.protobuf"; +option java_outer_classname = "WrappersProto"; +option java_multiple_files = true; +option objc_class_prefix = "GPB"; + +// Wrapper message for `double`. +// +// The JSON representation for `DoubleValue` is JSON number. +message DoubleValue { + // The double value. + double value = 1; +} + +// Wrapper message for `float`. +// +// The JSON representation for `FloatValue` is JSON number. +message FloatValue { + // The float value. + float value = 1; +} + +// Wrapper message for `int64`. +// +// The JSON representation for `Int64Value` is JSON string. +message Int64Value { + // The int64 value. + int64 value = 1; +} + +// Wrapper message for `uint64`. +// +// The JSON representation for `UInt64Value` is JSON string. +message UInt64Value { + // The uint64 value. + uint64 value = 1; +} + +// Wrapper message for `int32`. +// +// The JSON representation for `Int32Value` is JSON number. +message Int32Value { + // The int32 value. + int32 value = 1; +} + +// Wrapper message for `uint32`. +// +// The JSON representation for `UInt32Value` is JSON number. +message UInt32Value { + // The uint32 value. + uint32 value = 1; +} + +// Wrapper message for `bool`. +// +// The JSON representation for `BoolValue` is JSON `true` and `false`. +message BoolValue { + // The bool value. + bool value = 1; +} + +// Wrapper message for `string`. +// +// The JSON representation for `StringValue` is JSON string. +message StringValue { + // The string value. + string value = 1; +} + +// Wrapper message for `bytes`. +// +// The JSON representation for `BytesValue` is JSON string. +message BytesValue { + // The bytes value. + bytes value = 1; +} diff --git a/vendor/github.com/jmank88/nuts/.gitignore b/vendor/github.com/jmank88/nuts/.gitignore new file mode 100644 index 00000000..f562d2c8 --- /dev/null +++ b/vendor/github.com/jmank88/nuts/.gitignore @@ -0,0 +1,3 @@ +.idea +testdata +vendor/ \ No newline at end of file diff --git a/vendor/github.com/jmank88/nuts/.travis.yml b/vendor/github.com/jmank88/nuts/.travis.yml new file mode 100644 index 00000000..66385620 --- /dev/null +++ b/vendor/github.com/jmank88/nuts/.travis.yml @@ -0,0 +1,9 @@ +language: go + +go: + - 1.x + - tip + +install: + - go get -u github.com/golang/dep/... + - dep ensure -vendor-only \ No newline at end of file diff --git a/vendor/github.com/jmank88/nuts/Gopkg.lock b/vendor/github.com/jmank88/nuts/Gopkg.lock new file mode 100644 index 00000000..e6473ae6 --- /dev/null +++ b/vendor/github.com/jmank88/nuts/Gopkg.lock @@ -0,0 +1,21 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/boltdb/bolt" + packages = ["."] + revision = "2f1ce7a837dcb8da3ec595b1dac9d0632f0f99e8" + version = "v1.3.1" + +[[projects]] + branch = "master" + name = "golang.org/x/sys" + packages = ["unix"] + revision = "7ddbeae9ae08c6a06a59597f0c9edbc5ff2444ce" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "568758fa97eac2946d6043bc72b7e728f802aeba2169c527f8fbad2222e74700" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/github.com/jmank88/nuts/Gopkg.toml b/vendor/github.com/jmank88/nuts/Gopkg.toml new file mode 100644 index 00000000..f6598803 --- /dev/null +++ b/vendor/github.com/jmank88/nuts/Gopkg.toml @@ -0,0 +1,3 @@ +[[constraint]] + name = "github.com/boltdb/bolt" + version = "^1.0.0" diff --git a/vendor/github.com/jmank88/nuts/LICENSE b/vendor/github.com/jmank88/nuts/LICENSE new file mode 100644 index 00000000..da7ae80f --- /dev/null +++ b/vendor/github.com/jmank88/nuts/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017 Jordan Krage + +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/jmank88/nuts/README.md b/vendor/github.com/jmank88/nuts/README.md new file mode 100644 index 00000000..ad81fb58 --- /dev/null +++ b/vendor/github.com/jmank88/nuts/README.md @@ -0,0 +1,53 @@ +# Nuts - BoltDB Utilities + +[![GoDoc](https://godoc.org/github.com/jmank88/nuts?status.svg)](https://godoc.org/github.com/jmank88/nuts) [![Go Report Card](https://goreportcard.com/badge/github.com/jmank88/nuts)](https://goreportcard.com/report/github.com/jmank88/nuts) [![Coverage Status](https://coveralls.io/repos/github/jmank88/nuts/badge.svg?branch=master)](https://coveralls.io/github/jmank88/nuts?branch=master) + +A collection of [BoltDB](https://github.com/boltdb/bolt) utilities. + +## Path Prefix Scans + +The prefix scanning functions `SeekPathConflict` and `SeekPathMatch` facilitate maintenance and access to buckets of +paths supporting *variable elements* with *exclusive matches*. Paths are `/` delimited, must begin with a `/`, and +elements beginning with `:` or `*` are variable. + +Examples: + +``` +/ +/blogs/ +/blogs/:blog_id +``` + +### Variable Elements + +Path elements beginning with a `:` match any single element. Path elements beginning with `*` match any remaining +elements, and therefore must be last. + +Examples: + +``` +Path: /blogs/:blog_id +Match: /blogs/someblog +``` + +``` +Path: /blogs/:blog_id/comments/:comment_id/*suffix +Match: /blogs/42/comments/100/edit +``` + +### Exclusive Matches + +Using `SeekPathConflict` before putting new paths to ensure the bucket remains conflict-free guarantees that `SeekPathMatch` +will never match more than one path. + +Examples: + +``` +Conflicts: `/blogs/:blog_id`, `/blogs/golang` +Match: `/blogs/golang` +``` + +``` +Conflicts: `/blogs/*`, `/blogs/:blog_id/comments` +Match: `/blogs/42/comments` +``` diff --git a/vendor/github.com/jmank88/nuts/cmd/testdb/main.go b/vendor/github.com/jmank88/nuts/cmd/testdb/main.go new file mode 100644 index 00000000..4c7103cf --- /dev/null +++ b/vendor/github.com/jmank88/nuts/cmd/testdb/main.go @@ -0,0 +1,89 @@ +/* +Command testdb recursively walks the directory given as the first (and only) argument, and copies paths from .txt files +into .db BoltDB database files by the same name. +*/ +package main + +import ( + "bufio" + "fmt" + "log" + "os" + "path/filepath" + "strings" + + "github.com/boltdb/bolt" + "github.com/jmank88/nuts" +) + +func main() { + if len(os.Args) < 2 { + log.Fatal("too few arguments") + } + dir := os.Args[1] + if err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + if !info.IsDir() && strings.HasSuffix(path, ".txt") { + if err := copyToBolt(path); err != nil { + log.Printf("failed to copy %q to boltdb: %s\n", path, err) + } + } + return nil + }); err != nil { + log.Fatal("failed to walk files", err) + } +} + +const batchSize = 10000 + +func copyToBolt(txt string) (err error) { + path := strings.TrimSuffix(txt, ".txt") + ".db" + + db, err := bolt.Open(path, 0666, nil) + if err != nil { + return err + } + defer func() { + if err2 := db.Close(); err2 != nil && err == nil { + err = err2 + } + }() + + f, err := os.Open(txt) + if err != nil { + return err + } + defer f.Close() + + // Use default, ScanLines + s := bufio.NewScanner(f) + done := false + for !done { + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucketIfNotExists([]byte("paths")) + if err != nil { + return err + } + + for batch := 0; batch < batchSize; batch++ { + if !s.Scan() { + done = true + return s.Err() + } + path := s.Bytes() + if k, _ := nuts.SeekPathConflict(b.Cursor(), path); k != nil { + return fmt.Errorf("path %q conflicts with existing %q", string(path), string(k)) + } + if err := b.Put(path, []byte{}); err != nil { + return err + } + } + return nil + }); err != nil { + return err + } + } + return nil +} diff --git a/vendor/github.com/jmank88/nuts/cmd/testpaths/main.go b/vendor/github.com/jmank88/nuts/cmd/testpaths/main.go new file mode 100644 index 00000000..0f46a446 --- /dev/null +++ b/vendor/github.com/jmank88/nuts/cmd/testpaths/main.go @@ -0,0 +1,156 @@ +/* +Command testpaths generates files with one path per line. The first argument is the output directory and the second +must be one of 'standard', 'branchFactor', 'segmentCount', or 'segmentSize'. Each additional (integer) argument +generates a .txt file by the same name. +*/ +package main + +import ( + "bytes" + "crypto/md5" + "encoding/binary" + "fmt" + "hash/fnv" + "io" + "log" + "os" + "path/filepath" + "strconv" + "strings" +) + +// A writePathFn should write one path per line to w. +type writePathFn func(w io.Writer, arg int64) + +// Writes count routes of a 'standard' form. +func standard(w io.Writer, count int64) { + for i := int64(0); i < count; i++ { + path := generateRoute(uint64(i)) + if _, err := io.WriteString(w, path); err != nil { + log.Fatalf("failed to write path #%d %q: %s", i, path, err) + } + if _, err := w.Write([]byte{'\n'}); err != nil { + log.Fatal("failed to write new line:", err) + } + } +} + +// Writes count routes with different values for the same component. +func branchFactor(w io.Writer, count int64) { + for i := int64(0); i < count; i++ { + sum := md5.Sum([]byte{byte(i >> 16), byte(i), byte(i >> 24), byte(i >> 8)}) + if _, err := fmt.Fprintf(w, "/%x", sum); err != nil { + log.Fatalf("failed to write path #%d: %s", i, err) + } + if _, err := w.Write([]byte{'\n'}); err != nil { + log.Fatal("failed to write new line:", err) + } + } +} + +// Writes a route with count segments. +func segmentCount(w io.Writer, count int64) { + path := strings.Repeat("/test", int(count)) + if _, err := io.WriteString(w, path); err != nil { + log.Fatalf("failed to write path %d", count) + } +} + +// Writes a route with 5 counts sized segments. +func segmentSize(w io.Writer, size int64) { + path := strings.Repeat("/"+strings.Repeat("a", int(size)), 5) + if _, err := io.WriteString(w, path); err != nil { + log.Fatalf("failed to write path %d", size) + } +} + +func main() { + if len(os.Args) < 4 { + log.Fatal("too few arguments") + } + + dir := os.Args[1] + name := os.Args[2] + nameDir := filepath.Join(dir, name) + if err := os.MkdirAll(nameDir, 0777); err != nil { + log.Fatal("failed to create diretory:", err) + } + + var writePath writePathFn + switch name { + case "standard": + writePath = standard + case "branchFactor": + writePath = branchFactor + case "segmentCount": + writePath = segmentCount + case "segmentSize": + writePath = segmentSize + default: + log.Fatal("unrecognized name:", name) + } + + for _, arg := range os.Args[3:] { + routes, err := strconv.ParseInt(arg, 10, 0) + if err != nil { + log.Fatal("failed to parse argument:", err) + } + + createFile(filepath.Join(nameDir, arg+".txt"), routes, writePath) + } +} + +func createFile(name string, arg int64, writePath writePathFn) { + f, err := os.Create(name) + if err != nil { + log.Fatal("failed to create file:", err) + } + defer f.Close() + writePath(f, arg) +} + +// generateRoute generates a deterministic test route based on u. +// Routes are 32 bytes printed as hex, and split into 1, 2, 4, or 8 parts. +// ~1/5 of the parts after the first are parameters. ~1/2 of suffix parameters are catch all. +// Example: /61aab75e6134555e/:param/20c98ae9da239a03/*wildcard +// +// Verified conflict free up to: 1,000,000 +func generateRoute(u uint64) string { + s := make([]byte, 0, 32) + h128 := fnv.New128() + + num := make([]byte, 64) + binary.BigEndian.PutUint64(num, u) + _, _ = h128.Write(num) + s = h128.Sum(s) + h128.Reset() + binary.LittleEndian.PutUint64(num, u) + _, _ = h128.Write(num) + s = h128.Sum(s) + + parts := 1 << (u % 4) // [1,2,4,8] + each := len(s) / parts // [32,16,8,4] + + var b bytes.Buffer + h64 := fnv.New64() + for i := 0; i < parts; i++ { + b.WriteRune('/') + + h64.Reset() + h64.Write(b.Bytes()) + // if not first, 1/5 chance of param + if i > 0 && h64.Sum64()%5 == 0 { + // if last, 1/2 chance of * + if i == parts-1 && u%2 == 0 { + b.WriteString(`*wildcard`) + } else { + b.WriteString(`:param`) + } + } else { + nameStart := i * each + fmt.Fprintf(&b, "%x", s[nameStart:nameStart+each]) + } + } + + return b.String() +} diff --git a/vendor/github.com/jmank88/nuts/example_test.go b/vendor/github.com/jmank88/nuts/example_test.go new file mode 100644 index 00000000..e209c6a7 --- /dev/null +++ b/vendor/github.com/jmank88/nuts/example_test.go @@ -0,0 +1,22 @@ +package nuts + +import ( + "fmt" +) + +func ExampleKey_UUID() { + type uuid struct{ a, b uint64 } + + u := uuid{ + a: 0xaaaaaaaaaaaaaaaa, + b: 0xbbbbbbbbbbbbbbbb, + } + + key := make(Key, 16) + key[:8].Put(u.a) + key[8:].Put(u.b) + fmt.Printf("%#x", key) + + // Output: + // 0xaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbb +} diff --git a/vendor/github.com/jmank88/nuts/key.go b/vendor/github.com/jmank88/nuts/key.go new file mode 100644 index 00000000..55430c40 --- /dev/null +++ b/vendor/github.com/jmank88/nuts/key.go @@ -0,0 +1,39 @@ +package nuts + +// KeyLen returns the minimum number of bytes required to represent x; the result is 1 for x == 0. +// Returns 1-8. +func KeyLen(x uint64) int { + n := 1 + if x >= 1<<32 { + x >>= 32 + n += 4 + } + if x >= 1<<16 { + x >>= 16 + n += 2 + } + if x >= 1<<8 { + x >>= 8 + n += 1 + } + return n +} + +// Key is a byte slice with methods for serializing uint64 (big endian). +// Length can minimized (<8) with KeyLen. +// make(Key, KeyLen(uint64(max))) +// Large Keys can constructed by slicing. +// uuid := make(Key, 16) +// uuid[:8].Put(a) +// uuid[8:].Put(b) +type Key []byte + +// Put serializes x into the buffer (big endian). Behavior is undefined when x +// does not fit, so the caller must ensure c is large enough. +func (c Key) Put(x uint64) { + s := uint(8 * (len(c) - 1)) + for i := range c { + c[i] = byte(x >> s) + s -= 8 + } +} diff --git a/vendor/github.com/jmank88/nuts/key_test.go b/vendor/github.com/jmank88/nuts/key_test.go new file mode 100644 index 00000000..8fbcf783 --- /dev/null +++ b/vendor/github.com/jmank88/nuts/key_test.go @@ -0,0 +1,114 @@ +package nuts + +import ( + "bytes" + "strconv" + "testing" +) + +func TestKeyLen(t *testing.T) { + for _, test := range []struct { + x uint64 + exp int + }{ + {0, 1}, + {1, 1}, + {1 << 8, 2}, + {1 << 16, 3}, + {1 << 24, 4}, + {1 << 32, 5}, + {1 << 40, 6}, + {1 << 48, 7}, + {1 << 56, 8}, + } { + got := KeyLen(test.x) + if got != test.exp { + t.Errorf("%d: expected length %d but got %d", test.x, test.exp, got) + } + } +} + +func TestKey(t *testing.T) { + for _, test := range []struct { + max int + xs []uint64 + bs [][]byte + }{ + { + max: 1 << 7, + xs: []uint64{0, 1, (1 << 8) - 1}, + bs: [][]byte{ + {0x00}, {0x01}, {0xFF}, + }, + }, + { + max: 1 << 15, + xs: []uint64{0, 1, (1 << 16) - 1}, + bs: [][]byte{ + {0x00, 0x00}, {0x00, 0x01}, {0xFF, 0xFF}, + }, + }, + { + max: 1 << 23, + xs: []uint64{0, 1, (1 << 24) - 1}, + bs: [][]byte{ + {0x00, 0x00, 0x00}, {0x00, 0x00, 0x01}, {0xFF, 0xFF, 0xFF}, + }, + }, + { + max: 1 << 31, + xs: []uint64{0, 1, (1 << 32) - 1}, + bs: [][]byte{ + {0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x01}, + {0xFF, 0xFF, 0xFF, 0xFF}, + }, + }, + { + max: 1 << 39, + xs: []uint64{0, 1, (1 << 40) - 1}, + bs: [][]byte{ + {0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x01}, + {0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, + }, + }, + { + max: 1 << 47, + xs: []uint64{0, 1, (1 << 48) - 1}, + bs: [][]byte{ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, + {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, + }, + }, + { + max: 1 << 55, + xs: []uint64{0, 1, (1 << 56) - 1}, + bs: [][]byte{ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, + {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, + }, + }, + { + max: 1 << 60, + xs: []uint64{0, 1, (1 << 60) - 1}, + bs: [][]byte{ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, + {0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, + }, + }, + } { + t.Run(strconv.Itoa(test.max), func(t *testing.T) { + k := make(Key, KeyLen(uint64(test.max))) + for i, x := range test.xs { + k.Put(x) + if !bytes.Equal(k, test.bs[i]) { + t.Errorf("unexpected serialized integer %d:\n\t(GOT): %#x\n\t(WNT): %#x", x, k, test.bs[i]) + } + } + }) + } +} diff --git a/vendor/github.com/jmank88/nuts/nuts.go b/vendor/github.com/jmank88/nuts/nuts.go new file mode 100644 index 00000000..99f5d094 --- /dev/null +++ b/vendor/github.com/jmank88/nuts/nuts.go @@ -0,0 +1,2 @@ +// Package nuts is a collection of utilities for BoltDB (https://github.com/boltdb/bolt). +package nuts diff --git a/vendor/github.com/jmank88/nuts/paths.go b/vendor/github.com/jmank88/nuts/paths.go new file mode 100644 index 00000000..2d336afb --- /dev/null +++ b/vendor/github.com/jmank88/nuts/paths.go @@ -0,0 +1,260 @@ +package nuts + +/* +Path Prefix Scans + +The prefix scanning methods `SeekPathConflict` and `SeekPathMatch` facilitate maintenance and access to buckets of paths +supporting variable elements with exclusive matches. Paths are `/` delimited, must begin with a `/`, and elements +beginning with `:` or `*` are variable. + +Examples: + / + /blogs/ + /blogs/:blog_id + +Variable Paths + +Path elements beginning with a `:` match any single element. Path elements beginning with `*` match any remaining +suffix, and therefore must be the last element. + +Examples: + Path: /blogs/:blog_id + Match: /blogs/someblog + + Path: /blogs/:blog_id/comments/:comment_id/*suffix + Match: /blogs/42/comments/100/edit + +Exclusive Matches + +Using `SeekPathConflict` before putting new paths to ensure the bucket remains conflict-free guarantees that +`SeekPathMatch` will never match more than one path. + +Examples: + Conflicts: /blogs/:blog_id, /blogs/golang + Match: /blogs/golang + + Conflicts: /blogs/*, /blogs/:blog_id/comments + Match: /blogs/42/comments +*/ + +import ( + "bytes" + + "github.com/boltdb/bolt" +) + +// SeekPathMatch seeks an entry which matches `path`, or returns `nil, nil` when no match is found. +// Returned key may be `path`, or a matching dynamic path. +// Matches are exclusive if the set of keys are conflict free (see SeekPathConflict). +func SeekPathMatch(c *bolt.Cursor, path []byte) ([]byte, []byte) { + // Validation + if len(path) == 0 { + return nil, nil + } + if path[0] != '/' { + return nil, nil + } + + // Exact match fast-path + if k, v := c.Seek(path); bytes.Equal(k, path) { + return k, v + } + + // Prefix scan + prefixBuf := bytes.NewBuffer(make([]byte, 0, len(path))) + for { + // Match slash + prefixBuf.WriteByte('/') + prefix := prefixBuf.Bytes() + k, v := c.Seek(prefix) + if !bytes.HasPrefix(k, prefix) { + return nil, nil + } + // Advance past '/' + path = path[1:] + + // Exact match required for trailing slash. + if len(path) == 0 { + if len(k) == len(prefix) { + return k, v + } + return nil, nil + } + + // Advance cursor past exact match to first prefix match. + if len(k) == len(prefix) { + k, v = c.Next() + if !bytes.HasPrefix(k, prefix) { + return nil, nil + } + } + + // Find end of element. + i := bytes.IndexByte(path, '/') + last := i < 0 + + switch k[len(prefix)] { + case '*': + return k, v + + case ':': + // Append variable path element to prefix + ki := bytes.IndexByte(k[len(prefix):], '/') + if ki < 0 { + prefixBuf.Write(k[len(prefix):]) + } else { + prefixBuf.Write(k[len(prefix) : len(prefix)+ki]) + } + + if last { + // Exact match required for last element. + prefix = prefixBuf.Bytes() + if k, v = c.Seek(prefix); bytes.Equal(k, prefix) { + return k, v + } + return nil, nil + } + + default: + // Append path component to prefix. + if last { + prefixBuf.Write(path) + } else { + prefixBuf.Write(path[:i]) + } + + prefix = prefixBuf.Bytes() + k, v = c.Seek(prefix) + + if last { + // Exact match required for last element. + if bytes.Equal(k, prefix) { + return k, v + } + return nil, nil + } + + // Prefix match required for other elements. + if !bytes.HasPrefix(k, prefix) { + return nil, nil + } + } + + // Advance past element. + path = path[i:] + } +} + +// SeekPathConflict seeks an entry which conflicts with `path`, and returns the first encountered or `nil, nil` if none +// is found. +func SeekPathConflict(c *bolt.Cursor, path []byte) ([]byte, []byte) { + // Validation + if len(path) == 0 { + return nil, nil + } + if path[0] != '/' { + return nil, nil + } + + // Fast-path for exact and prefix match. + if k, v := c.Seek(path); bytes.Equal(k, path) { + return k, v + } else if bytes.HasPrefix(k, path) { + // Any prefixed k is good enough when path ends in '/'. + if path[len(path)-1] == '/' { + return nil, nil + } + + // If k's last element is longer it could be a conflict. + if k[len(path)] == '/' { + return nil, nil + } + } + + // Prefix scan. + i := 0 + for { + i++ + + // Match slash. + prefix := path[:i] + k, v := c.Seek(prefix) + if !bytes.HasPrefix(k, prefix) { + return nil, nil + } + + // Exact match is a conflict for trailing slash. + if i == len(path) { + if len(k) == len(path) { + return k, v + } + return nil, nil + } + + // Advance cursor past exact match to first prefix match. + if len(k) == len(prefix) { + k, v = c.Next() + if !bytes.HasPrefix(k, prefix) { + return nil, nil + } + } + + // Find end of element. + offset := bytes.IndexByte(path[i:], '/') + last := offset < 0 + if last { + i = len(path) + } else { + i += offset + } + + switch k[len(prefix)] { + case '*': + return k, v + + case ':': + // Find end of element. + kPrefix := k + offset := bytes.IndexByte(k[len(prefix):], '/') + if offset > 0 { + kPrefix = k[:len(prefix)+offset] + } + + // Exact match required through variable element. + prefix = path[:i] + if !bytes.Equal(prefix, kPrefix) { + return k, v + } + + if last { + // Exact match is a conflict for the last element. + if k, v = c.Seek(prefix); bytes.Equal(k, prefix) { + return k, v + } + return nil, nil + } + + default: + // Static (non-variable) element required. + next := path[len(prefix)] + if next == ':' || next == '*' { + return k, v + } + + prefix = path[:i] + k, v = c.Seek(prefix) + + if last { + // Exact match is a conflict for the last element. + if bytes.Equal(k, prefix) { + return k, v + } + return nil, nil + } + + if !bytes.HasPrefix(k, prefix) { + return nil, nil + } + } + } +} diff --git a/vendor/github.com/jmank88/nuts/paths_test.go b/vendor/github.com/jmank88/nuts/paths_test.go new file mode 100644 index 00000000..33a698b0 --- /dev/null +++ b/vendor/github.com/jmank88/nuts/paths_test.go @@ -0,0 +1,338 @@ +//go:generate rm -rf testdata +// +//go:generate go run cmd/testpaths/main.go testdata standard 10 100 1000 10000 100000 1000000 +//go:generate go run cmd/testpaths/main.go testdata segmentCount 1 5 10 50 100 +//go:generate go run cmd/testpaths/main.go testdata branchFactor 1 5 10 50 100 500 1000 5000 10000 +//go:generate go run cmd/testpaths/main.go testdata segmentSize 1 5 10 50 100 200 +// +//go:generate go run cmd/testdb/main.go testdata +package nuts + +import ( + "bufio" + "bytes" + "errors" + "fmt" + "io/ioutil" + "log" + "os" + "path/filepath" + "strings" + "testing" + + "github.com/boltdb/bolt" +) + +var bucketName = []byte("testBucket") + +func exDB(f func(db *bolt.DB)) { + tmp := tempfile() + defer os.Remove(tmp) + db, err := bolt.Open(tmp, 0666, nil) + if err != nil { + log.Fatal(err) + } + defer db.Close() + f(db) +} + +func ExampleSeekPathMatch() { + exDB(func(db *bolt.DB) { + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket(bucketName) + if err != nil { + return err + } + + // Put a variable path. + return b.Put([]byte("/blogs/:blog_id/comments/:comment_id"), []byte{}) + }); err != nil { + log.Fatal(err) + } + + if err := db.View(func(tx *bolt.Tx) error { + b := tx.Bucket(bucketName) + + // Match path. + path, _ := SeekPathMatch(b.Cursor(), []byte("/blogs/asdf/comments/42")) + fmt.Println(string(path)) + + return nil + }); err != nil { + log.Fatal(err) + } + }) + + // Output: /blogs/:blog_id/comments/:comment_id +} + +func ExampleSeekPathConflict() { + exDB(func(db *bolt.DB) { + insert := func(path string) { + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucketIfNotExists(bucketName) + if err != nil { + return err + } + + // Check for conflicts. + if k, _ := SeekPathConflict(b.Cursor(), []byte(path)); k != nil { + fmt.Printf("Put(%s) blocked - conflict: %s\n", path, string(k)) + return nil + } + + // Put. + if err := b.Put([]byte(path), []byte{}); err != nil { + return err + } + fmt.Printf("Put(%s)\n", path) + return nil + }); err != nil { + log.Fatal(err) + } + } + // Put + insert("/blogs/") + // Put + insert("/blogs/:blog_id") + // Conflict + insert("/blogs/a_blog") + }) + + // Output: + // Put(/blogs/) + // Put(/blogs/:blog_id) + // Put(/blogs/a_blog) blocked - conflict: /blogs/:blog_id +} + +var matchTests = []struct { + path string + matches []string +}{ + {`/blogs`, []string{`/blogs`}}, + {`/blogs/`, []string{`/blogs/`}}, + {`/blogs/:blog_id`, []string{`/blogs/123`}}, + {`/blogs/:blog_id/comments`, []string{`/blogs/123/comments`}}, + {`/blogs/:blog_id/comments/`, []string{`/blogs/123/comments/`}}, + {`/blogs/:blog_id/comments/:comment_id`, []string{`/blogs/123/comments/456`}}, + {`/blogs/:blog_id/comments/:comment_id/*suffix`, + []string{`/blogs/123/comments/456/test`, `/blogs/123/comments/456/test/test`}}, +} + +func TestMatchPath(t *testing.T) { + testDB(t, func(db *bolt.DB) { + bucketName := []byte("testBucket") + + // Setup - Put all paths + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket(bucketName) + if err != nil { + return err + } + for _, test := range matchTests { + err := b.Put([]byte(test.path), []byte{}) + if err != nil { + return err + } + } + return nil + }); err != nil { + t.Fatal("failed to insert paths:", err) + } + + // Test - Match each + if err := db.View(func(tx *bolt.Tx) error { + b := tx.Bucket(bucketName) + for _, test := range matchTests { + for _, match := range test.matches { + k, _ := SeekPathMatch(b.Cursor(), []byte(match)) + if k == nil { + t.Errorf("expected %q to match %q but got none", match, test.path) + } else if !bytes.Equal(k, []byte(test.path)) { + t.Errorf("expected %q to match %q but got %q", match, test.path, string(k)) + } + } + } + return nil + }); err != nil { + t.Fatal("tests failed:", err) + } + }) +} + +func TestConflicts(t *testing.T) { + for _, test := range []struct { + path string + conflicts []string + }{ + {`/test/test`, []string{`/test/test`, `/:test`, `/*test`, `/test/:test`, `/test/*test`, `/:test/test`}}, + {`/:test`, []string{`/:tst`, `/test`, `/*test`}}, + {`/test/*test`, []string{`/test/*tst`, `/test/test`, `/test/:tst`, `/test/test/test`, `/test/test/:test`, `/test/test/*test`}}, + } { + testDB(t, func(db *bolt.DB) { + // Setup - Put path + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket(bucketName) + if err != nil { + return err + } + return b.Put([]byte(test.path), []byte{}) + }); err != nil { + t.Fatal("failed to insert path", err) + } + + // Test - Verify all conflicts + if err := db.View(func(tx *bolt.Tx) error { + b := tx.Bucket(bucketName) + for _, c := range test.conflicts { + k, _ := SeekPathConflict(b.Cursor(), []byte(c)) + kStr := string(k) + if kStr != test.path { + t.Errorf("expected %q to match %q but got %q", c, test.path, kStr) + } + } + return nil + }); err != nil { + t.Fatal("failed to run tests", err) + } + }) + } +} + +// Attempts to put all matchTests w/o conflict. +func TestNoConflicts(t *testing.T) { + testDB(t, func(db *bolt.DB) { + bucketName := []byte("testBucket") + + if err := db.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucket(bucketName) + if err != nil { + return err + } + c := b.Cursor() + for _, test := range matchTests { + pathB := []byte(test.path) + if k, _ := SeekPathConflict(c, pathB); k != nil { + t.Errorf("unexpected conflict with %q: %s", test.path, string(k)) + } + + if err := b.Put(pathB, []byte{}); err != nil { + return err + } + } + return nil + }); err != nil { + t.Fatal("failed to insert paths:", err) + } + }) +} + +func Benchmark(b *testing.B) { + b.Run("standard", forEachDB("standard", strings.NewReplacer(":", "", "*", "").Replace)) + b.Run("branchFactor", forEachDB("branchFactor", nil)) + b.Run("segmentCount", forEachDB("segmentCount", nil)) + b.Run("segmentSize", forEachDB("segmentSize", nil)) +} + +func forEachDB(testname string, fn func(path string) string) func(*testing.B) { + return func(b *testing.B) { + dir := filepath.Join("testdata", testname) + err := filepath.Walk(dir, func(testfile string, info os.FileInfo, err error) error { + if !info.IsDir() && filepath.Ext(testfile) == ".db" { + arg := strings.TrimSuffix(filepath.Base(testfile), ".db") + + b.Run(arg, benchMatch(testfile, fn)) + } + return nil + }) + if err != nil { + b.Fatal(err) + } + } +} + +func benchMatch(testdb string, pathFn func(path string) string) func(b *testing.B) { + return func(b *testing.B) { + db, err := bolt.Open(testdb, 0666, nil) + if err != nil { + b.Fatalf("failed to open database %s: %s", testdb, err) + } + defer db.Close() + + testtxt := strings.TrimSuffix(testdb, ".db") + ".txt" + f, err := os.Open(testtxt) + if err != nil { + b.Fatalf("failed to open file %s: %s", testtxt, err) + } + + var paths [][]byte + func() { + defer f.Close() + + // Use default, ScanLines + s := bufio.NewScanner(f) + + paths = make([][]byte, 0, b.N) + for s.Scan() { + if pathFn == nil { + paths = append(paths, s.Bytes()) + } else { + paths = append(paths, []byte(pathFn(s.Text()))) + } + + if len(paths) == cap(paths) { + break + } + } + if s.Err() != nil { + b.Fatal("failed to read text paths:", s.Err()) + } + }() + + b.ResetTimer() + + lookup := func(path []byte) error { + return db.View(func(tx *bolt.Tx) error { + bk := tx.Bucket([]byte("paths")) + k, _ := SeekPathMatch(bk.Cursor(), path) + if k == nil { + return errors.New("no match found") + } + return nil + }) + } + + for i := 0; i < b.N; i++ { + path := paths[i%len(paths)] + + if err := lookup(path); err != nil { + b.Fatalf("failed to match %q: %s", string(path), err) + } + } + } +} + +func testDB(t *testing.T, f func(db *bolt.DB)) { + tmp := tempfile() + defer os.Remove(tmp) + db, err := bolt.Open(tmp, 0666, nil) + if err != nil { + t.Fatal("failed to open db:", err) + } + defer db.Close() + f(db) +} + +func tempfile() string { + f, err := ioutil.TempFile("", "nuts-bolt-") + if err != nil { + panic(err) + } + if err := f.Close(); err != nil { + panic(err) + } + if err := os.Remove(f.Name()); err != nil { + panic(err) + } + return f.Name() +} diff --git a/vendor/github.com/jmank88/nuts/types.go b/vendor/github.com/jmank88/nuts/types.go new file mode 100644 index 00000000..16e5e044 --- /dev/null +++ b/vendor/github.com/jmank88/nuts/types.go @@ -0,0 +1,16 @@ +package nuts + +import "github.com/boltdb/bolt" + +var _ Buckets = &bolt.Bucket{} +var _ Buckets = &bolt.Tx{} + +// Buckets is a collection of methods for managing bolt.Buckets which is satisfied +// by *bolt.Tx and *bolt.Bucket. +type Buckets interface { + Bucket([]byte) *bolt.Bucket + CreateBucket([]byte) (*bolt.Bucket, error) + CreateBucketIfNotExists([]byte) (*bolt.Bucket, error) + DeleteBucket([]byte) error + Cursor() *bolt.Cursor +} diff --git a/vendor/github.com/nightlyone/lockfile/.gitignore b/vendor/github.com/nightlyone/lockfile/.gitignore new file mode 100644 index 00000000..5a05665d --- /dev/null +++ b/vendor/github.com/nightlyone/lockfile/.gitignore @@ -0,0 +1,27 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# popular temporaries +.err +.out +.diff + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe diff --git a/vendor/github.com/nightlyone/lockfile/.gitmodules b/vendor/github.com/nightlyone/lockfile/.gitmodules new file mode 100644 index 00000000..6faa9e34 --- /dev/null +++ b/vendor/github.com/nightlyone/lockfile/.gitmodules @@ -0,0 +1,3 @@ +[submodule "git-hooks"] + path = git-hooks + url = https://github.com/nightlyone/git-hooks diff --git a/vendor/github.com/nightlyone/lockfile/.travis.yml b/vendor/github.com/nightlyone/lockfile/.travis.yml new file mode 100644 index 00000000..76e5962b --- /dev/null +++ b/vendor/github.com/nightlyone/lockfile/.travis.yml @@ -0,0 +1,14 @@ +language: go +go: + - 1.4.3 + - 1.6.2 + - tip + +# Only test commits to production branch and all pull requests +branches: + only: + - master + +matrix: + allow_failures: + - go: tip diff --git a/vendor/github.com/nightlyone/lockfile/LICENSE b/vendor/github.com/nightlyone/lockfile/LICENSE new file mode 100644 index 00000000..eb5b8046 --- /dev/null +++ b/vendor/github.com/nightlyone/lockfile/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2012 Ingo Oeser + +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/nightlyone/lockfile/README.md b/vendor/github.com/nightlyone/lockfile/README.md new file mode 100644 index 00000000..c35235cd --- /dev/null +++ b/vendor/github.com/nightlyone/lockfile/README.md @@ -0,0 +1,52 @@ +lockfile +========= +Handle locking via pid files. + +[![Build Status Unix][1]][2] +[![Build status Windows][3]][4] + +[1]: https://secure.travis-ci.org/nightlyone/lockfile.png +[2]: https://travis-ci.org/nightlyone/lockfile +[3]: https://ci.appveyor.com/api/projects/status/7mojkmauj81uvp8u/branch/master?svg=true +[4]: https://ci.appveyor.com/project/nightlyone/lockfile/branch/master + + + +install +------- +Install [Go 1][5], either [from source][6] or [with a prepackaged binary][7]. +For Windows suport, Go 1.4 or newer is required. + +Then run + + go get github.com/nightlyone/lockfile + +[5]: http://golang.org +[6]: http://golang.org/doc/install/source +[7]: http://golang.org/doc/install + +LICENSE +------- +MIT + +documentation +------------- +[package documentation at godoc.org](http://godoc.org/github.com/nightlyone/lockfile) + +install +------------------- + go get github.com/nightlyone/lockfile + + +contributing +============ + +Contributions are welcome. Please open an issue or send me a pull request for a dedicated branch. +Make sure the git commit hooks show it works. + +git commit hooks +----------------------- +enable commit hooks via + + cd .git ; rm -rf hooks; ln -s ../git-hooks hooks ; cd .. + diff --git a/vendor/github.com/nightlyone/lockfile/appveyor.yml b/vendor/github.com/nightlyone/lockfile/appveyor.yml new file mode 100644 index 00000000..cf72a58b --- /dev/null +++ b/vendor/github.com/nightlyone/lockfile/appveyor.yml @@ -0,0 +1,12 @@ +clone_folder: c:\gopath\src\github.com\nightlyone\lockfile + +environment: + GOPATH: c:\gopath + +install: + - go version + - go env + - go get -v -t ./... + +build_script: + - go test -v ./... diff --git a/vendor/github.com/nightlyone/lockfile/lockfile.go b/vendor/github.com/nightlyone/lockfile/lockfile.go new file mode 100644 index 00000000..af2d84a5 --- /dev/null +++ b/vendor/github.com/nightlyone/lockfile/lockfile.go @@ -0,0 +1,211 @@ +// Package lockfile handles pid file based locking. +// While a sync.Mutex helps against concurrency issues within a single process, +// this package is designed to help against concurrency issues between cooperating processes +// or serializing multiple invocations of the same process. You can also combine sync.Mutex +// with Lockfile in order to serialize an action between different goroutines in a single program +// and also multiple invocations of this program. +package lockfile + +import ( + "errors" + "fmt" + "io" + "io/ioutil" + "os" + "path/filepath" +) + +// Lockfile is a pid file which can be locked +type Lockfile string + +// TemporaryError is a type of error where a retry after a random amount of sleep should help to mitigate it. +type TemporaryError string + +func (t TemporaryError) Error() string { return string(t) } + +// Temporary returns always true. +// It exists, so you can detect it via +// if te, ok := err.(interface{ Temporary() bool }); ok { +// fmt.Println("I am a temporay error situation, so wait and retry") +// } +func (t TemporaryError) Temporary() bool { return true } + +// Various errors returned by this package +var ( + ErrBusy = TemporaryError("Locked by other process") // If you get this, retry after a short sleep might help + ErrNotExist = TemporaryError("Lockfile created, but doesn't exist") // If you get this, retry after a short sleep might help + ErrNeedAbsPath = errors.New("Lockfiles must be given as absolute path names") + ErrInvalidPid = errors.New("Lockfile contains invalid pid for system") + ErrDeadOwner = errors.New("Lockfile contains pid of process not existent on this system anymore") + ErrRogueDeletion = errors.New("Lockfile owned by me has been removed unexpectedly") +) + +// New describes a new filename located at the given absolute path. +func New(path string) (Lockfile, error) { + if !filepath.IsAbs(path) { + return Lockfile(""), ErrNeedAbsPath + } + return Lockfile(path), nil +} + +// GetOwner returns who owns the lockfile. +func (l Lockfile) GetOwner() (*os.Process, error) { + name := string(l) + + // Ok, see, if we have a stale lockfile here + content, err := ioutil.ReadFile(name) + if err != nil { + return nil, err + } + + // try hard for pids. If no pid, the lockfile is junk anyway and we delete it. + pid, err := scanPidLine(content) + if err != nil { + return nil, err + } + running, err := isRunning(pid) + if err != nil { + return nil, err + } + + if running { + proc, err := os.FindProcess(pid) + if err != nil { + return nil, err + } + return proc, nil + } + return nil, ErrDeadOwner + +} + +// TryLock tries to own the lock. +// It Returns nil, if successful and and error describing the reason, it didn't work out. +// Please note, that existing lockfiles containing pids of dead processes +// and lockfiles containing no pid at all are simply deleted. +func (l Lockfile) TryLock() error { + name := string(l) + + // This has been checked by New already. If we trigger here, + // the caller didn't use New and re-implemented it's functionality badly. + // So panic, that he might find this easily during testing. + if !filepath.IsAbs(name) { + panic(ErrNeedAbsPath) + } + + tmplock, err := ioutil.TempFile(filepath.Dir(name), filepath.Base(name)+".") + if err != nil { + return err + } + + cleanup := func() { + _ = tmplock.Close() + _ = os.Remove(tmplock.Name()) + } + defer cleanup() + + if err := writePidLine(tmplock, os.Getpid()); err != nil { + return err + } + + // EEXIST and similiar error codes, caught by os.IsExist, are intentionally ignored, + // as it means that someone was faster creating this link + // and ignoring this kind of error is part of the algorithm. + // The we will probably fail the pid owner check later, if this process is still alive. + // We cannot ignore ALL errors, since failure to support hard links, disk full + // as well as many other errors can happen to a filesystem operation + // and we really want to abort on those. + if err := os.Link(tmplock.Name(), name); err != nil { + if !os.IsExist(err) { + return err + } + } + + fiTmp, err := os.Lstat(tmplock.Name()) + if err != nil { + return err + } + fiLock, err := os.Lstat(name) + if err != nil { + // tell user that a retry would be a good idea + if os.IsNotExist(err) { + return ErrNotExist + } + return err + } + + // Success + if os.SameFile(fiTmp, fiLock) { + return nil + } + + proc, err := l.GetOwner() + switch err { + default: + // Other errors -> defensively fail and let caller handle this + return err + case nil: + if proc.Pid != os.Getpid() { + return ErrBusy + } + case ErrDeadOwner, ErrInvalidPid: + // cases we can fix below + } + + // clean stale/invalid lockfile + err = os.Remove(name) + if err != nil { + // If it doesn't exist, then it doesn't matter who removed it. + if !os.IsNotExist(err) { + return err + } + } + + // now that the stale lockfile is gone, let's recurse + return l.TryLock() +} + +// Unlock a lock again, if we owned it. Returns any error that happend during release of lock. +func (l Lockfile) Unlock() error { + proc, err := l.GetOwner() + switch err { + case ErrInvalidPid, ErrDeadOwner: + return ErrRogueDeletion + case nil: + if proc.Pid == os.Getpid() { + // we really own it, so let's remove it. + return os.Remove(string(l)) + } + // Not owned by me, so don't delete it. + return ErrRogueDeletion + default: + // This is an application error or system error. + // So give a better error for logging here. + if os.IsNotExist(err) { + return ErrRogueDeletion + } + // Other errors -> defensively fail and let caller handle this + return err + } +} + +func writePidLine(w io.Writer, pid int) error { + _, err := io.WriteString(w, fmt.Sprintf("%d\n", pid)) + return err +} + +func scanPidLine(content []byte) (int, error) { + if len(content) == 0 { + return 0, ErrInvalidPid + } + + var pid int + if _, err := fmt.Sscanln(string(content), &pid); err != nil { + return 0, ErrInvalidPid + } + + if pid <= 0 { + return 0, ErrInvalidPid + } + return pid, nil +} diff --git a/vendor/github.com/nightlyone/lockfile/lockfile_test.go b/vendor/github.com/nightlyone/lockfile/lockfile_test.go new file mode 100644 index 00000000..be2c821e --- /dev/null +++ b/vendor/github.com/nightlyone/lockfile/lockfile_test.go @@ -0,0 +1,308 @@ +package lockfile + +import ( + "fmt" + "io/ioutil" + "math/rand" + "os" + "path/filepath" + "strconv" + "testing" +) + +func ExampleLockfile() { + lock, err := New(filepath.Join(os.TempDir(), "lock.me.now.lck")) + if err != nil { + fmt.Printf("Cannot init lock. reason: %v", err) + panic(err) // handle properly please! + } + err = lock.TryLock() + + // Error handling is essential, as we only try to get the lock. + if err != nil { + fmt.Printf("Cannot lock %q, reason: %v", lock, err) + panic(err) // handle properly please! + } + + defer lock.Unlock() + + fmt.Println("Do stuff under lock") + // Output: Do stuff under lock +} + +func TestBasicLockUnlock(t *testing.T) { + path, err := filepath.Abs("test_lockfile.pid") + if err != nil { + panic(err) + } + + lf, err := New(path) + if err != nil { + t.Fail() + fmt.Println("Error making lockfile: ", err) + return + } + + err = lf.TryLock() + if err != nil { + t.Fail() + fmt.Println("Error locking lockfile: ", err) + return + } + + err = lf.Unlock() + if err != nil { + t.Fail() + fmt.Println("Error unlocking lockfile: ", err) + return + } +} + +func GetDeadPID() int { + // I have no idea how windows handles large PIDs, or if they even exist. + // So limit it to be less or equal to 4096 to be safe. + + const maxPid = 4095 + + // limited iteration, so we finish one day + seen := map[int]bool{} + for len(seen) < maxPid { + pid := rand.Intn(maxPid + 1) // see https://godoc.org/math/rand#Intn why + if seen[pid] { + continue + } + seen[pid] = true + running, err := isRunning(pid) + if err != nil { + fmt.Println("Error checking PID: ", err) + continue + } + + if !running { + return pid + } + } + panic(fmt.Sprintf("all pids lower %d are used, cannot test this", maxPid)) +} + +func TestBusy(t *testing.T) { + path, err := filepath.Abs("test_lockfile.pid") + if err != nil { + t.Fatal(err) + return + } + + pid := os.Getppid() + + if err := ioutil.WriteFile(path, []byte(strconv.Itoa(pid)+"\n"), 0666); err != nil { + t.Fatal(err) + return + } + defer os.Remove(path) + + lf, err := New(path) + if err != nil { + t.Fatal(err) + return + } + + got := lf.TryLock() + if got != ErrBusy { + t.Fatalf("expected error %q, got %v", ErrBusy, got) + return + } +} + +func TestRogueDeletion(t *testing.T) { + path, err := filepath.Abs("test_lockfile.pid") + if err != nil { + t.Fatal(err) + return + } + lf, err := New(path) + if err != nil { + t.Fatal(err) + return + } + err = lf.TryLock() + if err != nil { + t.Fatal(err) + return + } + err = os.Remove(path) + if err != nil { + t.Fatal(err) + return + } + + got := lf.Unlock() + if got != ErrRogueDeletion { + t.Fatalf("unexpected error: %v", got) + return + } +} + +func TestRogueDeletionDeadPid(t *testing.T) { + path, err := filepath.Abs("test_lockfile.pid") + if err != nil { + t.Fatal(err) + return + } + lf, err := New(path) + if err != nil { + t.Fatal(err) + return + } + err = lf.TryLock() + if err != nil { + t.Fatal(err) + return + } + + pid := GetDeadPID() + if err := ioutil.WriteFile(path, []byte(strconv.Itoa(pid)+"\n"), 0666); err != nil { + t.Fatal(err) + return + } + defer os.Remove(path) + + err = lf.Unlock() + if err != ErrRogueDeletion { + t.Fatalf("unexpected error: %v", err) + return + } + + if _, err := os.Stat(path); os.IsNotExist(err) { + t.Fatal("lockfile should not be deleted by us, if we didn't create it") + } else { + if err != nil { + t.Fatalf("unexpected error %v", err) + } + } +} + +func TestRemovesStaleLockOnDeadOwner(t *testing.T) { + path, err := filepath.Abs("test_lockfile.pid") + if err != nil { + t.Fatal(err) + return + } + lf, err := New(path) + if err != nil { + t.Fatal(err) + return + } + pid := GetDeadPID() + if err := ioutil.WriteFile(path, []byte(strconv.Itoa(pid)+"\n"), 0666); err != nil { + t.Fatal(err) + return + } + err = lf.TryLock() + if err != nil { + t.Fatal(err) + return + } + + if err := lf.Unlock(); err != nil { + t.Fatal(err) + return + } +} + +func TestInvalidPidLeadToReplacedLockfileAndSuccess(t *testing.T) { + path, err := filepath.Abs("test_lockfile.pid") + if err != nil { + t.Fatal(err) + return + } + if err := ioutil.WriteFile(path, []byte("\n"), 0666); err != nil { + t.Fatal(err) + return + } + defer os.Remove(path) + + lf, err := New(path) + if err != nil { + t.Fatal(err) + return + } + + if err := lf.TryLock(); err != nil { + t.Fatalf("unexpected error: %v", err) + return + } + + // now check if file exists and contains the correct content + got, err := ioutil.ReadFile(path) + if err != nil { + t.Fatalf("unexpected error %v", err) + return + } + want := fmt.Sprintf("%d\n", os.Getpid()) + if string(got) != want { + t.Fatalf("got %q, want %q", got, want) + } +} + +func TestScanPidLine(t *testing.T) { + tests := [...]struct { + input []byte + pid int + xfail error + }{ + { + xfail: ErrInvalidPid, + }, + { + input: []byte(""), + xfail: ErrInvalidPid, + }, + { + input: []byte("\n"), + xfail: ErrInvalidPid, + }, + { + input: []byte("-1\n"), + xfail: ErrInvalidPid, + }, + { + input: []byte("0\n"), + xfail: ErrInvalidPid, + }, + { + input: []byte("a\n"), + xfail: ErrInvalidPid, + }, + { + input: []byte("1\n"), + pid: 1, + }, + } + + // test positive cases first + for step, tc := range tests { + if tc.xfail != nil { + continue + } + want := tc.pid + got, err := scanPidLine(tc.input) + if err != nil { + t.Fatalf("%d: unexpected error %v", step, err) + } + if got != want { + t.Errorf("%d: expected pid %d, got %d", step, want, got) + } + } + + // test negative cases now + for step, tc := range tests { + if tc.xfail == nil { + continue + } + want := tc.xfail + _, got := scanPidLine(tc.input) + if got != want { + t.Errorf("%d: expected error %v, got %v", step, want, got) + } + } +} diff --git a/vendor/github.com/nightlyone/lockfile/lockfile_unix.go b/vendor/github.com/nightlyone/lockfile/lockfile_unix.go new file mode 100644 index 00000000..742b041f --- /dev/null +++ b/vendor/github.com/nightlyone/lockfile/lockfile_unix.go @@ -0,0 +1,20 @@ +// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris + +package lockfile + +import ( + "os" + "syscall" +) + +func isRunning(pid int) (bool, error) { + proc, err := os.FindProcess(pid) + if err != nil { + return false, err + } + + if err := proc.Signal(syscall.Signal(0)); err != nil { + return false, nil + } + return true, nil +} diff --git a/vendor/github.com/nightlyone/lockfile/lockfile_windows.go b/vendor/github.com/nightlyone/lockfile/lockfile_windows.go new file mode 100644 index 00000000..482bd91d --- /dev/null +++ b/vendor/github.com/nightlyone/lockfile/lockfile_windows.go @@ -0,0 +1,30 @@ +package lockfile + +import ( + "syscall" +) + +//For some reason these consts don't exist in syscall. +const ( + error_invalid_parameter = 87 + code_still_active = 259 +) + +func isRunning(pid int) (bool, error) { + procHnd, err := syscall.OpenProcess(syscall.PROCESS_QUERY_INFORMATION, true, uint32(pid)) + if err != nil { + if scerr, ok := err.(syscall.Errno); ok { + if uintptr(scerr) == error_invalid_parameter { + return false, nil + } + } + } + + var code uint32 + err = syscall.GetExitCodeProcess(procHnd, &code) + if err != nil { + return false, err + } + + return code == code_still_active, nil +} diff --git a/vendor/github.com/pelletier/go-toml/.gitignore b/vendor/github.com/pelletier/go-toml/.gitignore new file mode 100644 index 00000000..99e38bbc --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/.gitignore @@ -0,0 +1,2 @@ +test_program/test_program_bin +fuzz/ diff --git a/vendor/github.com/pelletier/go-toml/.travis.yml b/vendor/github.com/pelletier/go-toml/.travis.yml new file mode 100644 index 00000000..ab2775d7 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/.travis.yml @@ -0,0 +1,22 @@ +sudo: false +language: go +go: + - 1.8.5 + - 1.9.2 + - tip +matrix: + allow_failures: + - go: tip + fast_finish: true +script: + - if [ -n "$(go fmt ./...)" ]; then exit 1; fi + - ./test.sh + - ./benchmark.sh $TRAVIS_BRANCH https://github.com/$TRAVIS_REPO_SLUG.git +before_install: + - go get github.com/axw/gocov/gocov + - go get github.com/mattn/goveralls + - if ! go get code.google.com/p/go.tools/cmd/cover; then go get golang.org/x/tools/cmd/cover; fi +branches: + only: [master] +after_success: + - $HOME/gopath/bin/goveralls -service=travis-ci -coverprofile=coverage.out -repotoken $COVERALLS_TOKEN diff --git a/vendor/github.com/pelletier/go-toml/LICENSE b/vendor/github.com/pelletier/go-toml/LICENSE new file mode 100644 index 00000000..583bdae6 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2013 - 2017 Thomas Pelletier, Eric Anderton + +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/pelletier/go-toml/README.md b/vendor/github.com/pelletier/go-toml/README.md new file mode 100644 index 00000000..0d357acf --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/README.md @@ -0,0 +1,131 @@ +# go-toml + +Go library for the [TOML](https://github.com/mojombo/toml) format. + +This library supports TOML version +[v0.4.0](https://github.com/toml-lang/toml/blob/master/versions/en/toml-v0.4.0.md) + +[![GoDoc](https://godoc.org/github.com/pelletier/go-toml?status.svg)](http://godoc.org/github.com/pelletier/go-toml) +[![license](https://img.shields.io/github/license/pelletier/go-toml.svg)](https://github.com/pelletier/go-toml/blob/master/LICENSE) +[![Build Status](https://travis-ci.org/pelletier/go-toml.svg?branch=master)](https://travis-ci.org/pelletier/go-toml) +[![Coverage Status](https://coveralls.io/repos/github/pelletier/go-toml/badge.svg?branch=master)](https://coveralls.io/github/pelletier/go-toml?branch=master) +[![Go Report Card](https://goreportcard.com/badge/github.com/pelletier/go-toml)](https://goreportcard.com/report/github.com/pelletier/go-toml) + +## Features + +Go-toml provides the following features for using data parsed from TOML documents: + +* Load TOML documents from files and string data +* Easily navigate TOML structure using Tree +* Mashaling and unmarshaling to and from data structures +* Line & column position data for all parsed elements +* [Query support similar to JSON-Path](query/) +* Syntax errors contain line and column numbers + +## Import + +```go +import "github.com/pelletier/go-toml" +``` + +## Usage example + +Read a TOML document: + +```go +config, _ := toml.Load(` +[postgres] +user = "pelletier" +password = "mypassword"`) +// retrieve data directly +user := config.Get("postgres.user").(string) + +// or using an intermediate object +postgresConfig := config.Get("postgres").(*toml.Tree) +password := postgresConfig.Get("password").(string) +``` + +Or use Unmarshal: + +```go +type Postgres struct { + User string + Password string +} +type Config struct { + Postgres Postgres +} + +doc := []byte(` +[Postgres] +User = "pelletier" +Password = "mypassword"`) + +config := Config{} +toml.Unmarshal(doc, &config) +fmt.Println("user=", config.Postgres.User) +``` + +Or use a query: + +```go +// use a query to gather elements without walking the tree +q, _ := query.Compile("$..[user,password]") +results := q.Execute(config) +for ii, item := range results.Values() { + fmt.Println("Query result %d: %v", ii, item) +} +``` + +## Documentation + +The documentation and additional examples are available at +[godoc.org](http://godoc.org/github.com/pelletier/go-toml). + +## Tools + +Go-toml provides two handy command line tools: + +* `tomll`: Reads TOML files and lint them. + + ``` + go install github.com/pelletier/go-toml/cmd/tomll + tomll --help + ``` +* `tomljson`: Reads a TOML file and outputs its JSON representation. + + ``` + go install github.com/pelletier/go-toml/cmd/tomljson + tomljson --help + ``` + +## Contribute + +Feel free to report bugs and patches using GitHub's pull requests system on +[pelletier/go-toml](https://github.com/pelletier/go-toml). Any feedback would be +much appreciated! + +### Run tests + +You have to make sure two kind of tests run: + +1. The Go unit tests +2. The TOML examples base + +You can run both of them using `./test.sh`. + +### Fuzzing + +The script `./fuzz.sh` is available to +run [go-fuzz](https://github.com/dvyukov/go-fuzz) on go-toml. + +## Versioning + +Go-toml follows [Semantic Versioning](http://semver.org/). The supported version +of [TOML](https://github.com/toml-lang/toml) is indicated at the beginning of +this document. The last two major versions of Go are supported +(see [Go Release Policy](https://golang.org/doc/devel/release.html#policy)). + +## License + +The MIT License (MIT). Read [LICENSE](LICENSE). diff --git a/vendor/github.com/pelletier/go-toml/benchmark.json b/vendor/github.com/pelletier/go-toml/benchmark.json new file mode 100644 index 00000000..86f99c6a --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/benchmark.json @@ -0,0 +1,164 @@ +{ + "array": { + "key1": [ + 1, + 2, + 3 + ], + "key2": [ + "red", + "yellow", + "green" + ], + "key3": [ + [ + 1, + 2 + ], + [ + 3, + 4, + 5 + ] + ], + "key4": [ + [ + 1, + 2 + ], + [ + "a", + "b", + "c" + ] + ], + "key5": [ + 1, + 2, + 3 + ], + "key6": [ + 1, + 2 + ] + }, + "boolean": { + "False": false, + "True": true + }, + "datetime": { + "key1": "1979-05-27T07:32:00Z", + "key2": "1979-05-27T00:32:00-07:00", + "key3": "1979-05-27T00:32:00.999999-07:00" + }, + "float": { + "both": { + "key": 6.626e-34 + }, + "exponent": { + "key1": 5e+22, + "key2": 1000000, + "key3": -0.02 + }, + "fractional": { + "key1": 1, + "key2": 3.1415, + "key3": -0.01 + }, + "underscores": { + "key1": 9224617.445991227, + "key2": 1e+100 + } + }, + "fruit": [{ + "name": "apple", + "physical": { + "color": "red", + "shape": "round" + }, + "variety": [{ + "name": "red delicious" + }, + { + "name": "granny smith" + } + ] + }, + { + "name": "banana", + "variety": [{ + "name": "plantain" + }] + } + ], + "integer": { + "key1": 99, + "key2": 42, + "key3": 0, + "key4": -17, + "underscores": { + "key1": 1000, + "key2": 5349221, + "key3": 12345 + } + }, + "products": [{ + "name": "Hammer", + "sku": 738594937 + }, + {}, + { + "color": "gray", + "name": "Nail", + "sku": 284758393 + } + ], + "string": { + "basic": { + "basic": "I'm a string. \"You can quote me\". Name\tJosé\nLocation\tSF." + }, + "literal": { + "multiline": { + "lines": "The first newline is\ntrimmed in raw strings.\n All other whitespace\n is preserved.\n", + "regex2": "I [dw]on't need \\d{2} apples" + }, + "quoted": "Tom \"Dubs\" Preston-Werner", + "regex": "\u003c\\i\\c*\\s*\u003e", + "winpath": "C:\\Users\\nodejs\\templates", + "winpath2": "\\\\ServerX\\admin$\\system32\\" + }, + "multiline": { + "continued": { + "key1": "The quick brown fox jumps over the lazy dog.", + "key2": "The quick brown fox jumps over the lazy dog.", + "key3": "The quick brown fox jumps over the lazy dog." + }, + "key1": "One\nTwo", + "key2": "One\nTwo", + "key3": "One\nTwo" + } + }, + "table": { + "inline": { + "name": { + "first": "Tom", + "last": "Preston-Werner" + }, + "point": { + "x": 1, + "y": 2 + } + }, + "key": "value", + "subtable": { + "key": "another value" + } + }, + "x": { + "y": { + "z": { + "w": {} + } + } + } +} diff --git a/vendor/github.com/pelletier/go-toml/benchmark.sh b/vendor/github.com/pelletier/go-toml/benchmark.sh new file mode 100755 index 00000000..8b8bb528 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/benchmark.sh @@ -0,0 +1,32 @@ +#!/bin/bash + +set -e + +reference_ref=${1:-master} +reference_git=${2:-.} + +if ! `hash benchstat 2>/dev/null`; then + echo "Installing benchstat" + go get golang.org/x/perf/cmd/benchstat + go install golang.org/x/perf/cmd/benchstat +fi + +tempdir=`mktemp -d /tmp/go-toml-benchmark-XXXXXX` +ref_tempdir="${tempdir}/ref" +ref_benchmark="${ref_tempdir}/benchmark-`echo -n ${reference_ref}|tr -s '/' '-'`.txt" +local_benchmark="`pwd`/benchmark-local.txt" + +echo "=== ${reference_ref} (${ref_tempdir})" +git clone ${reference_git} ${ref_tempdir} >/dev/null 2>/dev/null +pushd ${ref_tempdir} >/dev/null +git checkout ${reference_ref} >/dev/null 2>/dev/null +go test -bench=. -benchmem | tee ${ref_benchmark} +popd >/dev/null + +echo "" +echo "=== local" +go test -bench=. -benchmem | tee ${local_benchmark} + +echo "" +echo "=== diff" +benchstat -delta-test=none ${ref_benchmark} ${local_benchmark} \ No newline at end of file diff --git a/vendor/github.com/pelletier/go-toml/benchmark.toml b/vendor/github.com/pelletier/go-toml/benchmark.toml new file mode 100644 index 00000000..dfd77e09 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/benchmark.toml @@ -0,0 +1,244 @@ +################################################################################ +## Comment + +# Speak your mind with the hash symbol. They go from the symbol to the end of +# the line. + + +################################################################################ +## Table + +# Tables (also known as hash tables or dictionaries) are collections of +# key/value pairs. They appear in square brackets on a line by themselves. + +[table] + +key = "value" # Yeah, you can do this. + +# Nested tables are denoted by table names with dots in them. Name your tables +# whatever crap you please, just don't use #, ., [ or ]. + +[table.subtable] + +key = "another value" + +# You don't need to specify all the super-tables if you don't want to. TOML +# knows how to do it for you. + +# [x] you +# [x.y] don't +# [x.y.z] need these +[x.y.z.w] # for this to work + + +################################################################################ +## Inline Table + +# Inline tables provide a more compact syntax for expressing tables. They are +# especially useful for grouped data that can otherwise quickly become verbose. +# Inline tables are enclosed in curly braces `{` and `}`. No newlines are +# allowed between the curly braces unless they are valid within a value. + +[table.inline] + +name = { first = "Tom", last = "Preston-Werner" } +point = { x = 1, y = 2 } + + +################################################################################ +## String + +# There are four ways to express strings: basic, multi-line basic, literal, and +# multi-line literal. All strings must contain only valid UTF-8 characters. + +[string.basic] + +basic = "I'm a string. \"You can quote me\". Name\tJos\u00E9\nLocation\tSF." + +[string.multiline] + +# The following strings are byte-for-byte equivalent: +key1 = "One\nTwo" +key2 = """One\nTwo""" +key3 = """ +One +Two""" + +[string.multiline.continued] + +# The following strings are byte-for-byte equivalent: +key1 = "The quick brown fox jumps over the lazy dog." + +key2 = """ +The quick brown \ + + + fox jumps over \ + the lazy dog.""" + +key3 = """\ + The quick brown \ + fox jumps over \ + the lazy dog.\ + """ + +[string.literal] + +# What you see is what you get. +winpath = 'C:\Users\nodejs\templates' +winpath2 = '\\ServerX\admin$\system32\' +quoted = 'Tom "Dubs" Preston-Werner' +regex = '<\i\c*\s*>' + + +[string.literal.multiline] + +regex2 = '''I [dw]on't need \d{2} apples''' +lines = ''' +The first newline is +trimmed in raw strings. + All other whitespace + is preserved. +''' + + +################################################################################ +## Integer + +# Integers are whole numbers. Positive numbers may be prefixed with a plus sign. +# Negative numbers are prefixed with a minus sign. + +[integer] + +key1 = +99 +key2 = 42 +key3 = 0 +key4 = -17 + +[integer.underscores] + +# For large numbers, you may use underscores to enhance readability. Each +# underscore must be surrounded by at least one digit. +key1 = 1_000 +key2 = 5_349_221 +key3 = 1_2_3_4_5 # valid but inadvisable + + +################################################################################ +## Float + +# A float consists of an integer part (which may be prefixed with a plus or +# minus sign) followed by a fractional part and/or an exponent part. + +[float.fractional] + +key1 = +1.0 +key2 = 3.1415 +key3 = -0.01 + +[float.exponent] + +key1 = 5e+22 +key2 = 1e6 +key3 = -2E-2 + +[float.both] + +key = 6.626e-34 + +[float.underscores] + +key1 = 9_224_617.445_991_228_313 +key2 = 1e1_00 + + +################################################################################ +## Boolean + +# Booleans are just the tokens you're used to. Always lowercase. + +[boolean] + +True = true +False = false + + +################################################################################ +## Datetime + +# Datetimes are RFC 3339 dates. + +[datetime] + +key1 = 1979-05-27T07:32:00Z +key2 = 1979-05-27T00:32:00-07:00 +key3 = 1979-05-27T00:32:00.999999-07:00 + + +################################################################################ +## Array + +# Arrays are square brackets with other primitives inside. Whitespace is +# ignored. Elements are separated by commas. Data types may not be mixed. + +[array] + +key1 = [ 1, 2, 3 ] +key2 = [ "red", "yellow", "green" ] +key3 = [ [ 1, 2 ], [3, 4, 5] ] +#key4 = [ [ 1, 2 ], ["a", "b", "c"] ] # this is ok + +# Arrays can also be multiline. So in addition to ignoring whitespace, arrays +# also ignore newlines between the brackets. Terminating commas are ok before +# the closing bracket. + +key5 = [ + 1, 2, 3 +] +key6 = [ + 1, + 2, # this is ok +] + + +################################################################################ +## Array of Tables + +# These can be expressed by using a table name in double brackets. Each table +# with the same double bracketed name will be an element in the array. The +# tables are inserted in the order encountered. + +[[products]] + +name = "Hammer" +sku = 738594937 + +[[products]] + +[[products]] + +name = "Nail" +sku = 284758393 +color = "gray" + + +# You can create nested arrays of tables as well. + +[[fruit]] + name = "apple" + + [fruit.physical] + color = "red" + shape = "round" + + [[fruit.variety]] + name = "red delicious" + + [[fruit.variety]] + name = "granny smith" + +[[fruit]] + name = "banana" + + [[fruit.variety]] + name = "plantain" diff --git a/vendor/github.com/pelletier/go-toml/benchmark.yml b/vendor/github.com/pelletier/go-toml/benchmark.yml new file mode 100644 index 00000000..0bd19f08 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/benchmark.yml @@ -0,0 +1,121 @@ +--- +array: + key1: + - 1 + - 2 + - 3 + key2: + - red + - yellow + - green + key3: + - - 1 + - 2 + - - 3 + - 4 + - 5 + key4: + - - 1 + - 2 + - - a + - b + - c + key5: + - 1 + - 2 + - 3 + key6: + - 1 + - 2 +boolean: + 'False': false + 'True': true +datetime: + key1: '1979-05-27T07:32:00Z' + key2: '1979-05-27T00:32:00-07:00' + key3: '1979-05-27T00:32:00.999999-07:00' +float: + both: + key: 6.626e-34 + exponent: + key1: 5.0e+22 + key2: 1000000 + key3: -0.02 + fractional: + key1: 1 + key2: 3.1415 + key3: -0.01 + underscores: + key1: 9224617.445991227 + key2: 1.0e+100 +fruit: +- name: apple + physical: + color: red + shape: round + variety: + - name: red delicious + - name: granny smith +- name: banana + variety: + - name: plantain +integer: + key1: 99 + key2: 42 + key3: 0 + key4: -17 + underscores: + key1: 1000 + key2: 5349221 + key3: 12345 +products: +- name: Hammer + sku: 738594937 +- {} +- color: gray + name: Nail + sku: 284758393 +string: + basic: + basic: "I'm a string. \"You can quote me\". Name\tJosé\nLocation\tSF." + literal: + multiline: + lines: | + The first newline is + trimmed in raw strings. + All other whitespace + is preserved. + regex2: I [dw]on't need \d{2} apples + quoted: Tom "Dubs" Preston-Werner + regex: "<\\i\\c*\\s*>" + winpath: C:\Users\nodejs\templates + winpath2: "\\\\ServerX\\admin$\\system32\\" + multiline: + continued: + key1: The quick brown fox jumps over the lazy dog. + key2: The quick brown fox jumps over the lazy dog. + key3: The quick brown fox jumps over the lazy dog. + key1: |- + One + Two + key2: |- + One + Two + key3: |- + One + Two +table: + inline: + name: + first: Tom + last: Preston-Werner + point: + x: 1 + y: 2 + key: value + subtable: + key: another value +x: + y: + z: + w: {} diff --git a/vendor/github.com/pelletier/go-toml/benchmark_test.go b/vendor/github.com/pelletier/go-toml/benchmark_test.go new file mode 100644 index 00000000..e1f209df --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/benchmark_test.go @@ -0,0 +1,192 @@ +package toml + +import ( + "bytes" + "encoding/json" + "io/ioutil" + "testing" + "time" + + burntsushi "github.com/BurntSushi/toml" + yaml "gopkg.in/yaml.v2" +) + +type benchmarkDoc struct { + Table struct { + Key string + Subtable struct { + Key string + } + Inline struct { + Name struct { + First string + Last string + } + Point struct { + X int64 + U int64 + } + } + } + String struct { + Basic struct { + Basic string + } + Multiline struct { + Key1 string + Key2 string + Key3 string + Continued struct { + Key1 string + Key2 string + Key3 string + } + } + Literal struct { + Winpath string + Winpath2 string + Quoted string + Regex string + Multiline struct { + Regex2 string + Lines string + } + } + } + Integer struct { + Key1 int64 + Key2 int64 + Key3 int64 + Key4 int64 + Underscores struct { + Key1 int64 + Key2 int64 + Key3 int64 + } + } + Float struct { + Fractional struct { + Key1 float64 + Key2 float64 + Key3 float64 + } + Exponent struct { + Key1 float64 + Key2 float64 + Key3 float64 + } + Both struct { + Key float64 + } + Underscores struct { + Key1 float64 + Key2 float64 + } + } + Boolean struct { + True bool + False bool + } + Datetime struct { + Key1 time.Time + Key2 time.Time + Key3 time.Time + } + Array struct { + Key1 []int64 + Key2 []string + Key3 [][]int64 + // TODO: Key4 not supported by go-toml's Unmarshal + Key5 []int64 + Key6 []int64 + } + Products []struct { + Name string + Sku int64 + Color string + } + Fruit []struct { + Name string + Physical struct { + Color string + Shape string + Variety []struct { + Name string + } + } + } +} + +func BenchmarkParseToml(b *testing.B) { + fileBytes, err := ioutil.ReadFile("benchmark.toml") + if err != nil { + b.Fatal(err) + } + b.ResetTimer() + for i := 0; i < b.N; i++ { + _, err := LoadReader(bytes.NewReader(fileBytes)) + if err != nil { + b.Fatal(err) + } + } +} + +func BenchmarkUnmarshalToml(b *testing.B) { + bytes, err := ioutil.ReadFile("benchmark.toml") + if err != nil { + b.Fatal(err) + } + b.ResetTimer() + for i := 0; i < b.N; i++ { + target := benchmarkDoc{} + err := Unmarshal(bytes, &target) + if err != nil { + b.Fatal(err) + } + } +} + +func BenchmarkUnmarshalBurntSushiToml(b *testing.B) { + bytes, err := ioutil.ReadFile("benchmark.toml") + if err != nil { + b.Fatal(err) + } + b.ResetTimer() + for i := 0; i < b.N; i++ { + target := benchmarkDoc{} + err := burntsushi.Unmarshal(bytes, &target) + if err != nil { + b.Fatal(err) + } + } +} + +func BenchmarkUnmarshalJson(b *testing.B) { + bytes, err := ioutil.ReadFile("benchmark.json") + if err != nil { + b.Fatal(err) + } + b.ResetTimer() + for i := 0; i < b.N; i++ { + target := benchmarkDoc{} + err := json.Unmarshal(bytes, &target) + if err != nil { + b.Fatal(err) + } + } +} + +func BenchmarkUnmarshalYaml(b *testing.B) { + bytes, err := ioutil.ReadFile("benchmark.yml") + if err != nil { + b.Fatal(err) + } + b.ResetTimer() + for i := 0; i < b.N; i++ { + target := benchmarkDoc{} + err := yaml.Unmarshal(bytes, &target) + if err != nil { + b.Fatal(err) + } + } +} diff --git a/vendor/github.com/pelletier/go-toml/cmd/test_program.go b/vendor/github.com/pelletier/go-toml/cmd/test_program.go new file mode 100644 index 00000000..73077f61 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/cmd/test_program.go @@ -0,0 +1,91 @@ +package main + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "log" + "os" + "time" + + "github.com/pelletier/go-toml" +) + +func main() { + bytes, err := ioutil.ReadAll(os.Stdin) + if err != nil { + log.Fatalf("Error during TOML read: %s", err) + os.Exit(2) + } + tree, err := toml.Load(string(bytes)) + if err != nil { + log.Fatalf("Error during TOML load: %s", err) + os.Exit(1) + } + + typedTree := translate(*tree) + + if err := json.NewEncoder(os.Stdout).Encode(typedTree); err != nil { + log.Fatalf("Error encoding JSON: %s", err) + os.Exit(3) + } + + os.Exit(0) +} + +func translate(tomlData interface{}) interface{} { + switch orig := tomlData.(type) { + case map[string]interface{}: + typed := make(map[string]interface{}, len(orig)) + for k, v := range orig { + typed[k] = translate(v) + } + return typed + case *toml.Tree: + return translate(*orig) + case toml.Tree: + keys := orig.Keys() + typed := make(map[string]interface{}, len(keys)) + for _, k := range keys { + typed[k] = translate(orig.GetPath([]string{k})) + } + return typed + case []*toml.Tree: + typed := make([]map[string]interface{}, len(orig)) + for i, v := range orig { + typed[i] = translate(v).(map[string]interface{}) + } + return typed + case []map[string]interface{}: + typed := make([]map[string]interface{}, len(orig)) + for i, v := range orig { + typed[i] = translate(v).(map[string]interface{}) + } + return typed + case []interface{}: + typed := make([]interface{}, len(orig)) + for i, v := range orig { + typed[i] = translate(v) + } + return tag("array", typed) + case time.Time: + return tag("datetime", orig.Format("2006-01-02T15:04:05Z")) + case bool: + return tag("bool", fmt.Sprintf("%v", orig)) + case int64: + return tag("integer", fmt.Sprintf("%d", orig)) + case float64: + return tag("float", fmt.Sprintf("%v", orig)) + case string: + return tag("string", orig) + } + + panic(fmt.Sprintf("Unknown type: %T", tomlData)) +} + +func tag(typeName string, data interface{}) map[string]interface{} { + return map[string]interface{}{ + "type": typeName, + "value": data, + } +} diff --git a/vendor/github.com/pelletier/go-toml/cmd/tomljson/main.go b/vendor/github.com/pelletier/go-toml/cmd/tomljson/main.go new file mode 100644 index 00000000..b2d6fc67 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/cmd/tomljson/main.go @@ -0,0 +1,72 @@ +// Tomljson reads TOML and converts to JSON. +// +// Usage: +// cat file.toml | tomljson > file.json +// tomljson file1.toml > file.json +package main + +import ( + "encoding/json" + "flag" + "fmt" + "io" + "os" + + "github.com/pelletier/go-toml" +) + +func main() { + flag.Usage = func() { + fmt.Fprintln(os.Stderr, `tomljson can be used in two ways: +Writing to STDIN and reading from STDOUT: + cat file.toml | tomljson > file.json + +Reading from a file name: + tomljson file.toml +`) + } + flag.Parse() + os.Exit(processMain(flag.Args(), os.Stdin, os.Stdout, os.Stderr)) +} + +func processMain(files []string, defaultInput io.Reader, output io.Writer, errorOutput io.Writer) int { + // read from stdin and print to stdout + inputReader := defaultInput + + if len(files) > 0 { + var err error + inputReader, err = os.Open(files[0]) + if err != nil { + printError(err, errorOutput) + return -1 + } + } + s, err := reader(inputReader) + if err != nil { + printError(err, errorOutput) + return -1 + } + io.WriteString(output, s+"\n") + return 0 +} + +func printError(err error, output io.Writer) { + io.WriteString(output, err.Error()+"\n") +} + +func reader(r io.Reader) (string, error) { + tree, err := toml.LoadReader(r) + if err != nil { + return "", err + } + return mapToJSON(tree) +} + +func mapToJSON(tree *toml.Tree) (string, error) { + treeMap := tree.ToMap() + bytes, err := json.MarshalIndent(treeMap, "", " ") + if err != nil { + return "", err + } + return string(bytes[:]), nil +} diff --git a/vendor/github.com/pelletier/go-toml/cmd/tomljson/main_test.go b/vendor/github.com/pelletier/go-toml/cmd/tomljson/main_test.go new file mode 100644 index 00000000..0b4bdbb1 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/cmd/tomljson/main_test.go @@ -0,0 +1,82 @@ +package main + +import ( + "bytes" + "io/ioutil" + "os" + "strings" + "testing" +) + +func expectBufferEquality(t *testing.T, name string, buffer *bytes.Buffer, expected string) { + output := buffer.String() + if output != expected { + t.Errorf("incorrect %s:\n%s\n\nexpected %s:\n%s", name, output, name, expected) + t.Log([]rune(output)) + t.Log([]rune(expected)) + } +} + +func expectProcessMainResults(t *testing.T, input string, args []string, exitCode int, expectedOutput string, expectedError string) { + inputReader := strings.NewReader(input) + outputBuffer := new(bytes.Buffer) + errorBuffer := new(bytes.Buffer) + + returnCode := processMain(args, inputReader, outputBuffer, errorBuffer) + + expectBufferEquality(t, "output", outputBuffer, expectedOutput) + expectBufferEquality(t, "error", errorBuffer, expectedError) + + if returnCode != exitCode { + t.Error("incorrect return code:", returnCode, "expected", exitCode) + } +} + +func TestProcessMainReadFromStdin(t *testing.T) { + input := ` + [mytoml] + a = 42` + expectedOutput := `{ + "mytoml": { + "a": 42 + } +} +` + expectedError := `` + expectedExitCode := 0 + + expectProcessMainResults(t, input, []string{}, expectedExitCode, expectedOutput, expectedError) +} + +func TestProcessMainReadFromFile(t *testing.T) { + input := ` + [mytoml] + a = 42` + + tmpfile, err := ioutil.TempFile("", "example.toml") + if err != nil { + t.Fatal(err) + } + if _, err := tmpfile.Write([]byte(input)); err != nil { + t.Fatal(err) + } + + defer os.Remove(tmpfile.Name()) + + expectedOutput := `{ + "mytoml": { + "a": 42 + } +} +` + expectedError := `` + expectedExitCode := 0 + + expectProcessMainResults(t, ``, []string{tmpfile.Name()}, expectedExitCode, expectedOutput, expectedError) +} + +func TestProcessMainReadFromMissingFile(t *testing.T) { + expectedError := `open /this/file/does/not/exist: no such file or directory +` + expectProcessMainResults(t, ``, []string{"/this/file/does/not/exist"}, -1, ``, expectedError) +} diff --git a/vendor/github.com/pelletier/go-toml/cmd/tomll/main.go b/vendor/github.com/pelletier/go-toml/cmd/tomll/main.go new file mode 100644 index 00000000..36c7e375 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/cmd/tomll/main.go @@ -0,0 +1,66 @@ +// Tomll is a linter for TOML +// +// Usage: +// cat file.toml | tomll > file_linted.toml +// tomll file1.toml file2.toml # lint the two files in place +package main + +import ( + "flag" + "fmt" + "io" + "io/ioutil" + "os" + + "github.com/pelletier/go-toml" +) + +func main() { + flag.Usage = func() { + fmt.Fprintln(os.Stderr, `tomll can be used in two ways: +Writing to STDIN and reading from STDOUT: + cat file.toml | tomll > file.toml + +Reading and updating a list of files: + tomll a.toml b.toml c.toml + +When given a list of files, tomll will modify all files in place without asking. +`) + } + flag.Parse() + // read from stdin and print to stdout + if flag.NArg() == 0 { + s, err := lintReader(os.Stdin) + if err != nil { + io.WriteString(os.Stderr, err.Error()) + os.Exit(-1) + } + io.WriteString(os.Stdout, s) + } else { + // otherwise modify a list of files + for _, filename := range flag.Args() { + s, err := lintFile(filename) + if err != nil { + io.WriteString(os.Stderr, err.Error()) + os.Exit(-1) + } + ioutil.WriteFile(filename, []byte(s), 0644) + } + } +} + +func lintFile(filename string) (string, error) { + tree, err := toml.LoadFile(filename) + if err != nil { + return "", err + } + return tree.String(), nil +} + +func lintReader(r io.Reader) (string, error) { + tree, err := toml.LoadReader(r) + if err != nil { + return "", err + } + return tree.String(), nil +} diff --git a/vendor/github.com/pelletier/go-toml/doc.go b/vendor/github.com/pelletier/go-toml/doc.go new file mode 100644 index 00000000..d5fd98c0 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/doc.go @@ -0,0 +1,23 @@ +// Package toml is a TOML parser and manipulation library. +// +// This version supports the specification as described in +// https://github.com/toml-lang/toml/blob/master/versions/en/toml-v0.4.0.md +// +// Marshaling +// +// Go-toml can marshal and unmarshal TOML documents from and to data +// structures. +// +// TOML document as a tree +// +// Go-toml can operate on a TOML document as a tree. Use one of the Load* +// functions to parse TOML data and obtain a Tree instance, then one of its +// methods to manipulate the tree. +// +// JSONPath-like queries +// +// The package github.com/pelletier/go-toml/query implements a system +// similar to JSONPath to quickly retrieve elements of a TOML document using a +// single expression. See the package documentation for more information. +// +package toml diff --git a/vendor/github.com/pelletier/go-toml/doc_test.go b/vendor/github.com/pelletier/go-toml/doc_test.go new file mode 100644 index 00000000..3b8171b2 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/doc_test.go @@ -0,0 +1,105 @@ +// code examples for godoc + +package toml_test + +import ( + "fmt" + "log" + + toml "github.com/pelletier/go-toml" +) + +func Example_tree() { + config, err := toml.LoadFile("config.toml") + + if err != nil { + fmt.Println("Error ", err.Error()) + } else { + // retrieve data directly + user := config.Get("postgres.user").(string) + password := config.Get("postgres.password").(string) + + // or using an intermediate object + configTree := config.Get("postgres").(*toml.Tree) + user = configTree.Get("user").(string) + password = configTree.Get("password").(string) + fmt.Println("User is", user, " and password is", password) + + // show where elements are in the file + fmt.Printf("User position: %v\n", configTree.GetPosition("user")) + fmt.Printf("Password position: %v\n", configTree.GetPosition("password")) + } +} + +func Example_unmarshal() { + type Employer struct { + Name string + Phone string + } + type Person struct { + Name string + Age int64 + Employer Employer + } + + document := []byte(` + name = "John" + age = 30 + [employer] + name = "Company Inc." + phone = "+1 234 567 89012" + `) + + person := Person{} + toml.Unmarshal(document, &person) + fmt.Println(person.Name, "is", person.Age, "and works at", person.Employer.Name) + // Output: + // John is 30 and works at Company Inc. +} + +func ExampleMarshal() { + type Postgres struct { + User string `toml:"user"` + Password string `toml:"password"` + Database string `toml:"db" commented:"true" comment:"not used anymore"` + } + type Config struct { + Postgres Postgres `toml:"postgres" comment:"Postgres configuration"` + } + + config := Config{Postgres{User: "pelletier", Password: "mypassword", Database: "old_database"}} + b, err := toml.Marshal(config) + if err != nil { + log.Fatal(err) + } + fmt.Println(string(b)) + // Output: + // # Postgres configuration + // [postgres] + // + // # not used anymore + // # db = "old_database" + // password = "mypassword" + // user = "pelletier" +} + +func ExampleUnmarshal() { + type Postgres struct { + User string + Password string + } + type Config struct { + Postgres Postgres + } + + doc := []byte(` + [postgres] + user = "pelletier" + password = "mypassword"`) + + config := Config{} + toml.Unmarshal(doc, &config) + fmt.Println("user=", config.Postgres.User) + // Output: + // user= pelletier +} diff --git a/vendor/github.com/pelletier/go-toml/example-crlf.toml b/vendor/github.com/pelletier/go-toml/example-crlf.toml new file mode 100644 index 00000000..12950a16 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/example-crlf.toml @@ -0,0 +1,29 @@ +# This is a TOML document. Boom. + +title = "TOML Example" + +[owner] +name = "Tom Preston-Werner" +organization = "GitHub" +bio = "GitHub Cofounder & CEO\nLikes tater tots and beer." +dob = 1979-05-27T07:32:00Z # First class dates? Why not? + +[database] +server = "192.168.1.1" +ports = [ 8001, 8001, 8002 ] +connection_max = 5000 +enabled = true + +[servers] + + # You can indent as you please. Tabs or spaces. TOML don't care. + [servers.alpha] + ip = "10.0.0.1" + dc = "eqdc10" + + [servers.beta] + ip = "10.0.0.2" + dc = "eqdc10" + +[clients] +data = [ ["gamma", "delta"], [1, 2] ] # just an update to make sure parsers support it diff --git a/vendor/github.com/pelletier/go-toml/example.toml b/vendor/github.com/pelletier/go-toml/example.toml new file mode 100644 index 00000000..3d902f28 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/example.toml @@ -0,0 +1,29 @@ +# This is a TOML document. Boom. + +title = "TOML Example" + +[owner] +name = "Tom Preston-Werner" +organization = "GitHub" +bio = "GitHub Cofounder & CEO\nLikes tater tots and beer." +dob = 1979-05-27T07:32:00Z # First class dates? Why not? + +[database] +server = "192.168.1.1" +ports = [ 8001, 8001, 8002 ] +connection_max = 5000 +enabled = true + +[servers] + + # You can indent as you please. Tabs or spaces. TOML don't care. + [servers.alpha] + ip = "10.0.0.1" + dc = "eqdc10" + + [servers.beta] + ip = "10.0.0.2" + dc = "eqdc10" + +[clients] +data = [ ["gamma", "delta"], [1, 2] ] # just an update to make sure parsers support it diff --git a/vendor/github.com/pelletier/go-toml/fuzz.go b/vendor/github.com/pelletier/go-toml/fuzz.go new file mode 100644 index 00000000..14570c8d --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/fuzz.go @@ -0,0 +1,31 @@ +// +build gofuzz + +package toml + +func Fuzz(data []byte) int { + tree, err := LoadBytes(data) + if err != nil { + if tree != nil { + panic("tree must be nil if there is an error") + } + return 0 + } + + str, err := tree.ToTomlString() + if err != nil { + if str != "" { + panic(`str must be "" if there is an error`) + } + panic(err) + } + + tree, err = Load(str) + if err != nil { + if tree != nil { + panic("tree must be nil if there is an error") + } + return 0 + } + + return 1 +} diff --git a/vendor/github.com/pelletier/go-toml/fuzz.sh b/vendor/github.com/pelletier/go-toml/fuzz.sh new file mode 100755 index 00000000..3204b4c4 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/fuzz.sh @@ -0,0 +1,15 @@ +#! /bin/sh +set -eu + +go get github.com/dvyukov/go-fuzz/go-fuzz +go get github.com/dvyukov/go-fuzz/go-fuzz-build + +if [ ! -e toml-fuzz.zip ]; then + go-fuzz-build github.com/pelletier/go-toml +fi + +rm -fr fuzz +mkdir -p fuzz/corpus +cp *.toml fuzz/corpus + +go-fuzz -bin=toml-fuzz.zip -workdir=fuzz diff --git a/vendor/github.com/pelletier/go-toml/keysparsing.go b/vendor/github.com/pelletier/go-toml/keysparsing.go new file mode 100644 index 00000000..284db646 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/keysparsing.go @@ -0,0 +1,85 @@ +// Parsing keys handling both bare and quoted keys. + +package toml + +import ( + "bytes" + "errors" + "fmt" + "unicode" +) + +// Convert the bare key group string to an array. +// The input supports double quotation to allow "." inside the key name, +// but escape sequences are not supported. Lexers must unescape them beforehand. +func parseKey(key string) ([]string, error) { + groups := []string{} + var buffer bytes.Buffer + inQuotes := false + wasInQuotes := false + ignoreSpace := true + expectDot := false + + for _, char := range key { + if ignoreSpace { + if char == ' ' { + continue + } + ignoreSpace = false + } + switch char { + case '"': + if inQuotes { + groups = append(groups, buffer.String()) + buffer.Reset() + wasInQuotes = true + } + inQuotes = !inQuotes + expectDot = false + case '.': + if inQuotes { + buffer.WriteRune(char) + } else { + if !wasInQuotes { + if buffer.Len() == 0 { + return nil, errors.New("empty table key") + } + groups = append(groups, buffer.String()) + buffer.Reset() + } + ignoreSpace = true + expectDot = false + wasInQuotes = false + } + case ' ': + if inQuotes { + buffer.WriteRune(char) + } else { + expectDot = true + } + default: + if !inQuotes && !isValidBareChar(char) { + return nil, fmt.Errorf("invalid bare character: %c", char) + } + if !inQuotes && expectDot { + return nil, errors.New("what?") + } + buffer.WriteRune(char) + expectDot = false + } + } + if inQuotes { + return nil, errors.New("mismatched quotes") + } + if buffer.Len() > 0 { + groups = append(groups, buffer.String()) + } + if len(groups) == 0 { + return nil, errors.New("empty key") + } + return groups, nil +} + +func isValidBareChar(r rune) bool { + return isAlphanumeric(r) || r == '-' || unicode.IsNumber(r) +} diff --git a/vendor/github.com/pelletier/go-toml/keysparsing_test.go b/vendor/github.com/pelletier/go-toml/keysparsing_test.go new file mode 100644 index 00000000..84cb8260 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/keysparsing_test.go @@ -0,0 +1,63 @@ +package toml + +import ( + "fmt" + "testing" +) + +func testResult(t *testing.T, key string, expected []string) { + parsed, err := parseKey(key) + t.Logf("key=%s expected=%s parsed=%s", key, expected, parsed) + if err != nil { + t.Fatal("Unexpected error:", err) + } + if len(expected) != len(parsed) { + t.Fatal("Expected length", len(expected), "but", len(parsed), "parsed") + } + for index, expectedKey := range expected { + if expectedKey != parsed[index] { + t.Fatal("Expected", expectedKey, "at index", index, "but found", parsed[index]) + } + } +} + +func testError(t *testing.T, key string, expectedError string) { + res, err := parseKey(key) + if err == nil { + t.Fatalf("Expected error, but succesfully parsed key %s", res) + } + if fmt.Sprintf("%s", err) != expectedError { + t.Fatalf("Expected error \"%s\", but got \"%s\".", expectedError, err) + } +} + +func TestBareKeyBasic(t *testing.T) { + testResult(t, "test", []string{"test"}) +} + +func TestBareKeyDotted(t *testing.T) { + testResult(t, "this.is.a.key", []string{"this", "is", "a", "key"}) +} + +func TestDottedKeyBasic(t *testing.T) { + testResult(t, "\"a.dotted.key\"", []string{"a.dotted.key"}) +} + +func TestBaseKeyPound(t *testing.T) { + testError(t, "hello#world", "invalid bare character: #") +} + +func TestQuotedKeys(t *testing.T) { + testResult(t, `hello."foo".bar`, []string{"hello", "foo", "bar"}) + testResult(t, `"hello!"`, []string{"hello!"}) + testResult(t, `foo."ba.r".baz`, []string{"foo", "ba.r", "baz"}) + + // escape sequences must not be converted + testResult(t, `"hello\tworld"`, []string{`hello\tworld`}) +} + +func TestEmptyKey(t *testing.T) { + testError(t, "", "empty key") + testError(t, " ", "empty key") + testResult(t, `""`, []string{""}) +} diff --git a/vendor/github.com/pelletier/go-toml/lexer.go b/vendor/github.com/pelletier/go-toml/lexer.go new file mode 100644 index 00000000..d11de428 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/lexer.go @@ -0,0 +1,750 @@ +// TOML lexer. +// +// Written using the principles developed by Rob Pike in +// http://www.youtube.com/watch?v=HxaD_trXwRE + +package toml + +import ( + "bytes" + "errors" + "fmt" + "regexp" + "strconv" + "strings" +) + +var dateRegexp *regexp.Regexp + +// Define state functions +type tomlLexStateFn func() tomlLexStateFn + +// Define lexer +type tomlLexer struct { + inputIdx int + input []rune // Textual source + currentTokenStart int + currentTokenStop int + tokens []token + depth int + line int + col int + endbufferLine int + endbufferCol int +} + +// Basic read operations on input + +func (l *tomlLexer) read() rune { + r := l.peek() + if r == '\n' { + l.endbufferLine++ + l.endbufferCol = 1 + } else { + l.endbufferCol++ + } + l.inputIdx++ + return r +} + +func (l *tomlLexer) next() rune { + r := l.read() + + if r != eof { + l.currentTokenStop++ + } + return r +} + +func (l *tomlLexer) ignore() { + l.currentTokenStart = l.currentTokenStop + l.line = l.endbufferLine + l.col = l.endbufferCol +} + +func (l *tomlLexer) skip() { + l.next() + l.ignore() +} + +func (l *tomlLexer) fastForward(n int) { + for i := 0; i < n; i++ { + l.next() + } +} + +func (l *tomlLexer) emitWithValue(t tokenType, value string) { + l.tokens = append(l.tokens, token{ + Position: Position{l.line, l.col}, + typ: t, + val: value, + }) + l.ignore() +} + +func (l *tomlLexer) emit(t tokenType) { + l.emitWithValue(t, string(l.input[l.currentTokenStart:l.currentTokenStop])) +} + +func (l *tomlLexer) peek() rune { + if l.inputIdx >= len(l.input) { + return eof + } + return l.input[l.inputIdx] +} + +func (l *tomlLexer) peekString(size int) string { + maxIdx := len(l.input) + upperIdx := l.inputIdx + size // FIXME: potential overflow + if upperIdx > maxIdx { + upperIdx = maxIdx + } + return string(l.input[l.inputIdx:upperIdx]) +} + +func (l *tomlLexer) follow(next string) bool { + return next == l.peekString(len(next)) +} + +// Error management + +func (l *tomlLexer) errorf(format string, args ...interface{}) tomlLexStateFn { + l.tokens = append(l.tokens, token{ + Position: Position{l.line, l.col}, + typ: tokenError, + val: fmt.Sprintf(format, args...), + }) + return nil +} + +// State functions + +func (l *tomlLexer) lexVoid() tomlLexStateFn { + for { + next := l.peek() + switch next { + case '[': + return l.lexTableKey + case '#': + return l.lexComment(l.lexVoid) + case '=': + return l.lexEqual + case '\r': + fallthrough + case '\n': + l.skip() + continue + } + + if isSpace(next) { + l.skip() + } + + if l.depth > 0 { + return l.lexRvalue + } + + if isKeyStartChar(next) { + return l.lexKey + } + + if next == eof { + l.next() + break + } + } + + l.emit(tokenEOF) + return nil +} + +func (l *tomlLexer) lexRvalue() tomlLexStateFn { + for { + next := l.peek() + switch next { + case '.': + return l.errorf("cannot start float with a dot") + case '=': + return l.lexEqual + case '[': + l.depth++ + return l.lexLeftBracket + case ']': + l.depth-- + return l.lexRightBracket + case '{': + return l.lexLeftCurlyBrace + case '}': + return l.lexRightCurlyBrace + case '#': + return l.lexComment(l.lexRvalue) + case '"': + return l.lexString + case '\'': + return l.lexLiteralString + case ',': + return l.lexComma + case '\r': + fallthrough + case '\n': + l.skip() + if l.depth == 0 { + return l.lexVoid + } + return l.lexRvalue + case '_': + return l.errorf("cannot start number with underscore") + } + + if l.follow("true") { + return l.lexTrue + } + + if l.follow("false") { + return l.lexFalse + } + + if l.follow("inf") { + return l.lexInf + } + + if l.follow("nan") { + return l.lexNan + } + + if isSpace(next) { + l.skip() + continue + } + + if next == eof { + l.next() + break + } + + possibleDate := l.peekString(35) + dateMatch := dateRegexp.FindString(possibleDate) + if dateMatch != "" { + l.fastForward(len(dateMatch)) + return l.lexDate + } + + if next == '+' || next == '-' || isDigit(next) { + return l.lexNumber + } + + if isAlphanumeric(next) { + return l.lexKey + } + + return l.errorf("no value can start with %c", next) + } + + l.emit(tokenEOF) + return nil +} + +func (l *tomlLexer) lexLeftCurlyBrace() tomlLexStateFn { + l.next() + l.emit(tokenLeftCurlyBrace) + return l.lexRvalue +} + +func (l *tomlLexer) lexRightCurlyBrace() tomlLexStateFn { + l.next() + l.emit(tokenRightCurlyBrace) + return l.lexRvalue +} + +func (l *tomlLexer) lexDate() tomlLexStateFn { + l.emit(tokenDate) + return l.lexRvalue +} + +func (l *tomlLexer) lexTrue() tomlLexStateFn { + l.fastForward(4) + l.emit(tokenTrue) + return l.lexRvalue +} + +func (l *tomlLexer) lexFalse() tomlLexStateFn { + l.fastForward(5) + l.emit(tokenFalse) + return l.lexRvalue +} + +func (l *tomlLexer) lexInf() tomlLexStateFn { + l.fastForward(3) + l.emit(tokenInf) + return l.lexRvalue +} + +func (l *tomlLexer) lexNan() tomlLexStateFn { + l.fastForward(3) + l.emit(tokenNan) + return l.lexRvalue +} + +func (l *tomlLexer) lexEqual() tomlLexStateFn { + l.next() + l.emit(tokenEqual) + return l.lexRvalue +} + +func (l *tomlLexer) lexComma() tomlLexStateFn { + l.next() + l.emit(tokenComma) + return l.lexRvalue +} + +// Parse the key and emits its value without escape sequences. +// bare keys, basic string keys and literal string keys are supported. +func (l *tomlLexer) lexKey() tomlLexStateFn { + growingString := "" + + for r := l.peek(); isKeyChar(r) || r == '\n' || r == '\r'; r = l.peek() { + if r == '"' { + l.next() + str, err := l.lexStringAsString(`"`, false, true) + if err != nil { + return l.errorf(err.Error()) + } + growingString += str + l.next() + continue + } else if r == '\'' { + l.next() + str, err := l.lexLiteralStringAsString(`'`, false) + if err != nil { + return l.errorf(err.Error()) + } + growingString += str + l.next() + continue + } else if r == '\n' { + return l.errorf("keys cannot contain new lines") + } else if isSpace(r) { + break + } else if !isValidBareChar(r) { + return l.errorf("keys cannot contain %c character", r) + } + growingString += string(r) + l.next() + } + l.emitWithValue(tokenKey, growingString) + return l.lexVoid +} + +func (l *tomlLexer) lexComment(previousState tomlLexStateFn) tomlLexStateFn { + return func() tomlLexStateFn { + for next := l.peek(); next != '\n' && next != eof; next = l.peek() { + if next == '\r' && l.follow("\r\n") { + break + } + l.next() + } + l.ignore() + return previousState + } +} + +func (l *tomlLexer) lexLeftBracket() tomlLexStateFn { + l.next() + l.emit(tokenLeftBracket) + return l.lexRvalue +} + +func (l *tomlLexer) lexLiteralStringAsString(terminator string, discardLeadingNewLine bool) (string, error) { + growingString := "" + + if discardLeadingNewLine { + if l.follow("\r\n") { + l.skip() + l.skip() + } else if l.peek() == '\n' { + l.skip() + } + } + + // find end of string + for { + if l.follow(terminator) { + return growingString, nil + } + + next := l.peek() + if next == eof { + break + } + growingString += string(l.next()) + } + + return "", errors.New("unclosed string") +} + +func (l *tomlLexer) lexLiteralString() tomlLexStateFn { + l.skip() + + // handle special case for triple-quote + terminator := "'" + discardLeadingNewLine := false + if l.follow("''") { + l.skip() + l.skip() + terminator = "'''" + discardLeadingNewLine = true + } + + str, err := l.lexLiteralStringAsString(terminator, discardLeadingNewLine) + if err != nil { + return l.errorf(err.Error()) + } + + l.emitWithValue(tokenString, str) + l.fastForward(len(terminator)) + l.ignore() + return l.lexRvalue +} + +// Lex a string and return the results as a string. +// Terminator is the substring indicating the end of the token. +// The resulting string does not include the terminator. +func (l *tomlLexer) lexStringAsString(terminator string, discardLeadingNewLine, acceptNewLines bool) (string, error) { + growingString := "" + + if discardLeadingNewLine { + if l.follow("\r\n") { + l.skip() + l.skip() + } else if l.peek() == '\n' { + l.skip() + } + } + + for { + if l.follow(terminator) { + return growingString, nil + } + + if l.follow("\\") { + l.next() + switch l.peek() { + case '\r': + fallthrough + case '\n': + fallthrough + case '\t': + fallthrough + case ' ': + // skip all whitespace chars following backslash + for strings.ContainsRune("\r\n\t ", l.peek()) { + l.next() + } + case '"': + growingString += "\"" + l.next() + case 'n': + growingString += "\n" + l.next() + case 'b': + growingString += "\b" + l.next() + case 'f': + growingString += "\f" + l.next() + case '/': + growingString += "/" + l.next() + case 't': + growingString += "\t" + l.next() + case 'r': + growingString += "\r" + l.next() + case '\\': + growingString += "\\" + l.next() + case 'u': + l.next() + code := "" + for i := 0; i < 4; i++ { + c := l.peek() + if !isHexDigit(c) { + return "", errors.New("unfinished unicode escape") + } + l.next() + code = code + string(c) + } + intcode, err := strconv.ParseInt(code, 16, 32) + if err != nil { + return "", errors.New("invalid unicode escape: \\u" + code) + } + growingString += string(rune(intcode)) + case 'U': + l.next() + code := "" + for i := 0; i < 8; i++ { + c := l.peek() + if !isHexDigit(c) { + return "", errors.New("unfinished unicode escape") + } + l.next() + code = code + string(c) + } + intcode, err := strconv.ParseInt(code, 16, 64) + if err != nil { + return "", errors.New("invalid unicode escape: \\U" + code) + } + growingString += string(rune(intcode)) + default: + return "", errors.New("invalid escape sequence: \\" + string(l.peek())) + } + } else { + r := l.peek() + + if 0x00 <= r && r <= 0x1F && !(acceptNewLines && (r == '\n' || r == '\r')) { + return "", fmt.Errorf("unescaped control character %U", r) + } + l.next() + growingString += string(r) + } + + if l.peek() == eof { + break + } + } + + return "", errors.New("unclosed string") +} + +func (l *tomlLexer) lexString() tomlLexStateFn { + l.skip() + + // handle special case for triple-quote + terminator := `"` + discardLeadingNewLine := false + acceptNewLines := false + if l.follow(`""`) { + l.skip() + l.skip() + terminator = `"""` + discardLeadingNewLine = true + acceptNewLines = true + } + + str, err := l.lexStringAsString(terminator, discardLeadingNewLine, acceptNewLines) + + if err != nil { + return l.errorf(err.Error()) + } + + l.emitWithValue(tokenString, str) + l.fastForward(len(terminator)) + l.ignore() + return l.lexRvalue +} + +func (l *tomlLexer) lexTableKey() tomlLexStateFn { + l.next() + + if l.peek() == '[' { + // token '[[' signifies an array of tables + l.next() + l.emit(tokenDoubleLeftBracket) + return l.lexInsideTableArrayKey + } + // vanilla table key + l.emit(tokenLeftBracket) + return l.lexInsideTableKey +} + +// Parse the key till "]]", but only bare keys are supported +func (l *tomlLexer) lexInsideTableArrayKey() tomlLexStateFn { + for r := l.peek(); r != eof; r = l.peek() { + switch r { + case ']': + if l.currentTokenStop > l.currentTokenStart { + l.emit(tokenKeyGroupArray) + } + l.next() + if l.peek() != ']' { + break + } + l.next() + l.emit(tokenDoubleRightBracket) + return l.lexVoid + case '[': + return l.errorf("table array key cannot contain ']'") + default: + l.next() + } + } + return l.errorf("unclosed table array key") +} + +// Parse the key till "]" but only bare keys are supported +func (l *tomlLexer) lexInsideTableKey() tomlLexStateFn { + for r := l.peek(); r != eof; r = l.peek() { + switch r { + case ']': + if l.currentTokenStop > l.currentTokenStart { + l.emit(tokenKeyGroup) + } + l.next() + l.emit(tokenRightBracket) + return l.lexVoid + case '[': + return l.errorf("table key cannot contain ']'") + default: + l.next() + } + } + return l.errorf("unclosed table key") +} + +func (l *tomlLexer) lexRightBracket() tomlLexStateFn { + l.next() + l.emit(tokenRightBracket) + return l.lexRvalue +} + +type validRuneFn func(r rune) bool + +func isValidHexRune(r rune) bool { + return r >= 'a' && r <= 'f' || + r >= 'A' && r <= 'F' || + r >= '0' && r <= '9' || + r == '_' +} + +func isValidOctalRune(r rune) bool { + return r >= '0' && r <= '7' || r == '_' +} + +func isValidBinaryRune(r rune) bool { + return r == '0' || r == '1' || r == '_' +} + +func (l *tomlLexer) lexNumber() tomlLexStateFn { + r := l.peek() + + if r == '0' { + follow := l.peekString(2) + if len(follow) == 2 { + var isValidRune validRuneFn + switch follow[1] { + case 'x': + isValidRune = isValidHexRune + case 'o': + isValidRune = isValidOctalRune + case 'b': + isValidRune = isValidBinaryRune + default: + if follow[1] >= 'a' && follow[1] <= 'z' || follow[1] >= 'A' && follow[1] <= 'Z' { + return l.errorf("unknown number base: %s. possible options are x (hex) o (octal) b (binary)", string(follow[1])) + } + } + + if isValidRune != nil { + l.next() + l.next() + digitSeen := false + for { + next := l.peek() + if !isValidRune(next) { + break + } + digitSeen = true + l.next() + } + + if !digitSeen { + return l.errorf("number needs at least one digit") + } + + l.emit(tokenInteger) + + return l.lexRvalue + } + } + } + + if r == '+' || r == '-' { + l.next() + if l.follow("inf") { + return l.lexInf + } + if l.follow("nan") { + return l.lexNan + } + } + + pointSeen := false + expSeen := false + digitSeen := false + for { + next := l.peek() + if next == '.' { + if pointSeen { + return l.errorf("cannot have two dots in one float") + } + l.next() + if !isDigit(l.peek()) { + return l.errorf("float cannot end with a dot") + } + pointSeen = true + } else if next == 'e' || next == 'E' { + expSeen = true + l.next() + r := l.peek() + if r == '+' || r == '-' { + l.next() + } + } else if isDigit(next) { + digitSeen = true + l.next() + } else if next == '_' { + l.next() + } else { + break + } + if pointSeen && !digitSeen { + return l.errorf("cannot start float with a dot") + } + } + + if !digitSeen { + return l.errorf("no digit in that number") + } + if pointSeen || expSeen { + l.emit(tokenFloat) + } else { + l.emit(tokenInteger) + } + return l.lexRvalue +} + +func (l *tomlLexer) run() { + for state := l.lexVoid; state != nil; { + state = state() + } +} + +func init() { + dateRegexp = regexp.MustCompile(`^\d{1,4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d{1,9})?(Z|[+-]\d{2}:\d{2})`) +} + +// Entry point +func lexToml(inputBytes []byte) []token { + runes := bytes.Runes(inputBytes) + l := &tomlLexer{ + input: runes, + tokens: make([]token, 0, 256), + line: 1, + col: 1, + endbufferLine: 1, + endbufferCol: 1, + } + l.run() + return l.tokens +} diff --git a/vendor/github.com/pelletier/go-toml/lexer_test.go b/vendor/github.com/pelletier/go-toml/lexer_test.go new file mode 100644 index 00000000..cb491303 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/lexer_test.go @@ -0,0 +1,750 @@ +package toml + +import ( + "reflect" + "testing" +) + +func testFlow(t *testing.T, input string, expectedFlow []token) { + tokens := lexToml([]byte(input)) + if !reflect.DeepEqual(tokens, expectedFlow) { + t.Fatal("Different flows. Expected\n", expectedFlow, "\nGot:\n", tokens) + } +} + +func TestValidKeyGroup(t *testing.T) { + testFlow(t, "[hello world]", []token{ + {Position{1, 1}, tokenLeftBracket, "["}, + {Position{1, 2}, tokenKeyGroup, "hello world"}, + {Position{1, 13}, tokenRightBracket, "]"}, + {Position{1, 14}, tokenEOF, ""}, + }) +} + +func TestNestedQuotedUnicodeKeyGroup(t *testing.T) { + testFlow(t, `[ j . "ʞ" . l ]`, []token{ + {Position{1, 1}, tokenLeftBracket, "["}, + {Position{1, 2}, tokenKeyGroup, ` j . "ʞ" . l `}, + {Position{1, 15}, tokenRightBracket, "]"}, + {Position{1, 16}, tokenEOF, ""}, + }) +} + +func TestUnclosedKeyGroup(t *testing.T) { + testFlow(t, "[hello world", []token{ + {Position{1, 1}, tokenLeftBracket, "["}, + {Position{1, 2}, tokenError, "unclosed table key"}, + }) +} + +func TestComment(t *testing.T) { + testFlow(t, "# blahblah", []token{ + {Position{1, 11}, tokenEOF, ""}, + }) +} + +func TestKeyGroupComment(t *testing.T) { + testFlow(t, "[hello world] # blahblah", []token{ + {Position{1, 1}, tokenLeftBracket, "["}, + {Position{1, 2}, tokenKeyGroup, "hello world"}, + {Position{1, 13}, tokenRightBracket, "]"}, + {Position{1, 25}, tokenEOF, ""}, + }) +} + +func TestMultipleKeyGroupsComment(t *testing.T) { + testFlow(t, "[hello world] # blahblah\n[test]", []token{ + {Position{1, 1}, tokenLeftBracket, "["}, + {Position{1, 2}, tokenKeyGroup, "hello world"}, + {Position{1, 13}, tokenRightBracket, "]"}, + {Position{2, 1}, tokenLeftBracket, "["}, + {Position{2, 2}, tokenKeyGroup, "test"}, + {Position{2, 6}, tokenRightBracket, "]"}, + {Position{2, 7}, tokenEOF, ""}, + }) +} + +func TestSimpleWindowsCRLF(t *testing.T) { + testFlow(t, "a=4\r\nb=2", []token{ + {Position{1, 1}, tokenKey, "a"}, + {Position{1, 2}, tokenEqual, "="}, + {Position{1, 3}, tokenInteger, "4"}, + {Position{2, 1}, tokenKey, "b"}, + {Position{2, 2}, tokenEqual, "="}, + {Position{2, 3}, tokenInteger, "2"}, + {Position{2, 4}, tokenEOF, ""}, + }) +} + +func TestBasicKey(t *testing.T) { + testFlow(t, "hello", []token{ + {Position{1, 1}, tokenKey, "hello"}, + {Position{1, 6}, tokenEOF, ""}, + }) +} + +func TestBasicKeyWithUnderscore(t *testing.T) { + testFlow(t, "hello_hello", []token{ + {Position{1, 1}, tokenKey, "hello_hello"}, + {Position{1, 12}, tokenEOF, ""}, + }) +} + +func TestBasicKeyWithDash(t *testing.T) { + testFlow(t, "hello-world", []token{ + {Position{1, 1}, tokenKey, "hello-world"}, + {Position{1, 12}, tokenEOF, ""}, + }) +} + +func TestBasicKeyWithUppercaseMix(t *testing.T) { + testFlow(t, "helloHELLOHello", []token{ + {Position{1, 1}, tokenKey, "helloHELLOHello"}, + {Position{1, 16}, tokenEOF, ""}, + }) +} + +func TestBasicKeyWithInternationalCharacters(t *testing.T) { + testFlow(t, "héllÖ", []token{ + {Position{1, 1}, tokenKey, "héllÖ"}, + {Position{1, 6}, tokenEOF, ""}, + }) +} + +func TestBasicKeyAndEqual(t *testing.T) { + testFlow(t, "hello =", []token{ + {Position{1, 1}, tokenKey, "hello"}, + {Position{1, 7}, tokenEqual, "="}, + {Position{1, 8}, tokenEOF, ""}, + }) +} + +func TestKeyWithSharpAndEqual(t *testing.T) { + testFlow(t, "key#name = 5", []token{ + {Position{1, 1}, tokenError, "keys cannot contain # character"}, + }) +} + +func TestKeyWithSymbolsAndEqual(t *testing.T) { + testFlow(t, "~!@$^&*()_+-`1234567890[]\\|/?><.,;:' = 5", []token{ + {Position{1, 1}, tokenError, "keys cannot contain ~ character"}, + }) +} + +func TestKeyEqualStringEscape(t *testing.T) { + testFlow(t, `foo = "hello\""`, []token{ + {Position{1, 1}, tokenKey, "foo"}, + {Position{1, 5}, tokenEqual, "="}, + {Position{1, 8}, tokenString, "hello\""}, + {Position{1, 16}, tokenEOF, ""}, + }) +} + +func TestKeyEqualStringUnfinished(t *testing.T) { + testFlow(t, `foo = "bar`, []token{ + {Position{1, 1}, tokenKey, "foo"}, + {Position{1, 5}, tokenEqual, "="}, + {Position{1, 8}, tokenError, "unclosed string"}, + }) +} + +func TestKeyEqualString(t *testing.T) { + testFlow(t, `foo = "bar"`, []token{ + {Position{1, 1}, tokenKey, "foo"}, + {Position{1, 5}, tokenEqual, "="}, + {Position{1, 8}, tokenString, "bar"}, + {Position{1, 12}, tokenEOF, ""}, + }) +} + +func TestKeyEqualTrue(t *testing.T) { + testFlow(t, "foo = true", []token{ + {Position{1, 1}, tokenKey, "foo"}, + {Position{1, 5}, tokenEqual, "="}, + {Position{1, 7}, tokenTrue, "true"}, + {Position{1, 11}, tokenEOF, ""}, + }) +} + +func TestKeyEqualFalse(t *testing.T) { + testFlow(t, "foo = false", []token{ + {Position{1, 1}, tokenKey, "foo"}, + {Position{1, 5}, tokenEqual, "="}, + {Position{1, 7}, tokenFalse, "false"}, + {Position{1, 12}, tokenEOF, ""}, + }) +} + +func TestArrayNestedString(t *testing.T) { + testFlow(t, `a = [ ["hello", "world"] ]`, []token{ + {Position{1, 1}, tokenKey, "a"}, + {Position{1, 3}, tokenEqual, "="}, + {Position{1, 5}, tokenLeftBracket, "["}, + {Position{1, 7}, tokenLeftBracket, "["}, + {Position{1, 9}, tokenString, "hello"}, + {Position{1, 15}, tokenComma, ","}, + {Position{1, 18}, tokenString, "world"}, + {Position{1, 24}, tokenRightBracket, "]"}, + {Position{1, 26}, tokenRightBracket, "]"}, + {Position{1, 27}, tokenEOF, ""}, + }) +} + +func TestArrayNestedInts(t *testing.T) { + testFlow(t, "a = [ [42, 21], [10] ]", []token{ + {Position{1, 1}, tokenKey, "a"}, + {Position{1, 3}, tokenEqual, "="}, + {Position{1, 5}, tokenLeftBracket, "["}, + {Position{1, 7}, tokenLeftBracket, "["}, + {Position{1, 8}, tokenInteger, "42"}, + {Position{1, 10}, tokenComma, ","}, + {Position{1, 12}, tokenInteger, "21"}, + {Position{1, 14}, tokenRightBracket, "]"}, + {Position{1, 15}, tokenComma, ","}, + {Position{1, 17}, tokenLeftBracket, "["}, + {Position{1, 18}, tokenInteger, "10"}, + {Position{1, 20}, tokenRightBracket, "]"}, + {Position{1, 22}, tokenRightBracket, "]"}, + {Position{1, 23}, tokenEOF, ""}, + }) +} + +func TestArrayInts(t *testing.T) { + testFlow(t, "a = [ 42, 21, 10, ]", []token{ + {Position{1, 1}, tokenKey, "a"}, + {Position{1, 3}, tokenEqual, "="}, + {Position{1, 5}, tokenLeftBracket, "["}, + {Position{1, 7}, tokenInteger, "42"}, + {Position{1, 9}, tokenComma, ","}, + {Position{1, 11}, tokenInteger, "21"}, + {Position{1, 13}, tokenComma, ","}, + {Position{1, 15}, tokenInteger, "10"}, + {Position{1, 17}, tokenComma, ","}, + {Position{1, 19}, tokenRightBracket, "]"}, + {Position{1, 20}, tokenEOF, ""}, + }) +} + +func TestMultilineArrayComments(t *testing.T) { + testFlow(t, "a = [1, # wow\n2, # such items\n3, # so array\n]", []token{ + {Position{1, 1}, tokenKey, "a"}, + {Position{1, 3}, tokenEqual, "="}, + {Position{1, 5}, tokenLeftBracket, "["}, + {Position{1, 6}, tokenInteger, "1"}, + {Position{1, 7}, tokenComma, ","}, + {Position{2, 1}, tokenInteger, "2"}, + {Position{2, 2}, tokenComma, ","}, + {Position{3, 1}, tokenInteger, "3"}, + {Position{3, 2}, tokenComma, ","}, + {Position{4, 1}, tokenRightBracket, "]"}, + {Position{4, 2}, tokenEOF, ""}, + }) +} + +func TestNestedArraysComment(t *testing.T) { + toml := ` +someArray = [ +# does not work +["entry1"] +]` + testFlow(t, toml, []token{ + {Position{2, 1}, tokenKey, "someArray"}, + {Position{2, 11}, tokenEqual, "="}, + {Position{2, 13}, tokenLeftBracket, "["}, + {Position{4, 1}, tokenLeftBracket, "["}, + {Position{4, 3}, tokenString, "entry1"}, + {Position{4, 10}, tokenRightBracket, "]"}, + {Position{5, 1}, tokenRightBracket, "]"}, + {Position{5, 2}, tokenEOF, ""}, + }) +} + +func TestKeyEqualArrayBools(t *testing.T) { + testFlow(t, "foo = [true, false, true]", []token{ + {Position{1, 1}, tokenKey, "foo"}, + {Position{1, 5}, tokenEqual, "="}, + {Position{1, 7}, tokenLeftBracket, "["}, + {Position{1, 8}, tokenTrue, "true"}, + {Position{1, 12}, tokenComma, ","}, + {Position{1, 14}, tokenFalse, "false"}, + {Position{1, 19}, tokenComma, ","}, + {Position{1, 21}, tokenTrue, "true"}, + {Position{1, 25}, tokenRightBracket, "]"}, + {Position{1, 26}, tokenEOF, ""}, + }) +} + +func TestKeyEqualArrayBoolsWithComments(t *testing.T) { + testFlow(t, "foo = [true, false, true] # YEAH", []token{ + {Position{1, 1}, tokenKey, "foo"}, + {Position{1, 5}, tokenEqual, "="}, + {Position{1, 7}, tokenLeftBracket, "["}, + {Position{1, 8}, tokenTrue, "true"}, + {Position{1, 12}, tokenComma, ","}, + {Position{1, 14}, tokenFalse, "false"}, + {Position{1, 19}, tokenComma, ","}, + {Position{1, 21}, tokenTrue, "true"}, + {Position{1, 25}, tokenRightBracket, "]"}, + {Position{1, 33}, tokenEOF, ""}, + }) +} + +func TestDateRegexp(t *testing.T) { + if dateRegexp.FindString("1979-05-27T07:32:00Z") == "" { + t.Error("basic lexing") + } + if dateRegexp.FindString("1979-05-27T00:32:00-07:00") == "" { + t.Error("offset lexing") + } + if dateRegexp.FindString("1979-05-27T00:32:00.999999-07:00") == "" { + t.Error("nano precision lexing") + } +} + +func TestKeyEqualDate(t *testing.T) { + testFlow(t, "foo = 1979-05-27T07:32:00Z", []token{ + {Position{1, 1}, tokenKey, "foo"}, + {Position{1, 5}, tokenEqual, "="}, + {Position{1, 7}, tokenDate, "1979-05-27T07:32:00Z"}, + {Position{1, 27}, tokenEOF, ""}, + }) + testFlow(t, "foo = 1979-05-27T00:32:00-07:00", []token{ + {Position{1, 1}, tokenKey, "foo"}, + {Position{1, 5}, tokenEqual, "="}, + {Position{1, 7}, tokenDate, "1979-05-27T00:32:00-07:00"}, + {Position{1, 32}, tokenEOF, ""}, + }) + testFlow(t, "foo = 1979-05-27T00:32:00.999999-07:00", []token{ + {Position{1, 1}, tokenKey, "foo"}, + {Position{1, 5}, tokenEqual, "="}, + {Position{1, 7}, tokenDate, "1979-05-27T00:32:00.999999-07:00"}, + {Position{1, 39}, tokenEOF, ""}, + }) +} + +func TestFloatEndingWithDot(t *testing.T) { + testFlow(t, "foo = 42.", []token{ + {Position{1, 1}, tokenKey, "foo"}, + {Position{1, 5}, tokenEqual, "="}, + {Position{1, 7}, tokenError, "float cannot end with a dot"}, + }) +} + +func TestFloatWithTwoDots(t *testing.T) { + testFlow(t, "foo = 4.2.", []token{ + {Position{1, 1}, tokenKey, "foo"}, + {Position{1, 5}, tokenEqual, "="}, + {Position{1, 7}, tokenError, "cannot have two dots in one float"}, + }) +} + +func TestFloatWithExponent1(t *testing.T) { + testFlow(t, "a = 5e+22", []token{ + {Position{1, 1}, tokenKey, "a"}, + {Position{1, 3}, tokenEqual, "="}, + {Position{1, 5}, tokenFloat, "5e+22"}, + {Position{1, 10}, tokenEOF, ""}, + }) +} + +func TestFloatWithExponent2(t *testing.T) { + testFlow(t, "a = 5E+22", []token{ + {Position{1, 1}, tokenKey, "a"}, + {Position{1, 3}, tokenEqual, "="}, + {Position{1, 5}, tokenFloat, "5E+22"}, + {Position{1, 10}, tokenEOF, ""}, + }) +} + +func TestFloatWithExponent3(t *testing.T) { + testFlow(t, "a = -5e+22", []token{ + {Position{1, 1}, tokenKey, "a"}, + {Position{1, 3}, tokenEqual, "="}, + {Position{1, 5}, tokenFloat, "-5e+22"}, + {Position{1, 11}, tokenEOF, ""}, + }) +} + +func TestFloatWithExponent4(t *testing.T) { + testFlow(t, "a = -5e-22", []token{ + {Position{1, 1}, tokenKey, "a"}, + {Position{1, 3}, tokenEqual, "="}, + {Position{1, 5}, tokenFloat, "-5e-22"}, + {Position{1, 11}, tokenEOF, ""}, + }) +} + +func TestFloatWithExponent5(t *testing.T) { + testFlow(t, "a = 6.626e-34", []token{ + {Position{1, 1}, tokenKey, "a"}, + {Position{1, 3}, tokenEqual, "="}, + {Position{1, 5}, tokenFloat, "6.626e-34"}, + {Position{1, 14}, tokenEOF, ""}, + }) +} + +func TestInvalidEsquapeSequence(t *testing.T) { + testFlow(t, `foo = "\x"`, []token{ + {Position{1, 1}, tokenKey, "foo"}, + {Position{1, 5}, tokenEqual, "="}, + {Position{1, 8}, tokenError, "invalid escape sequence: \\x"}, + }) +} + +func TestNestedArrays(t *testing.T) { + testFlow(t, "foo = [[[]]]", []token{ + {Position{1, 1}, tokenKey, "foo"}, + {Position{1, 5}, tokenEqual, "="}, + {Position{1, 7}, tokenLeftBracket, "["}, + {Position{1, 8}, tokenLeftBracket, "["}, + {Position{1, 9}, tokenLeftBracket, "["}, + {Position{1, 10}, tokenRightBracket, "]"}, + {Position{1, 11}, tokenRightBracket, "]"}, + {Position{1, 12}, tokenRightBracket, "]"}, + {Position{1, 13}, tokenEOF, ""}, + }) +} + +func TestKeyEqualNumber(t *testing.T) { + testFlow(t, "foo = 42", []token{ + {Position{1, 1}, tokenKey, "foo"}, + {Position{1, 5}, tokenEqual, "="}, + {Position{1, 7}, tokenInteger, "42"}, + {Position{1, 9}, tokenEOF, ""}, + }) + + testFlow(t, "foo = +42", []token{ + {Position{1, 1}, tokenKey, "foo"}, + {Position{1, 5}, tokenEqual, "="}, + {Position{1, 7}, tokenInteger, "+42"}, + {Position{1, 10}, tokenEOF, ""}, + }) + + testFlow(t, "foo = -42", []token{ + {Position{1, 1}, tokenKey, "foo"}, + {Position{1, 5}, tokenEqual, "="}, + {Position{1, 7}, tokenInteger, "-42"}, + {Position{1, 10}, tokenEOF, ""}, + }) + + testFlow(t, "foo = 4.2", []token{ + {Position{1, 1}, tokenKey, "foo"}, + {Position{1, 5}, tokenEqual, "="}, + {Position{1, 7}, tokenFloat, "4.2"}, + {Position{1, 10}, tokenEOF, ""}, + }) + + testFlow(t, "foo = +4.2", []token{ + {Position{1, 1}, tokenKey, "foo"}, + {Position{1, 5}, tokenEqual, "="}, + {Position{1, 7}, tokenFloat, "+4.2"}, + {Position{1, 11}, tokenEOF, ""}, + }) + + testFlow(t, "foo = -4.2", []token{ + {Position{1, 1}, tokenKey, "foo"}, + {Position{1, 5}, tokenEqual, "="}, + {Position{1, 7}, tokenFloat, "-4.2"}, + {Position{1, 11}, tokenEOF, ""}, + }) + + testFlow(t, "foo = 1_000", []token{ + {Position{1, 1}, tokenKey, "foo"}, + {Position{1, 5}, tokenEqual, "="}, + {Position{1, 7}, tokenInteger, "1_000"}, + {Position{1, 12}, tokenEOF, ""}, + }) + + testFlow(t, "foo = 5_349_221", []token{ + {Position{1, 1}, tokenKey, "foo"}, + {Position{1, 5}, tokenEqual, "="}, + {Position{1, 7}, tokenInteger, "5_349_221"}, + {Position{1, 16}, tokenEOF, ""}, + }) + + testFlow(t, "foo = 1_2_3_4_5", []token{ + {Position{1, 1}, tokenKey, "foo"}, + {Position{1, 5}, tokenEqual, "="}, + {Position{1, 7}, tokenInteger, "1_2_3_4_5"}, + {Position{1, 16}, tokenEOF, ""}, + }) + + testFlow(t, "flt8 = 9_224_617.445_991_228_313", []token{ + {Position{1, 1}, tokenKey, "flt8"}, + {Position{1, 6}, tokenEqual, "="}, + {Position{1, 8}, tokenFloat, "9_224_617.445_991_228_313"}, + {Position{1, 33}, tokenEOF, ""}, + }) + + testFlow(t, "foo = +", []token{ + {Position{1, 1}, tokenKey, "foo"}, + {Position{1, 5}, tokenEqual, "="}, + {Position{1, 7}, tokenError, "no digit in that number"}, + }) +} + +func TestMultiline(t *testing.T) { + testFlow(t, "foo = 42\nbar=21", []token{ + {Position{1, 1}, tokenKey, "foo"}, + {Position{1, 5}, tokenEqual, "="}, + {Position{1, 7}, tokenInteger, "42"}, + {Position{2, 1}, tokenKey, "bar"}, + {Position{2, 4}, tokenEqual, "="}, + {Position{2, 5}, tokenInteger, "21"}, + {Position{2, 7}, tokenEOF, ""}, + }) +} + +func TestKeyEqualStringUnicodeEscape(t *testing.T) { + testFlow(t, `foo = "hello \u2665"`, []token{ + {Position{1, 1}, tokenKey, "foo"}, + {Position{1, 5}, tokenEqual, "="}, + {Position{1, 8}, tokenString, "hello ♥"}, + {Position{1, 21}, tokenEOF, ""}, + }) + testFlow(t, `foo = "hello \U000003B4"`, []token{ + {Position{1, 1}, tokenKey, "foo"}, + {Position{1, 5}, tokenEqual, "="}, + {Position{1, 8}, tokenString, "hello δ"}, + {Position{1, 25}, tokenEOF, ""}, + }) + testFlow(t, `foo = "\uabcd"`, []token{ + {Position{1, 1}, tokenKey, "foo"}, + {Position{1, 5}, tokenEqual, "="}, + {Position{1, 8}, tokenString, "\uabcd"}, + {Position{1, 15}, tokenEOF, ""}, + }) + testFlow(t, `foo = "\uABCD"`, []token{ + {Position{1, 1}, tokenKey, "foo"}, + {Position{1, 5}, tokenEqual, "="}, + {Position{1, 8}, tokenString, "\uABCD"}, + {Position{1, 15}, tokenEOF, ""}, + }) + testFlow(t, `foo = "\U000bcdef"`, []token{ + {Position{1, 1}, tokenKey, "foo"}, + {Position{1, 5}, tokenEqual, "="}, + {Position{1, 8}, tokenString, "\U000bcdef"}, + {Position{1, 19}, tokenEOF, ""}, + }) + testFlow(t, `foo = "\U000BCDEF"`, []token{ + {Position{1, 1}, tokenKey, "foo"}, + {Position{1, 5}, tokenEqual, "="}, + {Position{1, 8}, tokenString, "\U000BCDEF"}, + {Position{1, 19}, tokenEOF, ""}, + }) + testFlow(t, `foo = "\u2"`, []token{ + {Position{1, 1}, tokenKey, "foo"}, + {Position{1, 5}, tokenEqual, "="}, + {Position{1, 8}, tokenError, "unfinished unicode escape"}, + }) + testFlow(t, `foo = "\U2"`, []token{ + {Position{1, 1}, tokenKey, "foo"}, + {Position{1, 5}, tokenEqual, "="}, + {Position{1, 8}, tokenError, "unfinished unicode escape"}, + }) +} + +func TestKeyEqualStringNoEscape(t *testing.T) { + testFlow(t, "foo = \"hello \u0002\"", []token{ + {Position{1, 1}, tokenKey, "foo"}, + {Position{1, 5}, tokenEqual, "="}, + {Position{1, 8}, tokenError, "unescaped control character U+0002"}, + }) + testFlow(t, "foo = \"hello \u001F\"", []token{ + {Position{1, 1}, tokenKey, "foo"}, + {Position{1, 5}, tokenEqual, "="}, + {Position{1, 8}, tokenError, "unescaped control character U+001F"}, + }) +} + +func TestLiteralString(t *testing.T) { + testFlow(t, `foo = 'C:\Users\nodejs\templates'`, []token{ + {Position{1, 1}, tokenKey, "foo"}, + {Position{1, 5}, tokenEqual, "="}, + {Position{1, 8}, tokenString, `C:\Users\nodejs\templates`}, + {Position{1, 34}, tokenEOF, ""}, + }) + testFlow(t, `foo = '\\ServerX\admin$\system32\'`, []token{ + {Position{1, 1}, tokenKey, "foo"}, + {Position{1, 5}, tokenEqual, "="}, + {Position{1, 8}, tokenString, `\\ServerX\admin$\system32\`}, + {Position{1, 35}, tokenEOF, ""}, + }) + testFlow(t, `foo = 'Tom "Dubs" Preston-Werner'`, []token{ + {Position{1, 1}, tokenKey, "foo"}, + {Position{1, 5}, tokenEqual, "="}, + {Position{1, 8}, tokenString, `Tom "Dubs" Preston-Werner`}, + {Position{1, 34}, tokenEOF, ""}, + }) + testFlow(t, `foo = '<\i\c*\s*>'`, []token{ + {Position{1, 1}, tokenKey, "foo"}, + {Position{1, 5}, tokenEqual, "="}, + {Position{1, 8}, tokenString, `<\i\c*\s*>`}, + {Position{1, 19}, tokenEOF, ""}, + }) + testFlow(t, `foo = 'C:\Users\nodejs\unfinis`, []token{ + {Position{1, 1}, tokenKey, "foo"}, + {Position{1, 5}, tokenEqual, "="}, + {Position{1, 8}, tokenError, "unclosed string"}, + }) +} + +func TestMultilineLiteralString(t *testing.T) { + testFlow(t, `foo = '''hello 'literal' world'''`, []token{ + {Position{1, 1}, tokenKey, "foo"}, + {Position{1, 5}, tokenEqual, "="}, + {Position{1, 10}, tokenString, `hello 'literal' world`}, + {Position{1, 34}, tokenEOF, ""}, + }) + + testFlow(t, "foo = '''\nhello\n'literal'\nworld'''", []token{ + {Position{1, 1}, tokenKey, "foo"}, + {Position{1, 5}, tokenEqual, "="}, + {Position{2, 1}, tokenString, "hello\n'literal'\nworld"}, + {Position{4, 9}, tokenEOF, ""}, + }) + testFlow(t, "foo = '''\r\nhello\r\n'literal'\r\nworld'''", []token{ + {Position{1, 1}, tokenKey, "foo"}, + {Position{1, 5}, tokenEqual, "="}, + {Position{2, 1}, tokenString, "hello\r\n'literal'\r\nworld"}, + {Position{4, 9}, tokenEOF, ""}, + }) +} + +func TestMultilineString(t *testing.T) { + testFlow(t, `foo = """hello "literal" world"""`, []token{ + {Position{1, 1}, tokenKey, "foo"}, + {Position{1, 5}, tokenEqual, "="}, + {Position{1, 10}, tokenString, `hello "literal" world`}, + {Position{1, 34}, tokenEOF, ""}, + }) + + testFlow(t, "foo = \"\"\"\r\nhello\\\r\n\"literal\"\\\nworld\"\"\"", []token{ + {Position{1, 1}, tokenKey, "foo"}, + {Position{1, 5}, tokenEqual, "="}, + {Position{2, 1}, tokenString, "hello\"literal\"world"}, + {Position{4, 9}, tokenEOF, ""}, + }) + + testFlow(t, "foo = \"\"\"\\\n \\\n \\\n hello\\\nmultiline\\\nworld\"\"\"", []token{ + {Position{1, 1}, tokenKey, "foo"}, + {Position{1, 5}, tokenEqual, "="}, + {Position{1, 10}, tokenString, "hellomultilineworld"}, + {Position{6, 9}, tokenEOF, ""}, + }) + + testFlow(t, "key2 = \"\"\"\nThe quick brown \\\n\n\n fox jumps over \\\n the lazy dog.\"\"\"", []token{ + {Position{1, 1}, tokenKey, "key2"}, + {Position{1, 6}, tokenEqual, "="}, + {Position{2, 1}, tokenString, "The quick brown fox jumps over the lazy dog."}, + {Position{6, 21}, tokenEOF, ""}, + }) + + testFlow(t, "key2 = \"\"\"\\\n The quick brown \\\n fox jumps over \\\n the lazy dog.\\\n \"\"\"", []token{ + {Position{1, 1}, tokenKey, "key2"}, + {Position{1, 6}, tokenEqual, "="}, + {Position{1, 11}, tokenString, "The quick brown fox jumps over the lazy dog."}, + {Position{5, 11}, tokenEOF, ""}, + }) + + testFlow(t, `key2 = "Roses are red\nViolets are blue"`, []token{ + {Position{1, 1}, tokenKey, "key2"}, + {Position{1, 6}, tokenEqual, "="}, + {Position{1, 9}, tokenString, "Roses are red\nViolets are blue"}, + {Position{1, 41}, tokenEOF, ""}, + }) + + testFlow(t, "key2 = \"\"\"\nRoses are red\nViolets are blue\"\"\"", []token{ + {Position{1, 1}, tokenKey, "key2"}, + {Position{1, 6}, tokenEqual, "="}, + {Position{2, 1}, tokenString, "Roses are red\nViolets are blue"}, + {Position{3, 20}, tokenEOF, ""}, + }) +} + +func TestUnicodeString(t *testing.T) { + testFlow(t, `foo = "hello ♥ world"`, []token{ + {Position{1, 1}, tokenKey, "foo"}, + {Position{1, 5}, tokenEqual, "="}, + {Position{1, 8}, tokenString, "hello ♥ world"}, + {Position{1, 22}, tokenEOF, ""}, + }) +} +func TestEscapeInString(t *testing.T) { + testFlow(t, `foo = "\b\f\/"`, []token{ + {Position{1, 1}, tokenKey, "foo"}, + {Position{1, 5}, tokenEqual, "="}, + {Position{1, 8}, tokenString, "\b\f/"}, + {Position{1, 15}, tokenEOF, ""}, + }) +} + +func TestKeyGroupArray(t *testing.T) { + testFlow(t, "[[foo]]", []token{ + {Position{1, 1}, tokenDoubleLeftBracket, "[["}, + {Position{1, 3}, tokenKeyGroupArray, "foo"}, + {Position{1, 6}, tokenDoubleRightBracket, "]]"}, + {Position{1, 8}, tokenEOF, ""}, + }) +} + +func TestQuotedKey(t *testing.T) { + testFlow(t, "\"a b\" = 42", []token{ + {Position{1, 1}, tokenKey, "a b"}, + {Position{1, 7}, tokenEqual, "="}, + {Position{1, 9}, tokenInteger, "42"}, + {Position{1, 11}, tokenEOF, ""}, + }) +} + +func TestKeyNewline(t *testing.T) { + testFlow(t, "a\n= 4", []token{ + {Position{1, 1}, tokenError, "keys cannot contain new lines"}, + }) +} + +func TestInvalidFloat(t *testing.T) { + testFlow(t, "a=7e1_", []token{ + {Position{1, 1}, tokenKey, "a"}, + {Position{1, 2}, tokenEqual, "="}, + {Position{1, 3}, tokenFloat, "7e1_"}, + {Position{1, 7}, tokenEOF, ""}, + }) +} + +func TestLexUnknownRvalue(t *testing.T) { + testFlow(t, `a = !b`, []token{ + {Position{1, 1}, tokenKey, "a"}, + {Position{1, 3}, tokenEqual, "="}, + {Position{1, 5}, tokenError, "no value can start with !"}, + }) + + testFlow(t, `a = \b`, []token{ + {Position{1, 1}, tokenKey, "a"}, + {Position{1, 3}, tokenEqual, "="}, + {Position{1, 5}, tokenError, `no value can start with \`}, + }) +} + +func BenchmarkLexer(b *testing.B) { + sample := `title = "Hugo: A Fast and Flexible Website Generator" +baseurl = "http://gohugo.io/" +MetaDataFormat = "yaml" +pluralizeListTitles = false + +[params] + description = "Documentation of Hugo, a fast and flexible static site generator built with love by spf13, bep and friends in Go" + author = "Steve Francia (spf13) and friends" + release = "0.22-DEV" + +[[menu.main]] + name = "Download Hugo" + pre = "" + url = "https://github.com/spf13/hugo/releases" + weight = -200 +` + b.ResetTimer() + for i := 0; i < b.N; i++ { + lexToml([]byte(sample)) + } +} diff --git a/vendor/github.com/pelletier/go-toml/marshal.go b/vendor/github.com/pelletier/go-toml/marshal.go new file mode 100644 index 00000000..b5a24150 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/marshal.go @@ -0,0 +1,600 @@ +package toml + +import ( + "bytes" + "errors" + "fmt" + "io" + "reflect" + "strconv" + "strings" + "time" +) + +type tomlOpts struct { + name string + comment string + commented bool + include bool + omitempty bool +} + +type encOpts struct { + quoteMapKeys bool + arraysOneElementPerLine bool +} + +var encOptsDefaults = encOpts{ + quoteMapKeys: false, +} + +var timeType = reflect.TypeOf(time.Time{}) +var marshalerType = reflect.TypeOf(new(Marshaler)).Elem() + +// Check if the given marshall type maps to a Tree primitive +func isPrimitive(mtype reflect.Type) bool { + switch mtype.Kind() { + case reflect.Ptr: + return isPrimitive(mtype.Elem()) + case reflect.Bool: + return true + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return true + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + return true + case reflect.Float32, reflect.Float64: + return true + case reflect.String: + return true + case reflect.Struct: + return mtype == timeType || isCustomMarshaler(mtype) + default: + return false + } +} + +// Check if the given marshall type maps to a Tree slice +func isTreeSlice(mtype reflect.Type) bool { + switch mtype.Kind() { + case reflect.Slice: + return !isOtherSlice(mtype) + default: + return false + } +} + +// Check if the given marshall type maps to a non-Tree slice +func isOtherSlice(mtype reflect.Type) bool { + switch mtype.Kind() { + case reflect.Ptr: + return isOtherSlice(mtype.Elem()) + case reflect.Slice: + return isPrimitive(mtype.Elem()) || isOtherSlice(mtype.Elem()) + default: + return false + } +} + +// Check if the given marshall type maps to a Tree +func isTree(mtype reflect.Type) bool { + switch mtype.Kind() { + case reflect.Map: + return true + case reflect.Struct: + return !isPrimitive(mtype) + default: + return false + } +} + +func isCustomMarshaler(mtype reflect.Type) bool { + return mtype.Implements(marshalerType) +} + +func callCustomMarshaler(mval reflect.Value) ([]byte, error) { + return mval.Interface().(Marshaler).MarshalTOML() +} + +// Marshaler is the interface implemented by types that +// can marshal themselves into valid TOML. +type Marshaler interface { + MarshalTOML() ([]byte, error) +} + +/* +Marshal returns the TOML encoding of v. Behavior is similar to the Go json +encoder, except that there is no concept of a Marshaler interface or MarshalTOML +function for sub-structs, and currently only definite types can be marshaled +(i.e. no `interface{}`). + +The following struct annotations are supported: + + toml:"Field" Overrides the field's name to output. + omitempty When set, empty values and groups are not emitted. + comment:"comment" Emits a # comment on the same line. This supports new lines. + commented:"true" Emits the value as commented. + +Note that pointers are automatically assigned the "omitempty" option, as TOML +explicitly does not handle null values (saying instead the label should be +dropped). + +Tree structural types and corresponding marshal types: + + *Tree (*)struct, (*)map[string]interface{} + []*Tree (*)[](*)struct, (*)[](*)map[string]interface{} + []interface{} (as interface{}) (*)[]primitive, (*)[]([]interface{}) + interface{} (*)primitive + +Tree primitive types and corresponding marshal types: + + uint64 uint, uint8-uint64, pointers to same + int64 int, int8-uint64, pointers to same + float64 float32, float64, pointers to same + string string, pointers to same + bool bool, pointers to same + time.Time time.Time{}, pointers to same +*/ +func Marshal(v interface{}) ([]byte, error) { + return NewEncoder(nil).marshal(v) +} + +// Encoder writes TOML values to an output stream. +type Encoder struct { + w io.Writer + encOpts +} + +// NewEncoder returns a new encoder that writes to w. +func NewEncoder(w io.Writer) *Encoder { + return &Encoder{ + w: w, + encOpts: encOptsDefaults, + } +} + +// Encode writes the TOML encoding of v to the stream. +// +// See the documentation for Marshal for details. +func (e *Encoder) Encode(v interface{}) error { + b, err := e.marshal(v) + if err != nil { + return err + } + if _, err := e.w.Write(b); err != nil { + return err + } + return nil +} + +// QuoteMapKeys sets up the encoder to encode +// maps with string type keys with quoted TOML keys. +// +// This relieves the character limitations on map keys. +func (e *Encoder) QuoteMapKeys(v bool) *Encoder { + e.quoteMapKeys = v + return e +} + +// ArraysWithOneElementPerLine sets up the encoder to encode arrays +// with more than one element on multiple lines instead of one. +// +// For example: +// +// A = [1,2,3] +// +// Becomes +// +// A = [ +// 1, +// 2, +// 3 +// ] +func (e *Encoder) ArraysWithOneElementPerLine(v bool) *Encoder { + e.arraysOneElementPerLine = v + return e +} + +func (e *Encoder) marshal(v interface{}) ([]byte, error) { + mtype := reflect.TypeOf(v) + if mtype.Kind() != reflect.Struct { + return []byte{}, errors.New("Only a struct can be marshaled to TOML") + } + sval := reflect.ValueOf(v) + if isCustomMarshaler(mtype) { + return callCustomMarshaler(sval) + } + t, err := e.valueToTree(mtype, sval) + if err != nil { + return []byte{}, err + } + + var buf bytes.Buffer + _, err = t.writeTo(&buf, "", "", 0, e.arraysOneElementPerLine) + + return buf.Bytes(), err +} + +// Convert given marshal struct or map value to toml tree +func (e *Encoder) valueToTree(mtype reflect.Type, mval reflect.Value) (*Tree, error) { + if mtype.Kind() == reflect.Ptr { + return e.valueToTree(mtype.Elem(), mval.Elem()) + } + tval := newTree() + switch mtype.Kind() { + case reflect.Struct: + for i := 0; i < mtype.NumField(); i++ { + mtypef, mvalf := mtype.Field(i), mval.Field(i) + opts := tomlOptions(mtypef) + if opts.include && (!opts.omitempty || !isZero(mvalf)) { + val, err := e.valueToToml(mtypef.Type, mvalf) + if err != nil { + return nil, err + } + tval.SetWithComment(opts.name, opts.comment, opts.commented, val) + } + } + case reflect.Map: + for _, key := range mval.MapKeys() { + mvalf := mval.MapIndex(key) + val, err := e.valueToToml(mtype.Elem(), mvalf) + if err != nil { + return nil, err + } + if e.quoteMapKeys { + keyStr, err := tomlValueStringRepresentation(key.String(), "", e.arraysOneElementPerLine) + if err != nil { + return nil, err + } + tval.SetPath([]string{keyStr}, val) + } else { + tval.Set(key.String(), val) + } + } + } + return tval, nil +} + +// Convert given marshal slice to slice of Toml trees +func (e *Encoder) valueToTreeSlice(mtype reflect.Type, mval reflect.Value) ([]*Tree, error) { + tval := make([]*Tree, mval.Len(), mval.Len()) + for i := 0; i < mval.Len(); i++ { + val, err := e.valueToTree(mtype.Elem(), mval.Index(i)) + if err != nil { + return nil, err + } + tval[i] = val + } + return tval, nil +} + +// Convert given marshal slice to slice of toml values +func (e *Encoder) valueToOtherSlice(mtype reflect.Type, mval reflect.Value) (interface{}, error) { + tval := make([]interface{}, mval.Len(), mval.Len()) + for i := 0; i < mval.Len(); i++ { + val, err := e.valueToToml(mtype.Elem(), mval.Index(i)) + if err != nil { + return nil, err + } + tval[i] = val + } + return tval, nil +} + +// Convert given marshal value to toml value +func (e *Encoder) valueToToml(mtype reflect.Type, mval reflect.Value) (interface{}, error) { + if mtype.Kind() == reflect.Ptr { + return e.valueToToml(mtype.Elem(), mval.Elem()) + } + switch { + case isCustomMarshaler(mtype): + return callCustomMarshaler(mval) + case isTree(mtype): + return e.valueToTree(mtype, mval) + case isTreeSlice(mtype): + return e.valueToTreeSlice(mtype, mval) + case isOtherSlice(mtype): + return e.valueToOtherSlice(mtype, mval) + default: + switch mtype.Kind() { + case reflect.Bool: + return mval.Bool(), nil + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return mval.Int(), nil + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + return mval.Uint(), nil + case reflect.Float32, reflect.Float64: + return mval.Float(), nil + case reflect.String: + return mval.String(), nil + case reflect.Struct: + return mval.Interface().(time.Time), nil + default: + return nil, fmt.Errorf("Marshal can't handle %v(%v)", mtype, mtype.Kind()) + } + } +} + +// Unmarshal attempts to unmarshal the Tree into a Go struct pointed by v. +// Neither Unmarshaler interfaces nor UnmarshalTOML functions are supported for +// sub-structs, and only definite types can be unmarshaled. +func (t *Tree) Unmarshal(v interface{}) error { + d := Decoder{tval: t} + return d.unmarshal(v) +} + +// Marshal returns the TOML encoding of Tree. +// See Marshal() documentation for types mapping table. +func (t *Tree) Marshal() ([]byte, error) { + var buf bytes.Buffer + err := NewEncoder(&buf).Encode(t) + return buf.Bytes(), err +} + +// Unmarshal parses the TOML-encoded data and stores the result in the value +// pointed to by v. Behavior is similar to the Go json encoder, except that there +// is no concept of an Unmarshaler interface or UnmarshalTOML function for +// sub-structs, and currently only definite types can be unmarshaled to (i.e. no +// `interface{}`). +// +// The following struct annotations are supported: +// +// toml:"Field" Overrides the field's name to map to. +// +// See Marshal() documentation for types mapping table. +func Unmarshal(data []byte, v interface{}) error { + t, err := LoadReader(bytes.NewReader(data)) + if err != nil { + return err + } + return t.Unmarshal(v) +} + +// Decoder reads and decodes TOML values from an input stream. +type Decoder struct { + r io.Reader + tval *Tree + encOpts +} + +// NewDecoder returns a new decoder that reads from r. +func NewDecoder(r io.Reader) *Decoder { + return &Decoder{ + r: r, + encOpts: encOptsDefaults, + } +} + +// Decode reads a TOML-encoded value from it's input +// and unmarshals it in the value pointed at by v. +// +// See the documentation for Marshal for details. +func (d *Decoder) Decode(v interface{}) error { + var err error + d.tval, err = LoadReader(d.r) + if err != nil { + return err + } + return d.unmarshal(v) +} + +func (d *Decoder) unmarshal(v interface{}) error { + mtype := reflect.TypeOf(v) + if mtype.Kind() != reflect.Ptr || mtype.Elem().Kind() != reflect.Struct { + return errors.New("Only a pointer to struct can be unmarshaled from TOML") + } + + sval, err := d.valueFromTree(mtype.Elem(), d.tval) + if err != nil { + return err + } + reflect.ValueOf(v).Elem().Set(sval) + return nil +} + +// Convert toml tree to marshal struct or map, using marshal type +func (d *Decoder) valueFromTree(mtype reflect.Type, tval *Tree) (reflect.Value, error) { + if mtype.Kind() == reflect.Ptr { + return d.unwrapPointer(mtype, tval) + } + var mval reflect.Value + switch mtype.Kind() { + case reflect.Struct: + mval = reflect.New(mtype).Elem() + for i := 0; i < mtype.NumField(); i++ { + mtypef := mtype.Field(i) + opts := tomlOptions(mtypef) + if opts.include { + baseKey := opts.name + keysToTry := []string{baseKey, strings.ToLower(baseKey), strings.ToTitle(baseKey)} + for _, key := range keysToTry { + exists := tval.Has(key) + if !exists { + continue + } + val := tval.Get(key) + mvalf, err := d.valueFromToml(mtypef.Type, val) + if err != nil { + return mval, formatError(err, tval.GetPosition(key)) + } + mval.Field(i).Set(mvalf) + break + } + } + } + case reflect.Map: + mval = reflect.MakeMap(mtype) + for _, key := range tval.Keys() { + // TODO: path splits key + val := tval.GetPath([]string{key}) + mvalf, err := d.valueFromToml(mtype.Elem(), val) + if err != nil { + return mval, formatError(err, tval.GetPosition(key)) + } + mval.SetMapIndex(reflect.ValueOf(key), mvalf) + } + } + return mval, nil +} + +// Convert toml value to marshal struct/map slice, using marshal type +func (d *Decoder) valueFromTreeSlice(mtype reflect.Type, tval []*Tree) (reflect.Value, error) { + mval := reflect.MakeSlice(mtype, len(tval), len(tval)) + for i := 0; i < len(tval); i++ { + val, err := d.valueFromTree(mtype.Elem(), tval[i]) + if err != nil { + return mval, err + } + mval.Index(i).Set(val) + } + return mval, nil +} + +// Convert toml value to marshal primitive slice, using marshal type +func (d *Decoder) valueFromOtherSlice(mtype reflect.Type, tval []interface{}) (reflect.Value, error) { + mval := reflect.MakeSlice(mtype, len(tval), len(tval)) + for i := 0; i < len(tval); i++ { + val, err := d.valueFromToml(mtype.Elem(), tval[i]) + if err != nil { + return mval, err + } + mval.Index(i).Set(val) + } + return mval, nil +} + +// Convert toml value to marshal value, using marshal type +func (d *Decoder) valueFromToml(mtype reflect.Type, tval interface{}) (reflect.Value, error) { + if mtype.Kind() == reflect.Ptr { + return d.unwrapPointer(mtype, tval) + } + + switch tval.(type) { + case *Tree: + if isTree(mtype) { + return d.valueFromTree(mtype, tval.(*Tree)) + } + return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to a tree", tval, tval) + case []*Tree: + if isTreeSlice(mtype) { + return d.valueFromTreeSlice(mtype, tval.([]*Tree)) + } + return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to trees", tval, tval) + case []interface{}: + if isOtherSlice(mtype) { + return d.valueFromOtherSlice(mtype, tval.([]interface{})) + } + return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to a slice", tval, tval) + default: + switch mtype.Kind() { + case reflect.Bool, reflect.Struct: + val := reflect.ValueOf(tval) + // if this passes for when mtype is reflect.Struct, tval is a time.Time + if !val.Type().ConvertibleTo(mtype) { + return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v", tval, tval, mtype.String()) + } + + return val.Convert(mtype), nil + case reflect.String: + val := reflect.ValueOf(tval) + // stupidly, int64 is convertible to string. So special case this. + if !val.Type().ConvertibleTo(mtype) || val.Kind() == reflect.Int64 { + return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v", tval, tval, mtype.String()) + } + + return val.Convert(mtype), nil + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + val := reflect.ValueOf(tval) + if !val.Type().ConvertibleTo(mtype) { + return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v", tval, tval, mtype.String()) + } + if reflect.Indirect(reflect.New(mtype)).OverflowInt(val.Int()) { + return reflect.ValueOf(nil), fmt.Errorf("%v(%T) would overflow %v", tval, tval, mtype.String()) + } + + return val.Convert(mtype), nil + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + val := reflect.ValueOf(tval) + if !val.Type().ConvertibleTo(mtype) { + return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v", tval, tval, mtype.String()) + } + if val.Int() < 0 { + return reflect.ValueOf(nil), fmt.Errorf("%v(%T) is negative so does not fit in %v", tval, tval, mtype.String()) + } + if reflect.Indirect(reflect.New(mtype)).OverflowUint(uint64(val.Int())) { + return reflect.ValueOf(nil), fmt.Errorf("%v(%T) would overflow %v", tval, tval, mtype.String()) + } + + return val.Convert(mtype), nil + case reflect.Float32, reflect.Float64: + val := reflect.ValueOf(tval) + if !val.Type().ConvertibleTo(mtype) { + return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v", tval, tval, mtype.String()) + } + if reflect.Indirect(reflect.New(mtype)).OverflowFloat(val.Float()) { + return reflect.ValueOf(nil), fmt.Errorf("%v(%T) would overflow %v", tval, tval, mtype.String()) + } + + return val.Convert(mtype), nil + default: + return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v(%v)", tval, tval, mtype, mtype.Kind()) + } + } +} + +func (d *Decoder) unwrapPointer(mtype reflect.Type, tval interface{}) (reflect.Value, error) { + val, err := d.valueFromToml(mtype.Elem(), tval) + if err != nil { + return reflect.ValueOf(nil), err + } + mval := reflect.New(mtype.Elem()) + mval.Elem().Set(val) + return mval, nil +} + +func tomlOptions(vf reflect.StructField) tomlOpts { + tag := vf.Tag.Get("toml") + parse := strings.Split(tag, ",") + var comment string + if c := vf.Tag.Get("comment"); c != "" { + comment = c + } + commented, _ := strconv.ParseBool(vf.Tag.Get("commented")) + result := tomlOpts{name: vf.Name, comment: comment, commented: commented, include: true, omitempty: false} + if parse[0] != "" { + if parse[0] == "-" && len(parse) == 1 { + result.include = false + } else { + result.name = strings.Trim(parse[0], " ") + } + } + if vf.PkgPath != "" { + result.include = false + } + if len(parse) > 1 && strings.Trim(parse[1], " ") == "omitempty" { + result.omitempty = true + } + if vf.Type.Kind() == reflect.Ptr { + result.omitempty = true + } + return result +} + +func isZero(val reflect.Value) bool { + switch val.Type().Kind() { + case reflect.Map: + fallthrough + case reflect.Array: + fallthrough + case reflect.Slice: + return val.Len() == 0 + default: + return reflect.DeepEqual(val.Interface(), reflect.Zero(val.Type()).Interface()) + } +} + +func formatError(err error, pos Position) error { + if err.Error()[0] == '(' { // Error already contains position information + return err + } + return fmt.Errorf("%s: %s", pos, err) +} diff --git a/vendor/github.com/pelletier/go-toml/marshal_test.go b/vendor/github.com/pelletier/go-toml/marshal_test.go new file mode 100644 index 00000000..291a80d2 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/marshal_test.go @@ -0,0 +1,806 @@ +package toml + +import ( + "bytes" + "encoding/json" + "fmt" + "io/ioutil" + "reflect" + "strings" + "testing" + "time" +) + +type basicMarshalTestStruct struct { + String string `toml:"string"` + StringList []string `toml:"strlist"` + Sub basicMarshalTestSubStruct `toml:"subdoc"` + SubList []basicMarshalTestSubStruct `toml:"sublist"` +} + +type basicMarshalTestSubStruct struct { + String2 string +} + +var basicTestData = basicMarshalTestStruct{ + String: "Hello", + StringList: []string{"Howdy", "Hey There"}, + Sub: basicMarshalTestSubStruct{"One"}, + SubList: []basicMarshalTestSubStruct{{"Two"}, {"Three"}}, +} + +var basicTestToml = []byte(`string = "Hello" +strlist = ["Howdy","Hey There"] + +[subdoc] + String2 = "One" + +[[sublist]] + String2 = "Two" + +[[sublist]] + String2 = "Three" +`) + +func TestBasicMarshal(t *testing.T) { + result, err := Marshal(basicTestData) + if err != nil { + t.Fatal(err) + } + expected := basicTestToml + if !bytes.Equal(result, expected) { + t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result) + } +} + +func TestBasicUnmarshal(t *testing.T) { + result := basicMarshalTestStruct{} + err := Unmarshal(basicTestToml, &result) + expected := basicTestData + if err != nil { + t.Fatal(err) + } + if !reflect.DeepEqual(result, expected) { + t.Errorf("Bad unmarshal: expected %v, got %v", expected, result) + } +} + +type testDoc struct { + Title string `toml:"title"` + Basics testDocBasics `toml:"basic"` + BasicLists testDocBasicLists `toml:"basic_lists"` + BasicMap map[string]string `toml:"basic_map"` + Subdocs testDocSubs `toml:"subdoc"` + SubDocList []testSubDoc `toml:"subdoclist"` + SubDocPtrs []*testSubDoc `toml:"subdocptrs"` + err int `toml:"shouldntBeHere"` + unexported int `toml:"shouldntBeHere"` + Unexported2 int `toml:"-"` +} + +type testDocBasics struct { + Bool bool `toml:"bool"` + Date time.Time `toml:"date"` + Float float32 `toml:"float"` + Int int `toml:"int"` + Uint uint `toml:"uint"` + String *string `toml:"string"` + unexported int `toml:"shouldntBeHere"` +} + +type testDocBasicLists struct { + Bools []bool `toml:"bools"` + Dates []time.Time `toml:"dates"` + Floats []*float32 `toml:"floats"` + Ints []int `toml:"ints"` + Strings []string `toml:"strings"` + UInts []uint `toml:"uints"` +} + +type testDocSubs struct { + First testSubDoc `toml:"first"` + Second *testSubDoc `toml:"second"` +} + +type testSubDoc struct { + Name string `toml:"name"` + unexported int `toml:"shouldntBeHere"` +} + +var biteMe = "Bite me" +var float1 float32 = 12.3 +var float2 float32 = 45.6 +var float3 float32 = 78.9 +var subdoc = testSubDoc{"Second", 0} + +var docData = testDoc{ + Title: "TOML Marshal Testing", + unexported: 0, + Unexported2: 0, + Basics: testDocBasics{ + Bool: true, + Date: time.Date(1979, 5, 27, 7, 32, 0, 0, time.UTC), + Float: 123.4, + Int: 5000, + Uint: 5001, + String: &biteMe, + unexported: 0, + }, + BasicLists: testDocBasicLists{ + Bools: []bool{true, false, true}, + Dates: []time.Time{ + time.Date(1979, 5, 27, 7, 32, 0, 0, time.UTC), + time.Date(1980, 5, 27, 7, 32, 0, 0, time.UTC), + }, + Floats: []*float32{&float1, &float2, &float3}, + Ints: []int{8001, 8001, 8002}, + Strings: []string{"One", "Two", "Three"}, + UInts: []uint{5002, 5003}, + }, + BasicMap: map[string]string{ + "one": "one", + "two": "two", + }, + Subdocs: testDocSubs{ + First: testSubDoc{"First", 0}, + Second: &subdoc, + }, + SubDocList: []testSubDoc{ + {"List.First", 0}, + {"List.Second", 0}, + }, + SubDocPtrs: []*testSubDoc{&subdoc}, +} + +func TestDocMarshal(t *testing.T) { + result, err := Marshal(docData) + if err != nil { + t.Fatal(err) + } + expected, _ := ioutil.ReadFile("marshal_test.toml") + if !bytes.Equal(result, expected) { + t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result) + } +} + +func TestDocUnmarshal(t *testing.T) { + result := testDoc{} + tomlData, _ := ioutil.ReadFile("marshal_test.toml") + err := Unmarshal(tomlData, &result) + expected := docData + if err != nil { + t.Fatal(err) + } + if !reflect.DeepEqual(result, expected) { + resStr, _ := json.MarshalIndent(result, "", " ") + expStr, _ := json.MarshalIndent(expected, "", " ") + t.Errorf("Bad unmarshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expStr, resStr) + } +} + +func TestDocPartialUnmarshal(t *testing.T) { + result := testDocSubs{} + + tree, _ := LoadFile("marshal_test.toml") + subTree := tree.Get("subdoc").(*Tree) + err := subTree.Unmarshal(&result) + expected := docData.Subdocs + if err != nil { + t.Fatal(err) + } + if !reflect.DeepEqual(result, expected) { + resStr, _ := json.MarshalIndent(result, "", " ") + expStr, _ := json.MarshalIndent(expected, "", " ") + t.Errorf("Bad partial unmartial: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expStr, resStr) + } +} + +type tomlTypeCheckTest struct { + name string + item interface{} + typ int //0=primitive, 1=otherslice, 2=treeslice, 3=tree +} + +func TestTypeChecks(t *testing.T) { + tests := []tomlTypeCheckTest{ + {"integer", 2, 0}, + {"time", time.Date(2015, 1, 1, 0, 0, 0, 0, time.UTC), 0}, + {"stringlist", []string{"hello", "hi"}, 1}, + {"timelist", []time.Time{time.Date(2015, 1, 1, 0, 0, 0, 0, time.UTC)}, 1}, + {"objectlist", []tomlTypeCheckTest{}, 2}, + {"object", tomlTypeCheckTest{}, 3}, + } + + for _, test := range tests { + expected := []bool{false, false, false, false} + expected[test.typ] = true + result := []bool{ + isPrimitive(reflect.TypeOf(test.item)), + isOtherSlice(reflect.TypeOf(test.item)), + isTreeSlice(reflect.TypeOf(test.item)), + isTree(reflect.TypeOf(test.item)), + } + if !reflect.DeepEqual(expected, result) { + t.Errorf("Bad type check on %q: expected %v, got %v", test.name, expected, result) + } + } +} + +type unexportedMarshalTestStruct struct { + String string `toml:"string"` + StringList []string `toml:"strlist"` + Sub basicMarshalTestSubStruct `toml:"subdoc"` + SubList []basicMarshalTestSubStruct `toml:"sublist"` + unexported int `toml:"shouldntBeHere"` + Unexported2 int `toml:"-"` +} + +var unexportedTestData = unexportedMarshalTestStruct{ + String: "Hello", + StringList: []string{"Howdy", "Hey There"}, + Sub: basicMarshalTestSubStruct{"One"}, + SubList: []basicMarshalTestSubStruct{{"Two"}, {"Three"}}, + unexported: 0, + Unexported2: 0, +} + +var unexportedTestToml = []byte(`string = "Hello" +strlist = ["Howdy","Hey There"] +unexported = 1 +shouldntBeHere = 2 + +[subdoc] + String2 = "One" + +[[sublist]] + String2 = "Two" + +[[sublist]] + String2 = "Three" +`) + +func TestUnexportedUnmarshal(t *testing.T) { + result := unexportedMarshalTestStruct{} + err := Unmarshal(unexportedTestToml, &result) + expected := unexportedTestData + if err != nil { + t.Fatal(err) + } + if !reflect.DeepEqual(result, expected) { + t.Errorf("Bad unexported unmarshal: expected %v, got %v", expected, result) + } +} + +type errStruct struct { + Bool bool `toml:"bool"` + Date time.Time `toml:"date"` + Float float64 `toml:"float"` + Int int16 `toml:"int"` + String *string `toml:"string"` +} + +var errTomls = []string{ + "bool = truly\ndate = 1979-05-27T07:32:00Z\nfloat = 123.4\nint = 5000\nstring = \"Bite me\"", + "bool = true\ndate = 1979-05-27T07:3200Z\nfloat = 123.4\nint = 5000\nstring = \"Bite me\"", + "bool = true\ndate = 1979-05-27T07:32:00Z\nfloat = 123a4\nint = 5000\nstring = \"Bite me\"", + "bool = true\ndate = 1979-05-27T07:32:00Z\nfloat = 123.4\nint = j000\nstring = \"Bite me\"", + "bool = true\ndate = 1979-05-27T07:32:00Z\nfloat = 123.4\nint = 5000\nstring = Bite me", + "bool = true\ndate = 1979-05-27T07:32:00Z\nfloat = 123.4\nint = 5000\nstring = Bite me", + "bool = 1\ndate = 1979-05-27T07:32:00Z\nfloat = 123.4\nint = 5000\nstring = \"Bite me\"", + "bool = true\ndate = 1\nfloat = 123.4\nint = 5000\nstring = \"Bite me\"", + "bool = true\ndate = 1979-05-27T07:32:00Z\n\"sorry\"\nint = 5000\nstring = \"Bite me\"", + "bool = true\ndate = 1979-05-27T07:32:00Z\nfloat = 123.4\nint = \"sorry\"\nstring = \"Bite me\"", + "bool = true\ndate = 1979-05-27T07:32:00Z\nfloat = 123.4\nint = 5000\nstring = 1", +} + +type mapErr struct { + Vals map[string]float64 +} + +type intErr struct { + Int1 int + Int2 int8 + Int3 int16 + Int4 int32 + Int5 int64 + UInt1 uint + UInt2 uint8 + UInt3 uint16 + UInt4 uint32 + UInt5 uint64 + Flt1 float32 + Flt2 float64 +} + +var intErrTomls = []string{ + "Int1 = []\nInt2 = 2\nInt3 = 3\nInt4 = 4\nInt5 = 5\nUInt1 = 1\nUInt2 = 2\nUInt3 = 3\nUInt4 = 4\nUInt5 = 5\nFlt1 = 1.0\nFlt2 = 2.0", + "Int1 = 1\nInt2 = []\nInt3 = 3\nInt4 = 4\nInt5 = 5\nUInt1 = 1\nUInt2 = 2\nUInt3 = 3\nUInt4 = 4\nUInt5 = 5\nFlt1 = 1.0\nFlt2 = 2.0", + "Int1 = 1\nInt2 = 2\nInt3 = []\nInt4 = 4\nInt5 = 5\nUInt1 = 1\nUInt2 = 2\nUInt3 = 3\nUInt4 = 4\nUInt5 = 5\nFlt1 = 1.0\nFlt2 = 2.0", + "Int1 = 1\nInt2 = 2\nInt3 = 3\nInt4 = []\nInt5 = 5\nUInt1 = 1\nUInt2 = 2\nUInt3 = 3\nUInt4 = 4\nUInt5 = 5\nFlt1 = 1.0\nFlt2 = 2.0", + "Int1 = 1\nInt2 = 2\nInt3 = 3\nInt4 = 4\nInt5 = []\nUInt1 = 1\nUInt2 = 2\nUInt3 = 3\nUInt4 = 4\nUInt5 = 5\nFlt1 = 1.0\nFlt2 = 2.0", + "Int1 = 1\nInt2 = 2\nInt3 = 3\nInt4 = 4\nInt5 = 5\nUInt1 = []\nUInt2 = 2\nUInt3 = 3\nUInt4 = 4\nUInt5 = 5\nFlt1 = 1.0\nFlt2 = 2.0", + "Int1 = 1\nInt2 = 2\nInt3 = 3\nInt4 = 4\nInt5 = 5\nUInt1 = 1\nUInt2 = []\nUInt3 = 3\nUInt4 = 4\nUInt5 = 5\nFlt1 = 1.0\nFlt2 = 2.0", + "Int1 = 1\nInt2 = 2\nInt3 = 3\nInt4 = 4\nInt5 = 5\nUInt1 = 1\nUInt2 = 2\nUInt3 = []\nUInt4 = 4\nUInt5 = 5\nFlt1 = 1.0\nFlt2 = 2.0", + "Int1 = 1\nInt2 = 2\nInt3 = 3\nInt4 = 4\nInt5 = 5\nUInt1 = 1\nUInt2 = 2\nUInt3 = 3\nUInt4 = []\nUInt5 = 5\nFlt1 = 1.0\nFlt2 = 2.0", + "Int1 = 1\nInt2 = 2\nInt3 = 3\nInt4 = 4\nInt5 = 5\nUInt1 = 1\nUInt2 = 2\nUInt3 = 3\nUInt4 = 4\nUInt5 = []\nFlt1 = 1.0\nFlt2 = 2.0", + "Int1 = 1\nInt2 = 2\nInt3 = 3\nInt4 = 4\nInt5 = 5\nUInt1 = 1\nUInt2 = 2\nUInt3 = 3\nUInt4 = 4\nUInt5 = 5\nFlt1 = []\nFlt2 = 2.0", + "Int1 = 1\nInt2 = 2\nInt3 = 3\nInt4 = 4\nInt5 = 5\nUInt1 = 1\nUInt2 = 2\nUInt3 = 3\nUInt4 = 4\nUInt5 = 5\nFlt1 = 1.0\nFlt2 = []", +} + +func TestErrUnmarshal(t *testing.T) { + for ind, toml := range errTomls { + result := errStruct{} + err := Unmarshal([]byte(toml), &result) + if err == nil { + t.Errorf("Expected err from case %d\n", ind) + } + } + result2 := mapErr{} + err := Unmarshal([]byte("[Vals]\nfred=\"1.2\""), &result2) + if err == nil { + t.Errorf("Expected err from map") + } + for ind, toml := range intErrTomls { + result3 := intErr{} + err := Unmarshal([]byte(toml), &result3) + if err == nil { + t.Errorf("Expected int err from case %d\n", ind) + } + } +} + +type emptyMarshalTestStruct struct { + Title string `toml:"title"` + Bool bool `toml:"bool"` + Int int `toml:"int"` + String string `toml:"string"` + StringList []string `toml:"stringlist"` + Ptr *basicMarshalTestStruct `toml:"ptr"` + Map map[string]string `toml:"map"` +} + +var emptyTestData = emptyMarshalTestStruct{ + Title: "Placeholder", + Bool: false, + Int: 0, + String: "", + StringList: []string{}, + Ptr: nil, + Map: map[string]string{}, +} + +var emptyTestToml = []byte(`bool = false +int = 0 +string = "" +stringlist = [] +title = "Placeholder" + +[map] +`) + +type emptyMarshalTestStruct2 struct { + Title string `toml:"title"` + Bool bool `toml:"bool,omitempty"` + Int int `toml:"int, omitempty"` + String string `toml:"string,omitempty "` + StringList []string `toml:"stringlist,omitempty"` + Ptr *basicMarshalTestStruct `toml:"ptr,omitempty"` + Map map[string]string `toml:"map,omitempty"` +} + +var emptyTestData2 = emptyMarshalTestStruct2{ + Title: "Placeholder", + Bool: false, + Int: 0, + String: "", + StringList: []string{}, + Ptr: nil, + Map: map[string]string{}, +} + +var emptyTestToml2 = []byte(`title = "Placeholder" +`) + +func TestEmptyMarshal(t *testing.T) { + result, err := Marshal(emptyTestData) + if err != nil { + t.Fatal(err) + } + expected := emptyTestToml + if !bytes.Equal(result, expected) { + t.Errorf("Bad empty marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result) + } +} + +func TestEmptyMarshalOmit(t *testing.T) { + result, err := Marshal(emptyTestData2) + if err != nil { + t.Fatal(err) + } + expected := emptyTestToml2 + if !bytes.Equal(result, expected) { + t.Errorf("Bad empty omit marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result) + } +} + +func TestEmptyUnmarshal(t *testing.T) { + result := emptyMarshalTestStruct{} + err := Unmarshal(emptyTestToml, &result) + expected := emptyTestData + if err != nil { + t.Fatal(err) + } + if !reflect.DeepEqual(result, expected) { + t.Errorf("Bad empty unmarshal: expected %v, got %v", expected, result) + } +} + +func TestEmptyUnmarshalOmit(t *testing.T) { + result := emptyMarshalTestStruct2{} + err := Unmarshal(emptyTestToml, &result) + expected := emptyTestData2 + if err != nil { + t.Fatal(err) + } + if !reflect.DeepEqual(result, expected) { + t.Errorf("Bad empty omit unmarshal: expected %v, got %v", expected, result) + } +} + +type pointerMarshalTestStruct struct { + Str *string + List *[]string + ListPtr *[]*string + Map *map[string]string + MapPtr *map[string]*string + EmptyStr *string + EmptyList *[]string + EmptyMap *map[string]string + DblPtr *[]*[]*string +} + +var pointerStr = "Hello" +var pointerList = []string{"Hello back"} +var pointerListPtr = []*string{&pointerStr} +var pointerMap = map[string]string{"response": "Goodbye"} +var pointerMapPtr = map[string]*string{"alternate": &pointerStr} +var pointerTestData = pointerMarshalTestStruct{ + Str: &pointerStr, + List: &pointerList, + ListPtr: &pointerListPtr, + Map: &pointerMap, + MapPtr: &pointerMapPtr, + EmptyStr: nil, + EmptyList: nil, + EmptyMap: nil, +} + +var pointerTestToml = []byte(`List = ["Hello back"] +ListPtr = ["Hello"] +Str = "Hello" + +[Map] + response = "Goodbye" + +[MapPtr] + alternate = "Hello" +`) + +func TestPointerMarshal(t *testing.T) { + result, err := Marshal(pointerTestData) + if err != nil { + t.Fatal(err) + } + expected := pointerTestToml + if !bytes.Equal(result, expected) { + t.Errorf("Bad pointer marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result) + } +} + +func TestPointerUnmarshal(t *testing.T) { + result := pointerMarshalTestStruct{} + err := Unmarshal(pointerTestToml, &result) + expected := pointerTestData + if err != nil { + t.Fatal(err) + } + if !reflect.DeepEqual(result, expected) { + t.Errorf("Bad pointer unmarshal: expected %v, got %v", expected, result) + } +} + +func TestUnmarshalTypeMismatch(t *testing.T) { + result := pointerMarshalTestStruct{} + err := Unmarshal([]byte("List = 123"), &result) + if !strings.HasPrefix(err.Error(), "(1, 1): Can't convert 123(int64) to []string(slice)") { + t.Errorf("Type mismatch must be reported: got %v", err.Error()) + } +} + +type nestedMarshalTestStruct struct { + String [][]string + //Struct [][]basicMarshalTestSubStruct + StringPtr *[]*[]*string + // StructPtr *[]*[]*basicMarshalTestSubStruct +} + +var str1 = "Three" +var str2 = "Four" +var strPtr = []*string{&str1, &str2} +var strPtr2 = []*[]*string{&strPtr} + +var nestedTestData = nestedMarshalTestStruct{ + String: [][]string{{"Five", "Six"}, {"One", "Two"}}, + StringPtr: &strPtr2, +} + +var nestedTestToml = []byte(`String = [["Five","Six"],["One","Two"]] +StringPtr = [["Three","Four"]] +`) + +func TestNestedMarshal(t *testing.T) { + result, err := Marshal(nestedTestData) + if err != nil { + t.Fatal(err) + } + expected := nestedTestToml + if !bytes.Equal(result, expected) { + t.Errorf("Bad nested marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result) + } +} + +func TestNestedUnmarshal(t *testing.T) { + result := nestedMarshalTestStruct{} + err := Unmarshal(nestedTestToml, &result) + expected := nestedTestData + if err != nil { + t.Fatal(err) + } + if !reflect.DeepEqual(result, expected) { + t.Errorf("Bad nested unmarshal: expected %v, got %v", expected, result) + } +} + +type customMarshalerParent struct { + Self customMarshaler `toml:"me"` + Friends []customMarshaler `toml:"friends"` +} + +type customMarshaler struct { + FirsName string + LastName string +} + +func (c customMarshaler) MarshalTOML() ([]byte, error) { + fullName := fmt.Sprintf("%s %s", c.FirsName, c.LastName) + return []byte(fullName), nil +} + +var customMarshalerData = customMarshaler{FirsName: "Sally", LastName: "Fields"} +var customMarshalerToml = []byte(`Sally Fields`) +var nestedCustomMarshalerData = customMarshalerParent{ + Self: customMarshaler{FirsName: "Maiku", LastName: "Suteda"}, + Friends: []customMarshaler{customMarshalerData}, +} +var nestedCustomMarshalerToml = []byte(`friends = ["Sally Fields"] +me = "Maiku Suteda" +`) + +func TestCustomMarshaler(t *testing.T) { + result, err := Marshal(customMarshalerData) + if err != nil { + t.Fatal(err) + } + expected := customMarshalerToml + if !bytes.Equal(result, expected) { + t.Errorf("Bad custom marshaler: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result) + } +} + +func TestNestedCustomMarshaler(t *testing.T) { + result, err := Marshal(nestedCustomMarshalerData) + if err != nil { + t.Fatal(err) + } + expected := nestedCustomMarshalerToml + if !bytes.Equal(result, expected) { + t.Errorf("Bad nested custom marshaler: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result) + } +} + +var commentTestToml = []byte(` +# it's a comment on type +[postgres] + # isCommented = "dvalue" + noComment = "cvalue" + + # A comment on AttrB with a + # break line + password = "bvalue" + + # A comment on AttrA + user = "avalue" + + [[postgres.My]] + + # a comment on my on typeC + My = "Foo" + + [[postgres.My]] + + # a comment on my on typeC + My = "Baar" +`) + +func TestMarshalComment(t *testing.T) { + type TypeC struct { + My string `comment:"a comment on my on typeC"` + } + type TypeB struct { + AttrA string `toml:"user" comment:"A comment on AttrA"` + AttrB string `toml:"password" comment:"A comment on AttrB with a\n break line"` + AttrC string `toml:"noComment"` + AttrD string `toml:"isCommented" commented:"true"` + My []TypeC + } + type TypeA struct { + TypeB TypeB `toml:"postgres" comment:"it's a comment on type"` + } + + ta := []TypeC{{My: "Foo"}, {My: "Baar"}} + config := TypeA{TypeB{AttrA: "avalue", AttrB: "bvalue", AttrC: "cvalue", AttrD: "dvalue", My: ta}} + result, err := Marshal(config) + if err != nil { + t.Fatal(err) + } + expected := commentTestToml + if !bytes.Equal(result, expected) { + t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result) + } +} + +type mapsTestStruct struct { + Simple map[string]string + Paths map[string]string + Other map[string]float64 + X struct { + Y struct { + Z map[string]bool + } + } +} + +var mapsTestData = mapsTestStruct{ + Simple: map[string]string{ + "one plus one": "two", + "next": "three", + }, + Paths: map[string]string{ + "/this/is/a/path": "/this/is/also/a/path", + "/heloo.txt": "/tmp/lololo.txt", + }, + Other: map[string]float64{ + "testing": 3.9999, + }, + X: struct{ Y struct{ Z map[string]bool } }{ + Y: struct{ Z map[string]bool }{ + Z: map[string]bool{ + "is.Nested": true, + }, + }, + }, +} +var mapsTestToml = []byte(` +[Other] + "testing" = 3.9999 + +[Paths] + "/heloo.txt" = "/tmp/lololo.txt" + "/this/is/a/path" = "/this/is/also/a/path" + +[Simple] + "next" = "three" + "one plus one" = "two" + +[X] + + [X.Y] + + [X.Y.Z] + "is.Nested" = true +`) + +func TestEncodeQuotedMapKeys(t *testing.T) { + var buf bytes.Buffer + if err := NewEncoder(&buf).QuoteMapKeys(true).Encode(mapsTestData); err != nil { + t.Fatal(err) + } + result := buf.Bytes() + expected := mapsTestToml + if !bytes.Equal(result, expected) { + t.Errorf("Bad maps marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result) + } +} + +func TestDecodeQuotedMapKeys(t *testing.T) { + result := mapsTestStruct{} + err := NewDecoder(bytes.NewBuffer(mapsTestToml)).Decode(&result) + expected := mapsTestData + if err != nil { + t.Fatal(err) + } + if !reflect.DeepEqual(result, expected) { + t.Errorf("Bad maps unmarshal: expected %v, got %v", expected, result) + } +} + +type structArrayNoTag struct { + A struct { + B []int64 + C []int64 + } +} + +func TestMarshalArray(t *testing.T) { + expected := []byte(` +[A] + B = [1,2,3] + C = [1] +`) + + m := structArrayNoTag{ + A: struct { + B []int64 + C []int64 + }{ + B: []int64{1, 2, 3}, + C: []int64{1}, + }, + } + + b, err := Marshal(m) + + if err != nil { + t.Fatal(err) + } + + if !bytes.Equal(b, expected) { + t.Errorf("Bad arrays marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, b) + } +} + +func TestMarshalArrayOnePerLine(t *testing.T) { + expected := []byte(` +[A] + B = [ + 1, + 2, + 3 + ] + C = [1] +`) + + m := structArrayNoTag{ + A: struct { + B []int64 + C []int64 + }{ + B: []int64{1, 2, 3}, + C: []int64{1}, + }, + } + + var buf bytes.Buffer + encoder := NewEncoder(&buf).ArraysWithOneElementPerLine(true) + err := encoder.Encode(m) + + if err != nil { + t.Fatal(err) + } + + b := buf.Bytes() + + if !bytes.Equal(b, expected) { + t.Errorf("Bad arrays marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, b) + } +} diff --git a/vendor/github.com/pelletier/go-toml/marshal_test.toml b/vendor/github.com/pelletier/go-toml/marshal_test.toml new file mode 100644 index 00000000..1c5f98e7 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/marshal_test.toml @@ -0,0 +1,38 @@ +title = "TOML Marshal Testing" + +[basic] + bool = true + date = 1979-05-27T07:32:00Z + float = 123.4 + int = 5000 + string = "Bite me" + uint = 5001 + +[basic_lists] + bools = [true,false,true] + dates = [1979-05-27T07:32:00Z,1980-05-27T07:32:00Z] + floats = [12.3,45.6,78.9] + ints = [8001,8001,8002] + strings = ["One","Two","Three"] + uints = [5002,5003] + +[basic_map] + one = "one" + two = "two" + +[subdoc] + + [subdoc.first] + name = "First" + + [subdoc.second] + name = "Second" + +[[subdoclist]] + name = "List.First" + +[[subdoclist]] + name = "List.Second" + +[[subdocptrs]] + name = "Second" diff --git a/vendor/github.com/pelletier/go-toml/parser.go b/vendor/github.com/pelletier/go-toml/parser.go new file mode 100644 index 00000000..2d27599a --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/parser.go @@ -0,0 +1,430 @@ +// TOML Parser. + +package toml + +import ( + "errors" + "fmt" + "math" + "reflect" + "regexp" + "strconv" + "strings" + "time" +) + +type tomlParser struct { + flowIdx int + flow []token + tree *Tree + currentTable []string + seenTableKeys []string +} + +type tomlParserStateFn func() tomlParserStateFn + +// Formats and panics an error message based on a token +func (p *tomlParser) raiseError(tok *token, msg string, args ...interface{}) { + panic(tok.Position.String() + ": " + fmt.Sprintf(msg, args...)) +} + +func (p *tomlParser) run() { + for state := p.parseStart; state != nil; { + state = state() + } +} + +func (p *tomlParser) peek() *token { + if p.flowIdx >= len(p.flow) { + return nil + } + return &p.flow[p.flowIdx] +} + +func (p *tomlParser) assume(typ tokenType) { + tok := p.getToken() + if tok == nil { + p.raiseError(tok, "was expecting token %s, but token stream is empty", tok) + } + if tok.typ != typ { + p.raiseError(tok, "was expecting token %s, but got %s instead", typ, tok) + } +} + +func (p *tomlParser) getToken() *token { + tok := p.peek() + if tok == nil { + return nil + } + p.flowIdx++ + return tok +} + +func (p *tomlParser) parseStart() tomlParserStateFn { + tok := p.peek() + + // end of stream, parsing is finished + if tok == nil { + return nil + } + + switch tok.typ { + case tokenDoubleLeftBracket: + return p.parseGroupArray + case tokenLeftBracket: + return p.parseGroup + case tokenKey: + return p.parseAssign + case tokenEOF: + return nil + default: + p.raiseError(tok, "unexpected token") + } + return nil +} + +func (p *tomlParser) parseGroupArray() tomlParserStateFn { + startToken := p.getToken() // discard the [[ + key := p.getToken() + if key.typ != tokenKeyGroupArray { + p.raiseError(key, "unexpected token %s, was expecting a table array key", key) + } + + // get or create table array element at the indicated part in the path + keys, err := parseKey(key.val) + if err != nil { + p.raiseError(key, "invalid table array key: %s", err) + } + p.tree.createSubTree(keys[:len(keys)-1], startToken.Position) // create parent entries + destTree := p.tree.GetPath(keys) + var array []*Tree + if destTree == nil { + array = make([]*Tree, 0) + } else if target, ok := destTree.([]*Tree); ok && target != nil { + array = destTree.([]*Tree) + } else { + p.raiseError(key, "key %s is already assigned and not of type table array", key) + } + p.currentTable = keys + + // add a new tree to the end of the table array + newTree := newTree() + newTree.position = startToken.Position + array = append(array, newTree) + p.tree.SetPath(p.currentTable, array) + + // remove all keys that were children of this table array + prefix := key.val + "." + found := false + for ii := 0; ii < len(p.seenTableKeys); { + tableKey := p.seenTableKeys[ii] + if strings.HasPrefix(tableKey, prefix) { + p.seenTableKeys = append(p.seenTableKeys[:ii], p.seenTableKeys[ii+1:]...) + } else { + found = (tableKey == key.val) + ii++ + } + } + + // keep this key name from use by other kinds of assignments + if !found { + p.seenTableKeys = append(p.seenTableKeys, key.val) + } + + // move to next parser state + p.assume(tokenDoubleRightBracket) + return p.parseStart +} + +func (p *tomlParser) parseGroup() tomlParserStateFn { + startToken := p.getToken() // discard the [ + key := p.getToken() + if key.typ != tokenKeyGroup { + p.raiseError(key, "unexpected token %s, was expecting a table key", key) + } + for _, item := range p.seenTableKeys { + if item == key.val { + p.raiseError(key, "duplicated tables") + } + } + + p.seenTableKeys = append(p.seenTableKeys, key.val) + keys, err := parseKey(key.val) + if err != nil { + p.raiseError(key, "invalid table array key: %s", err) + } + if err := p.tree.createSubTree(keys, startToken.Position); err != nil { + p.raiseError(key, "%s", err) + } + p.assume(tokenRightBracket) + p.currentTable = keys + return p.parseStart +} + +func (p *tomlParser) parseAssign() tomlParserStateFn { + key := p.getToken() + p.assume(tokenEqual) + + value := p.parseRvalue() + var tableKey []string + if len(p.currentTable) > 0 { + tableKey = p.currentTable + } else { + tableKey = []string{} + } + + // find the table to assign, looking out for arrays of tables + var targetNode *Tree + switch node := p.tree.GetPath(tableKey).(type) { + case []*Tree: + targetNode = node[len(node)-1] + case *Tree: + targetNode = node + default: + p.raiseError(key, "Unknown table type for path: %s", + strings.Join(tableKey, ".")) + } + + // assign value to the found table + keyVals := []string{key.val} + if len(keyVals) != 1 { + p.raiseError(key, "Invalid key") + } + keyVal := keyVals[0] + localKey := []string{keyVal} + finalKey := append(tableKey, keyVal) + if targetNode.GetPath(localKey) != nil { + p.raiseError(key, "The following key was defined twice: %s", + strings.Join(finalKey, ".")) + } + var toInsert interface{} + + switch value.(type) { + case *Tree, []*Tree: + toInsert = value + default: + toInsert = &tomlValue{value: value, position: key.Position} + } + targetNode.values[keyVal] = toInsert + return p.parseStart +} + +var numberUnderscoreInvalidRegexp *regexp.Regexp +var hexNumberUnderscoreInvalidRegexp *regexp.Regexp + +func numberContainsInvalidUnderscore(value string) error { + if numberUnderscoreInvalidRegexp.MatchString(value) { + return errors.New("invalid use of _ in number") + } + return nil +} + +func hexNumberContainsInvalidUnderscore(value string) error { + if hexNumberUnderscoreInvalidRegexp.MatchString(value) { + return errors.New("invalid use of _ in hex number") + } + return nil +} + +func cleanupNumberToken(value string) string { + cleanedVal := strings.Replace(value, "_", "", -1) + return cleanedVal +} + +func (p *tomlParser) parseRvalue() interface{} { + tok := p.getToken() + if tok == nil || tok.typ == tokenEOF { + p.raiseError(tok, "expecting a value") + } + + switch tok.typ { + case tokenString: + return tok.val + case tokenTrue: + return true + case tokenFalse: + return false + case tokenInf: + if tok.val[0] == '-' { + return math.Inf(-1) + } + return math.Inf(1) + case tokenNan: + return math.NaN() + case tokenInteger: + cleanedVal := cleanupNumberToken(tok.val) + var err error + var val int64 + if len(cleanedVal) >= 3 && cleanedVal[0] == '0' { + switch cleanedVal[1] { + case 'x': + err = hexNumberContainsInvalidUnderscore(tok.val) + if err != nil { + p.raiseError(tok, "%s", err) + } + val, err = strconv.ParseInt(cleanedVal[2:], 16, 64) + case 'o': + err = numberContainsInvalidUnderscore(tok.val) + if err != nil { + p.raiseError(tok, "%s", err) + } + val, err = strconv.ParseInt(cleanedVal[2:], 8, 64) + case 'b': + err = numberContainsInvalidUnderscore(tok.val) + if err != nil { + p.raiseError(tok, "%s", err) + } + val, err = strconv.ParseInt(cleanedVal[2:], 2, 64) + default: + panic("invalid base") // the lexer should catch this first + } + } else { + err = numberContainsInvalidUnderscore(tok.val) + if err != nil { + p.raiseError(tok, "%s", err) + } + val, err = strconv.ParseInt(cleanedVal, 10, 64) + } + if err != nil { + p.raiseError(tok, "%s", err) + } + return val + case tokenFloat: + err := numberContainsInvalidUnderscore(tok.val) + if err != nil { + p.raiseError(tok, "%s", err) + } + cleanedVal := cleanupNumberToken(tok.val) + val, err := strconv.ParseFloat(cleanedVal, 64) + if err != nil { + p.raiseError(tok, "%s", err) + } + return val + case tokenDate: + val, err := time.ParseInLocation(time.RFC3339Nano, tok.val, time.UTC) + if err != nil { + p.raiseError(tok, "%s", err) + } + return val + case tokenLeftBracket: + return p.parseArray() + case tokenLeftCurlyBrace: + return p.parseInlineTable() + case tokenEqual: + p.raiseError(tok, "cannot have multiple equals for the same key") + case tokenError: + p.raiseError(tok, "%s", tok) + } + + p.raiseError(tok, "never reached") + + return nil +} + +func tokenIsComma(t *token) bool { + return t != nil && t.typ == tokenComma +} + +func (p *tomlParser) parseInlineTable() *Tree { + tree := newTree() + var previous *token +Loop: + for { + follow := p.peek() + if follow == nil || follow.typ == tokenEOF { + p.raiseError(follow, "unterminated inline table") + } + switch follow.typ { + case tokenRightCurlyBrace: + p.getToken() + break Loop + case tokenKey: + if !tokenIsComma(previous) && previous != nil { + p.raiseError(follow, "comma expected between fields in inline table") + } + key := p.getToken() + p.assume(tokenEqual) + value := p.parseRvalue() + tree.Set(key.val, value) + case tokenComma: + if previous == nil { + p.raiseError(follow, "inline table cannot start with a comma") + } + if tokenIsComma(previous) { + p.raiseError(follow, "need field between two commas in inline table") + } + p.getToken() + default: + p.raiseError(follow, "unexpected token type in inline table: %s", follow.String()) + } + previous = follow + } + if tokenIsComma(previous) { + p.raiseError(previous, "trailing comma at the end of inline table") + } + return tree +} + +func (p *tomlParser) parseArray() interface{} { + var array []interface{} + arrayType := reflect.TypeOf(nil) + for { + follow := p.peek() + if follow == nil || follow.typ == tokenEOF { + p.raiseError(follow, "unterminated array") + } + if follow.typ == tokenRightBracket { + p.getToken() + break + } + val := p.parseRvalue() + if arrayType == nil { + arrayType = reflect.TypeOf(val) + } + if reflect.TypeOf(val) != arrayType { + p.raiseError(follow, "mixed types in array") + } + array = append(array, val) + follow = p.peek() + if follow == nil || follow.typ == tokenEOF { + p.raiseError(follow, "unterminated array") + } + if follow.typ != tokenRightBracket && follow.typ != tokenComma { + p.raiseError(follow, "missing comma") + } + if follow.typ == tokenComma { + p.getToken() + } + } + // An array of Trees is actually an array of inline + // tables, which is a shorthand for a table array. If the + // array was not converted from []interface{} to []*Tree, + // the two notations would not be equivalent. + if arrayType == reflect.TypeOf(newTree()) { + tomlArray := make([]*Tree, len(array)) + for i, v := range array { + tomlArray[i] = v.(*Tree) + } + return tomlArray + } + return array +} + +func parseToml(flow []token) *Tree { + result := newTree() + result.position = Position{1, 1} + parser := &tomlParser{ + flowIdx: 0, + flow: flow, + tree: result, + currentTable: make([]string, 0), + seenTableKeys: make([]string, 0), + } + parser.run() + return result +} + +func init() { + numberUnderscoreInvalidRegexp = regexp.MustCompile(`([^\d]_|_[^\d])|_$|^_`) + hexNumberUnderscoreInvalidRegexp = regexp.MustCompile(`(^0x_)|([^\da-f]_|_[^\da-f])|_$|^_`) +} diff --git a/vendor/github.com/pelletier/go-toml/parser_test.go b/vendor/github.com/pelletier/go-toml/parser_test.go new file mode 100644 index 00000000..ca29c442 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/parser_test.go @@ -0,0 +1,899 @@ +package toml + +import ( + "fmt" + "math" + "reflect" + "testing" + "time" + + "github.com/davecgh/go-spew/spew" +) + +func assertSubTree(t *testing.T, path []string, tree *Tree, err error, ref map[string]interface{}) { + if err != nil { + t.Error("Non-nil error:", err.Error()) + return + } + for k, v := range ref { + nextPath := append(path, k) + t.Log("asserting path", nextPath) + // NOTE: directly access key instead of resolve by path + // NOTE: see TestSpecialKV + switch node := tree.GetPath([]string{k}).(type) { + case []*Tree: + t.Log("\tcomparing key", nextPath, "by array iteration") + for idx, item := range node { + assertSubTree(t, nextPath, item, err, v.([]map[string]interface{})[idx]) + } + case *Tree: + t.Log("\tcomparing key", nextPath, "by subtree assestion") + assertSubTree(t, nextPath, node, err, v.(map[string]interface{})) + default: + t.Log("\tcomparing key", nextPath, "by string representation because it's of type", reflect.TypeOf(node)) + if fmt.Sprintf("%v", node) != fmt.Sprintf("%v", v) { + t.Errorf("was expecting %v at %v but got %v", v, k, node) + } + } + } +} + +func assertTree(t *testing.T, tree *Tree, err error, ref map[string]interface{}) { + t.Log("Asserting tree:\n", spew.Sdump(tree)) + assertSubTree(t, []string{}, tree, err, ref) + t.Log("Finished tree assertion.") +} + +func TestCreateSubTree(t *testing.T) { + tree := newTree() + tree.createSubTree([]string{"a", "b", "c"}, Position{}) + tree.Set("a.b.c", 42) + if tree.Get("a.b.c") != 42 { + t.Fail() + } +} + +func TestSimpleKV(t *testing.T) { + tree, err := Load("a = 42") + assertTree(t, tree, err, map[string]interface{}{ + "a": int64(42), + }) + + tree, _ = Load("a = 42\nb = 21") + assertTree(t, tree, err, map[string]interface{}{ + "a": int64(42), + "b": int64(21), + }) +} + +func TestNumberInKey(t *testing.T) { + tree, err := Load("hello2 = 42") + assertTree(t, tree, err, map[string]interface{}{ + "hello2": int64(42), + }) +} + +func TestIncorrectKeyExtraSquareBracket(t *testing.T) { + _, err := Load(`[a]b] +zyx = 42`) + if err == nil { + t.Error("Error should have been returned.") + } + if err.Error() != "(1, 4): unexpected token" { + t.Error("Bad error message:", err.Error()) + } +} + +func TestSimpleNumbers(t *testing.T) { + tree, err := Load("a = +42\nb = -21\nc = +4.2\nd = -2.1") + assertTree(t, tree, err, map[string]interface{}{ + "a": int64(42), + "b": int64(-21), + "c": float64(4.2), + "d": float64(-2.1), + }) +} + +func TestSpecialFloats(t *testing.T) { + tree, err := Load(` +normalinf = inf +plusinf = +inf +minusinf = -inf +normalnan = nan +plusnan = +nan +minusnan = -nan +`) + assertTree(t, tree, err, map[string]interface{}{ + "normalinf": math.Inf(1), + "plusinf": math.Inf(1), + "minusinf": math.Inf(-1), + "normalnan": math.NaN(), + "plusnan": math.NaN(), + "minusnan": math.NaN(), + }) +} + +func TestHexIntegers(t *testing.T) { + tree, err := Load(`a = 0xDEADBEEF`) + assertTree(t, tree, err, map[string]interface{}{"a": int64(3735928559)}) + + tree, err = Load(`a = 0xdeadbeef`) + assertTree(t, tree, err, map[string]interface{}{"a": int64(3735928559)}) + + tree, err = Load(`a = 0xdead_beef`) + assertTree(t, tree, err, map[string]interface{}{"a": int64(3735928559)}) + + _, err = Load(`a = 0x_1`) + if err.Error() != "(1, 5): invalid use of _ in hex number" { + t.Error("Bad error message:", err.Error()) + } +} + +func TestOctIntegers(t *testing.T) { + tree, err := Load(`a = 0o01234567`) + assertTree(t, tree, err, map[string]interface{}{"a": int64(342391)}) + + tree, err = Load(`a = 0o755`) + assertTree(t, tree, err, map[string]interface{}{"a": int64(493)}) + + _, err = Load(`a = 0o_1`) + if err.Error() != "(1, 5): invalid use of _ in number" { + t.Error("Bad error message:", err.Error()) + } +} + +func TestBinIntegers(t *testing.T) { + tree, err := Load(`a = 0b11010110`) + assertTree(t, tree, err, map[string]interface{}{"a": int64(214)}) + + _, err = Load(`a = 0b_1`) + if err.Error() != "(1, 5): invalid use of _ in number" { + t.Error("Bad error message:", err.Error()) + } +} + +func TestBadIntegerBase(t *testing.T) { + _, err := Load(`a = 0k1`) + if err.Error() != "(1, 5): unknown number base: k. possible options are x (hex) o (octal) b (binary)" { + t.Error("Error should have been returned.") + } +} + +func TestIntegerNoDigit(t *testing.T) { + _, err := Load(`a = 0b`) + if err.Error() != "(1, 5): number needs at least one digit" { + t.Error("Bad error message:", err.Error()) + } +} + +func TestNumbersWithUnderscores(t *testing.T) { + tree, err := Load("a = 1_000") + assertTree(t, tree, err, map[string]interface{}{ + "a": int64(1000), + }) + + tree, err = Load("a = 5_349_221") + assertTree(t, tree, err, map[string]interface{}{ + "a": int64(5349221), + }) + + tree, err = Load("a = 1_2_3_4_5") + assertTree(t, tree, err, map[string]interface{}{ + "a": int64(12345), + }) + + tree, err = Load("flt8 = 9_224_617.445_991_228_313") + assertTree(t, tree, err, map[string]interface{}{ + "flt8": float64(9224617.445991228313), + }) + + tree, err = Load("flt9 = 1e1_00") + assertTree(t, tree, err, map[string]interface{}{ + "flt9": float64(1e100), + }) +} + +func TestFloatsWithExponents(t *testing.T) { + tree, err := Load("a = 5e+22\nb = 5E+22\nc = -5e+22\nd = -5e-22\ne = 6.626e-34") + assertTree(t, tree, err, map[string]interface{}{ + "a": float64(5e+22), + "b": float64(5E+22), + "c": float64(-5e+22), + "d": float64(-5e-22), + "e": float64(6.626e-34), + }) +} + +func TestSimpleDate(t *testing.T) { + tree, err := Load("a = 1979-05-27T07:32:00Z") + assertTree(t, tree, err, map[string]interface{}{ + "a": time.Date(1979, time.May, 27, 7, 32, 0, 0, time.UTC), + }) +} + +func TestDateOffset(t *testing.T) { + tree, err := Load("a = 1979-05-27T00:32:00-07:00") + assertTree(t, tree, err, map[string]interface{}{ + "a": time.Date(1979, time.May, 27, 0, 32, 0, 0, time.FixedZone("", -7*60*60)), + }) +} + +func TestDateNano(t *testing.T) { + tree, err := Load("a = 1979-05-27T00:32:00.999999999-07:00") + assertTree(t, tree, err, map[string]interface{}{ + "a": time.Date(1979, time.May, 27, 0, 32, 0, 999999999, time.FixedZone("", -7*60*60)), + }) +} + +func TestSimpleString(t *testing.T) { + tree, err := Load("a = \"hello world\"") + assertTree(t, tree, err, map[string]interface{}{ + "a": "hello world", + }) +} + +func TestSpaceKey(t *testing.T) { + tree, err := Load("\"a b\" = \"hello world\"") + assertTree(t, tree, err, map[string]interface{}{ + "a b": "hello world", + }) +} + +func TestDoubleQuotedKey(t *testing.T) { + tree, err := Load(` + "key" = "a" + "\t" = "b" + "\U0001F914" = "c" + "\u2764" = "d" + `) + assertTree(t, tree, err, map[string]interface{}{ + "key": "a", + "\t": "b", + "\U0001F914": "c", + "\u2764": "d", + }) +} + +func TestSingleQuotedKey(t *testing.T) { + tree, err := Load(` + 'key' = "a" + '\t' = "b" + '\U0001F914' = "c" + '\u2764' = "d" + `) + assertTree(t, tree, err, map[string]interface{}{ + `key`: "a", + `\t`: "b", + `\U0001F914`: "c", + `\u2764`: "d", + }) +} + +func TestStringEscapables(t *testing.T) { + tree, err := Load("a = \"a \\n b\"") + assertTree(t, tree, err, map[string]interface{}{ + "a": "a \n b", + }) + + tree, err = Load("a = \"a \\t b\"") + assertTree(t, tree, err, map[string]interface{}{ + "a": "a \t b", + }) + + tree, err = Load("a = \"a \\r b\"") + assertTree(t, tree, err, map[string]interface{}{ + "a": "a \r b", + }) + + tree, err = Load("a = \"a \\\\ b\"") + assertTree(t, tree, err, map[string]interface{}{ + "a": "a \\ b", + }) +} + +func TestEmptyQuotedString(t *testing.T) { + tree, err := Load(`[""] +"" = 1`) + assertTree(t, tree, err, map[string]interface{}{ + "": map[string]interface{}{ + "": int64(1), + }, + }) +} + +func TestBools(t *testing.T) { + tree, err := Load("a = true\nb = false") + assertTree(t, tree, err, map[string]interface{}{ + "a": true, + "b": false, + }) +} + +func TestNestedKeys(t *testing.T) { + tree, err := Load("[a.b.c]\nd = 42") + assertTree(t, tree, err, map[string]interface{}{ + "a": map[string]interface{}{ + "b": map[string]interface{}{ + "c": map[string]interface{}{ + "d": int64(42), + }, + }, + }, + }) +} + +func TestNestedQuotedUnicodeKeys(t *testing.T) { + tree, err := Load("[ j . \"ʞ\" . l ]\nd = 42") + assertTree(t, tree, err, map[string]interface{}{ + "j": map[string]interface{}{ + "ʞ": map[string]interface{}{ + "l": map[string]interface{}{ + "d": int64(42), + }, + }, + }, + }) + + tree, err = Load("[ g . h . i ]\nd = 42") + assertTree(t, tree, err, map[string]interface{}{ + "g": map[string]interface{}{ + "h": map[string]interface{}{ + "i": map[string]interface{}{ + "d": int64(42), + }, + }, + }, + }) + + tree, err = Load("[ d.e.f ]\nk = 42") + assertTree(t, tree, err, map[string]interface{}{ + "d": map[string]interface{}{ + "e": map[string]interface{}{ + "f": map[string]interface{}{ + "k": int64(42), + }, + }, + }, + }) +} + +func TestArrayOne(t *testing.T) { + tree, err := Load("a = [1]") + assertTree(t, tree, err, map[string]interface{}{ + "a": []int64{int64(1)}, + }) +} + +func TestArrayZero(t *testing.T) { + tree, err := Load("a = []") + assertTree(t, tree, err, map[string]interface{}{ + "a": []interface{}{}, + }) +} + +func TestArraySimple(t *testing.T) { + tree, err := Load("a = [42, 21, 10]") + assertTree(t, tree, err, map[string]interface{}{ + "a": []int64{int64(42), int64(21), int64(10)}, + }) + + tree, _ = Load("a = [42, 21, 10,]") + assertTree(t, tree, err, map[string]interface{}{ + "a": []int64{int64(42), int64(21), int64(10)}, + }) +} + +func TestArrayMultiline(t *testing.T) { + tree, err := Load("a = [42,\n21, 10,]") + assertTree(t, tree, err, map[string]interface{}{ + "a": []int64{int64(42), int64(21), int64(10)}, + }) +} + +func TestArrayNested(t *testing.T) { + tree, err := Load("a = [[42, 21], [10]]") + assertTree(t, tree, err, map[string]interface{}{ + "a": [][]int64{{int64(42), int64(21)}, {int64(10)}}, + }) +} + +func TestNestedArrayComment(t *testing.T) { + tree, err := Load(` +someArray = [ +# does not work +["entry1"] +]`) + assertTree(t, tree, err, map[string]interface{}{ + "someArray": [][]string{{"entry1"}}, + }) +} + +func TestNestedEmptyArrays(t *testing.T) { + tree, err := Load("a = [[[]]]") + assertTree(t, tree, err, map[string]interface{}{ + "a": [][][]interface{}{{{}}}, + }) +} + +func TestArrayMixedTypes(t *testing.T) { + _, err := Load("a = [42, 16.0]") + if err.Error() != "(1, 10): mixed types in array" { + t.Error("Bad error message:", err.Error()) + } + + _, err = Load("a = [42, \"hello\"]") + if err.Error() != "(1, 11): mixed types in array" { + t.Error("Bad error message:", err.Error()) + } +} + +func TestArrayNestedStrings(t *testing.T) { + tree, err := Load("data = [ [\"gamma\", \"delta\"], [\"Foo\"] ]") + assertTree(t, tree, err, map[string]interface{}{ + "data": [][]string{{"gamma", "delta"}, {"Foo"}}, + }) +} + +func TestParseUnknownRvalue(t *testing.T) { + _, err := Load("a = !bssss") + if err == nil { + t.Error("Expecting a parse error") + } + + _, err = Load("a = /b") + if err == nil { + t.Error("Expecting a parse error") + } +} + +func TestMissingValue(t *testing.T) { + _, err := Load("a = ") + if err.Error() != "(1, 5): expecting a value" { + t.Error("Bad error message:", err.Error()) + } +} + +func TestUnterminatedArray(t *testing.T) { + _, err := Load("a = [1,") + if err.Error() != "(1, 8): unterminated array" { + t.Error("Bad error message:", err.Error()) + } + + _, err = Load("a = [1") + if err.Error() != "(1, 7): unterminated array" { + t.Error("Bad error message:", err.Error()) + } + + _, err = Load("a = [1 2") + if err.Error() != "(1, 8): missing comma" { + t.Error("Bad error message:", err.Error()) + } +} + +func TestNewlinesInArrays(t *testing.T) { + tree, err := Load("a = [1,\n2,\n3]") + assertTree(t, tree, err, map[string]interface{}{ + "a": []int64{int64(1), int64(2), int64(3)}, + }) +} + +func TestArrayWithExtraComma(t *testing.T) { + tree, err := Load("a = [1,\n2,\n3,\n]") + assertTree(t, tree, err, map[string]interface{}{ + "a": []int64{int64(1), int64(2), int64(3)}, + }) +} + +func TestArrayWithExtraCommaComment(t *testing.T) { + tree, err := Load("a = [1, # wow\n2, # such items\n3, # so array\n]") + assertTree(t, tree, err, map[string]interface{}{ + "a": []int64{int64(1), int64(2), int64(3)}, + }) +} + +func TestSimpleInlineGroup(t *testing.T) { + tree, err := Load("key = {a = 42}") + assertTree(t, tree, err, map[string]interface{}{ + "key": map[string]interface{}{ + "a": int64(42), + }, + }) +} + +func TestDoubleInlineGroup(t *testing.T) { + tree, err := Load("key = {a = 42, b = \"foo\"}") + assertTree(t, tree, err, map[string]interface{}{ + "key": map[string]interface{}{ + "a": int64(42), + "b": "foo", + }, + }) +} + +func TestExampleInlineGroup(t *testing.T) { + tree, err := Load(`name = { first = "Tom", last = "Preston-Werner" } +point = { x = 1, y = 2 }`) + assertTree(t, tree, err, map[string]interface{}{ + "name": map[string]interface{}{ + "first": "Tom", + "last": "Preston-Werner", + }, + "point": map[string]interface{}{ + "x": int64(1), + "y": int64(2), + }, + }) +} + +func TestExampleInlineGroupInArray(t *testing.T) { + tree, err := Load(`points = [{ x = 1, y = 2 }]`) + assertTree(t, tree, err, map[string]interface{}{ + "points": []map[string]interface{}{ + { + "x": int64(1), + "y": int64(2), + }, + }, + }) +} + +func TestInlineTableUnterminated(t *testing.T) { + _, err := Load("foo = {") + if err.Error() != "(1, 8): unterminated inline table" { + t.Error("Bad error message:", err.Error()) + } +} + +func TestInlineTableCommaExpected(t *testing.T) { + _, err := Load("foo = {hello = 53 test = foo}") + if err.Error() != "(1, 19): comma expected between fields in inline table" { + t.Error("Bad error message:", err.Error()) + } +} + +func TestInlineTableCommaStart(t *testing.T) { + _, err := Load("foo = {, hello = 53}") + if err.Error() != "(1, 8): inline table cannot start with a comma" { + t.Error("Bad error message:", err.Error()) + } +} + +func TestInlineTableDoubleComma(t *testing.T) { + _, err := Load("foo = {hello = 53,, foo = 17}") + if err.Error() != "(1, 19): need field between two commas in inline table" { + t.Error("Bad error message:", err.Error()) + } +} + +func TestDuplicateGroups(t *testing.T) { + _, err := Load("[foo]\na=2\n[foo]b=3") + if err.Error() != "(3, 2): duplicated tables" { + t.Error("Bad error message:", err.Error()) + } +} + +func TestDuplicateKeys(t *testing.T) { + _, err := Load("foo = 2\nfoo = 3") + if err.Error() != "(2, 1): The following key was defined twice: foo" { + t.Error("Bad error message:", err.Error()) + } +} + +func TestEmptyIntermediateTable(t *testing.T) { + _, err := Load("[foo..bar]") + if err.Error() != "(1, 2): invalid table array key: empty table key" { + t.Error("Bad error message:", err.Error()) + } +} + +func TestImplicitDeclarationBefore(t *testing.T) { + tree, err := Load("[a.b.c]\nanswer = 42\n[a]\nbetter = 43") + assertTree(t, tree, err, map[string]interface{}{ + "a": map[string]interface{}{ + "b": map[string]interface{}{ + "c": map[string]interface{}{ + "answer": int64(42), + }, + }, + "better": int64(43), + }, + }) +} + +func TestFloatsWithoutLeadingZeros(t *testing.T) { + _, err := Load("a = .42") + if err.Error() != "(1, 5): cannot start float with a dot" { + t.Error("Bad error message:", err.Error()) + } + + _, err = Load("a = -.42") + if err.Error() != "(1, 5): cannot start float with a dot" { + t.Error("Bad error message:", err.Error()) + } +} + +func TestMissingFile(t *testing.T) { + _, err := LoadFile("foo.toml") + if err.Error() != "open foo.toml: no such file or directory" && + err.Error() != "open foo.toml: The system cannot find the file specified." { + t.Error("Bad error message:", err.Error()) + } +} + +func TestParseFile(t *testing.T) { + tree, err := LoadFile("example.toml") + + assertTree(t, tree, err, map[string]interface{}{ + "title": "TOML Example", + "owner": map[string]interface{}{ + "name": "Tom Preston-Werner", + "organization": "GitHub", + "bio": "GitHub Cofounder & CEO\nLikes tater tots and beer.", + "dob": time.Date(1979, time.May, 27, 7, 32, 0, 0, time.UTC), + }, + "database": map[string]interface{}{ + "server": "192.168.1.1", + "ports": []int64{8001, 8001, 8002}, + "connection_max": 5000, + "enabled": true, + }, + "servers": map[string]interface{}{ + "alpha": map[string]interface{}{ + "ip": "10.0.0.1", + "dc": "eqdc10", + }, + "beta": map[string]interface{}{ + "ip": "10.0.0.2", + "dc": "eqdc10", + }, + }, + "clients": map[string]interface{}{ + "data": []interface{}{ + []string{"gamma", "delta"}, + []int64{1, 2}, + }, + }, + }) +} + +func TestParseFileCRLF(t *testing.T) { + tree, err := LoadFile("example-crlf.toml") + + assertTree(t, tree, err, map[string]interface{}{ + "title": "TOML Example", + "owner": map[string]interface{}{ + "name": "Tom Preston-Werner", + "organization": "GitHub", + "bio": "GitHub Cofounder & CEO\nLikes tater tots and beer.", + "dob": time.Date(1979, time.May, 27, 7, 32, 0, 0, time.UTC), + }, + "database": map[string]interface{}{ + "server": "192.168.1.1", + "ports": []int64{8001, 8001, 8002}, + "connection_max": 5000, + "enabled": true, + }, + "servers": map[string]interface{}{ + "alpha": map[string]interface{}{ + "ip": "10.0.0.1", + "dc": "eqdc10", + }, + "beta": map[string]interface{}{ + "ip": "10.0.0.2", + "dc": "eqdc10", + }, + }, + "clients": map[string]interface{}{ + "data": []interface{}{ + []string{"gamma", "delta"}, + []int64{1, 2}, + }, + }, + }) +} + +func TestParseKeyGroupArray(t *testing.T) { + tree, err := Load("[[foo.bar]] a = 42\n[[foo.bar]] a = 69") + assertTree(t, tree, err, map[string]interface{}{ + "foo": map[string]interface{}{ + "bar": []map[string]interface{}{ + {"a": int64(42)}, + {"a": int64(69)}, + }, + }, + }) +} + +func TestParseKeyGroupArrayUnfinished(t *testing.T) { + _, err := Load("[[foo.bar]\na = 42") + if err.Error() != "(1, 10): was expecting token [[, but got unclosed table array key instead" { + t.Error("Bad error message:", err.Error()) + } + + _, err = Load("[[foo.[bar]\na = 42") + if err.Error() != "(1, 3): unexpected token table array key cannot contain ']', was expecting a table array key" { + t.Error("Bad error message:", err.Error()) + } +} + +func TestParseKeyGroupArrayQueryExample(t *testing.T) { + tree, err := Load(` + [[book]] + title = "The Stand" + author = "Stephen King" + [[book]] + title = "For Whom the Bell Tolls" + author = "Ernest Hemmingway" + [[book]] + title = "Neuromancer" + author = "William Gibson" + `) + + assertTree(t, tree, err, map[string]interface{}{ + "book": []map[string]interface{}{ + {"title": "The Stand", "author": "Stephen King"}, + {"title": "For Whom the Bell Tolls", "author": "Ernest Hemmingway"}, + {"title": "Neuromancer", "author": "William Gibson"}, + }, + }) +} + +func TestParseKeyGroupArraySpec(t *testing.T) { + tree, err := Load("[[fruit]]\n name=\"apple\"\n [fruit.physical]\n color=\"red\"\n shape=\"round\"\n [[fruit]]\n name=\"banana\"") + assertTree(t, tree, err, map[string]interface{}{ + "fruit": []map[string]interface{}{ + {"name": "apple", "physical": map[string]interface{}{"color": "red", "shape": "round"}}, + {"name": "banana"}, + }, + }) +} + +func TestTomlValueStringRepresentation(t *testing.T) { + for idx, item := range []struct { + Value interface{} + Expect string + }{ + {int64(12345), "12345"}, + {uint64(50), "50"}, + {float64(123.45), "123.45"}, + {true, "true"}, + {"hello world", "\"hello world\""}, + {"\b\t\n\f\r\"\\", "\"\\b\\t\\n\\f\\r\\\"\\\\\""}, + {"\x05", "\"\\u0005\""}, + {time.Date(1979, time.May, 27, 7, 32, 0, 0, time.UTC), + "1979-05-27T07:32:00Z"}, + {[]interface{}{"gamma", "delta"}, + "[\"gamma\",\"delta\"]"}, + {nil, ""}, + } { + result, err := tomlValueStringRepresentation(item.Value, "", false) + if err != nil { + t.Errorf("Test %d - unexpected error: %s", idx, err) + } + if result != item.Expect { + t.Errorf("Test %d - got '%s', expected '%s'", idx, result, item.Expect) + } + } +} + +func TestToStringMapStringString(t *testing.T) { + tree, err := TreeFromMap(map[string]interface{}{"m": map[string]interface{}{"v": "abc"}}) + if err != nil { + t.Fatalf("unexpected error: %s", err) + } + want := "\n[m]\n v = \"abc\"\n" + got := tree.String() + + if got != want { + t.Errorf("want:\n%q\ngot:\n%q", want, got) + } +} + +func assertPosition(t *testing.T, text string, ref map[string]Position) { + tree, err := Load(text) + if err != nil { + t.Errorf("Error loading document text: `%v`", text) + t.Errorf("Error: %v", err) + } + for path, pos := range ref { + testPos := tree.GetPosition(path) + if testPos.Invalid() { + t.Errorf("Failed to query tree path or path has invalid position: %s", path) + } else if pos != testPos { + t.Errorf("Expected position %v, got %v instead", pos, testPos) + } + } +} + +func TestDocumentPositions(t *testing.T) { + assertPosition(t, + "[foo]\nbar=42\nbaz=69", + map[string]Position{ + "": {1, 1}, + "foo": {1, 1}, + "foo.bar": {2, 1}, + "foo.baz": {3, 1}, + }) +} + +func TestDocumentPositionsWithSpaces(t *testing.T) { + assertPosition(t, + " [foo]\n bar=42\n baz=69", + map[string]Position{ + "": {1, 1}, + "foo": {1, 3}, + "foo.bar": {2, 3}, + "foo.baz": {3, 3}, + }) +} + +func TestDocumentPositionsWithGroupArray(t *testing.T) { + assertPosition(t, + "[[foo]]\nbar=42\nbaz=69", + map[string]Position{ + "": {1, 1}, + "foo": {1, 1}, + "foo.bar": {2, 1}, + "foo.baz": {3, 1}, + }) +} + +func TestNestedTreePosition(t *testing.T) { + assertPosition(t, + "[foo.bar]\na=42\nb=69", + map[string]Position{ + "": {1, 1}, + "foo": {1, 1}, + "foo.bar": {1, 1}, + "foo.bar.a": {2, 1}, + "foo.bar.b": {3, 1}, + }) +} + +func TestInvalidGroupArray(t *testing.T) { + _, err := Load("[table#key]\nanswer = 42") + if err == nil { + t.Error("Should error") + } + + _, err = Load("[foo.[bar]\na = 42") + if err.Error() != "(1, 2): unexpected token table key cannot contain ']', was expecting a table key" { + t.Error("Bad error message:", err.Error()) + } +} + +func TestDoubleEqual(t *testing.T) { + _, err := Load("foo= = 2") + if err.Error() != "(1, 6): cannot have multiple equals for the same key" { + t.Error("Bad error message:", err.Error()) + } +} + +func TestGroupArrayReassign(t *testing.T) { + _, err := Load("[hello]\n[[hello]]") + if err.Error() != "(2, 3): key \"hello\" is already assigned and not of type table array" { + t.Error("Bad error message:", err.Error()) + } +} + +func TestInvalidFloatParsing(t *testing.T) { + _, err := Load("a=1e_2") + if err.Error() != "(1, 3): invalid use of _ in number" { + t.Error("Bad error message:", err.Error()) + } + + _, err = Load("a=1e2_") + if err.Error() != "(1, 3): invalid use of _ in number" { + t.Error("Bad error message:", err.Error()) + } + + _, err = Load("a=1__2") + if err.Error() != "(1, 3): invalid use of _ in number" { + t.Error("Bad error message:", err.Error()) + } + + _, err = Load("a=_1_2") + if err.Error() != "(1, 3): cannot start number with underscore" { + t.Error("Bad error message:", err.Error()) + } +} diff --git a/vendor/github.com/pelletier/go-toml/position.go b/vendor/github.com/pelletier/go-toml/position.go new file mode 100644 index 00000000..c17bff87 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/position.go @@ -0,0 +1,29 @@ +// Position support for go-toml + +package toml + +import ( + "fmt" +) + +// Position of a document element within a TOML document. +// +// Line and Col are both 1-indexed positions for the element's line number and +// column number, respectively. Values of zero or less will cause Invalid(), +// to return true. +type Position struct { + Line int // line within the document + Col int // column within the line +} + +// String representation of the position. +// Displays 1-indexed line and column numbers. +func (p Position) String() string { + return fmt.Sprintf("(%d, %d)", p.Line, p.Col) +} + +// Invalid returns whether or not the position is valid (i.e. with negative or +// null values) +func (p Position) Invalid() bool { + return p.Line <= 0 || p.Col <= 0 +} diff --git a/vendor/github.com/pelletier/go-toml/position_test.go b/vendor/github.com/pelletier/go-toml/position_test.go new file mode 100644 index 00000000..63ad1afc --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/position_test.go @@ -0,0 +1,29 @@ +// Testing support for go-toml + +package toml + +import ( + "testing" +) + +func TestPositionString(t *testing.T) { + p := Position{123, 456} + expected := "(123, 456)" + value := p.String() + + if value != expected { + t.Errorf("Expected %v, got %v instead", expected, value) + } +} + +func TestInvalid(t *testing.T) { + for i, v := range []Position{ + {0, 1234}, + {1234, 0}, + {0, 0}, + } { + if !v.Invalid() { + t.Errorf("Position at %v is valid: %v", i, v) + } + } +} diff --git a/vendor/github.com/pelletier/go-toml/query/doc.go b/vendor/github.com/pelletier/go-toml/query/doc.go new file mode 100644 index 00000000..ed63c110 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/query/doc.go @@ -0,0 +1,175 @@ +// Package query performs JSONPath-like queries on a TOML document. +// +// The query path implementation is based loosely on the JSONPath specification: +// http://goessner.net/articles/JsonPath/. +// +// The idea behind a query path is to allow quick access to any element, or set +// of elements within TOML document, with a single expression. +// +// result, err := query.CompileAndExecute("$.foo.bar.baz", tree) +// +// This is roughly equivalent to: +// +// next := tree.Get("foo") +// if next != nil { +// next = next.Get("bar") +// if next != nil { +// next = next.Get("baz") +// } +// } +// result := next +// +// err is nil if any parsing exception occurs. +// +// If no node in the tree matches the query, result will simply contain an empty list of +// items. +// +// As illustrated above, the query path is much more efficient, especially since +// the structure of the TOML file can vary. Rather than making assumptions about +// a document's structure, a query allows the programmer to make structured +// requests into the document, and get zero or more values as a result. +// +// Query syntax +// +// The syntax of a query begins with a root token, followed by any number +// sub-expressions: +// +// $ +// Root of the TOML tree. This must always come first. +// .name +// Selects child of this node, where 'name' is a TOML key +// name. +// ['name'] +// Selects child of this node, where 'name' is a string +// containing a TOML key name. +// [index] +// Selcts child array element at 'index'. +// ..expr +// Recursively selects all children, filtered by an a union, +// index, or slice expression. +// ..* +// Recursive selection of all nodes at this point in the +// tree. +// .* +// Selects all children of the current node. +// [expr,expr] +// Union operator - a logical 'or' grouping of two or more +// sub-expressions: index, key name, or filter. +// [start:end:step] +// Slice operator - selects array elements from start to +// end-1, at the given step. All three arguments are +// optional. +// [?(filter)] +// Named filter expression - the function 'filter' is +// used to filter children at this node. +// +// Query Indexes And Slices +// +// Index expressions perform no bounds checking, and will contribute no +// values to the result set if the provided index or index range is invalid. +// Negative indexes represent values from the end of the array, counting backwards. +// +// // select the last index of the array named 'foo' +// query.CompileAndExecute("$.foo[-1]", tree) +// +// Slice expressions are supported, by using ':' to separate a start/end index pair. +// +// // select up to the first five elements in the array +// query.CompileAndExecute("$.foo[0:5]", tree) +// +// Slice expressions also allow negative indexes for the start and stop +// arguments. +// +// // select all array elements. +// query.CompileAndExecute("$.foo[0:-1]", tree) +// +// Slice expressions may have an optional stride/step parameter: +// +// // select every other element +// query.CompileAndExecute("$.foo[0:-1:2]", tree) +// +// Slice start and end parameters are also optional: +// +// // these are all equivalent and select all the values in the array +// query.CompileAndExecute("$.foo[:]", tree) +// query.CompileAndExecute("$.foo[0:]", tree) +// query.CompileAndExecute("$.foo[:-1]", tree) +// query.CompileAndExecute("$.foo[0:-1:]", tree) +// query.CompileAndExecute("$.foo[::1]", tree) +// query.CompileAndExecute("$.foo[0::1]", tree) +// query.CompileAndExecute("$.foo[:-1:1]", tree) +// query.CompileAndExecute("$.foo[0:-1:1]", tree) +// +// Query Filters +// +// Query filters are used within a Union [,] or single Filter [] expression. +// A filter only allows nodes that qualify through to the next expression, +// and/or into the result set. +// +// // returns children of foo that are permitted by the 'bar' filter. +// query.CompileAndExecute("$.foo[?(bar)]", tree) +// +// There are several filters provided with the library: +// +// tree +// Allows nodes of type Tree. +// int +// Allows nodes of type int64. +// float +// Allows nodes of type float64. +// string +// Allows nodes of type string. +// time +// Allows nodes of type time.Time. +// bool +// Allows nodes of type bool. +// +// Query Results +// +// An executed query returns a Result object. This contains the nodes +// in the TOML tree that qualify the query expression. Position information +// is also available for each value in the set. +// +// // display the results of a query +// results := query.CompileAndExecute("$.foo.bar.baz", tree) +// for idx, value := results.Values() { +// fmt.Println("%v: %v", results.Positions()[idx], value) +// } +// +// Compiled Queries +// +// Queries may be executed directly on a Tree object, or compiled ahead +// of time and executed discretely. The former is more convenient, but has the +// penalty of having to recompile the query expression each time. +// +// // basic query +// results := query.CompileAndExecute("$.foo.bar.baz", tree) +// +// // compiled query +// query, err := toml.Compile("$.foo.bar.baz") +// results := query.Execute(tree) +// +// // run the compiled query again on a different tree +// moreResults := query.Execute(anotherTree) +// +// User Defined Query Filters +// +// Filter expressions may also be user defined by using the SetFilter() +// function on the Query object. The function must return true/false, which +// signifies if the passed node is kept or discarded, respectively. +// +// // create a query that references a user-defined filter +// query, _ := query.Compile("$[?(bazOnly)]") +// +// // define the filter, and assign it to the query +// query.SetFilter("bazOnly", func(node interface{}) bool{ +// if tree, ok := node.(*Tree); ok { +// return tree.Has("baz") +// } +// return false // reject all other node types +// }) +// +// // run the query +// query.Execute(tree) +// +package query diff --git a/vendor/github.com/pelletier/go-toml/query/lexer.go b/vendor/github.com/pelletier/go-toml/query/lexer.go new file mode 100644 index 00000000..2dc31940 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/query/lexer.go @@ -0,0 +1,357 @@ +// TOML JSONPath lexer. +// +// Written using the principles developed by Rob Pike in +// http://www.youtube.com/watch?v=HxaD_trXwRE + +package query + +import ( + "fmt" + "github.com/pelletier/go-toml" + "strconv" + "strings" + "unicode/utf8" +) + +// Lexer state function +type queryLexStateFn func() queryLexStateFn + +// Lexer definition +type queryLexer struct { + input string + start int + pos int + width int + tokens chan token + depth int + line int + col int + stringTerm string +} + +func (l *queryLexer) run() { + for state := l.lexVoid; state != nil; { + state = state() + } + close(l.tokens) +} + +func (l *queryLexer) nextStart() { + // iterate by runes (utf8 characters) + // search for newlines and advance line/col counts + for i := l.start; i < l.pos; { + r, width := utf8.DecodeRuneInString(l.input[i:]) + if r == '\n' { + l.line++ + l.col = 1 + } else { + l.col++ + } + i += width + } + // advance start position to next token + l.start = l.pos +} + +func (l *queryLexer) emit(t tokenType) { + l.tokens <- token{ + Position: toml.Position{Line: l.line, Col: l.col}, + typ: t, + val: l.input[l.start:l.pos], + } + l.nextStart() +} + +func (l *queryLexer) emitWithValue(t tokenType, value string) { + l.tokens <- token{ + Position: toml.Position{Line: l.line, Col: l.col}, + typ: t, + val: value, + } + l.nextStart() +} + +func (l *queryLexer) next() rune { + if l.pos >= len(l.input) { + l.width = 0 + return eof + } + var r rune + r, l.width = utf8.DecodeRuneInString(l.input[l.pos:]) + l.pos += l.width + return r +} + +func (l *queryLexer) ignore() { + l.nextStart() +} + +func (l *queryLexer) backup() { + l.pos -= l.width +} + +func (l *queryLexer) errorf(format string, args ...interface{}) queryLexStateFn { + l.tokens <- token{ + Position: toml.Position{Line: l.line, Col: l.col}, + typ: tokenError, + val: fmt.Sprintf(format, args...), + } + return nil +} + +func (l *queryLexer) peek() rune { + r := l.next() + l.backup() + return r +} + +func (l *queryLexer) accept(valid string) bool { + if strings.ContainsRune(valid, l.next()) { + return true + } + l.backup() + return false +} + +func (l *queryLexer) follow(next string) bool { + return strings.HasPrefix(l.input[l.pos:], next) +} + +func (l *queryLexer) lexVoid() queryLexStateFn { + for { + next := l.peek() + switch next { + case '$': + l.pos++ + l.emit(tokenDollar) + continue + case '.': + if l.follow("..") { + l.pos += 2 + l.emit(tokenDotDot) + } else { + l.pos++ + l.emit(tokenDot) + } + continue + case '[': + l.pos++ + l.emit(tokenLeftBracket) + continue + case ']': + l.pos++ + l.emit(tokenRightBracket) + continue + case ',': + l.pos++ + l.emit(tokenComma) + continue + case '*': + l.pos++ + l.emit(tokenStar) + continue + case '(': + l.pos++ + l.emit(tokenLeftParen) + continue + case ')': + l.pos++ + l.emit(tokenRightParen) + continue + case '?': + l.pos++ + l.emit(tokenQuestion) + continue + case ':': + l.pos++ + l.emit(tokenColon) + continue + case '\'': + l.ignore() + l.stringTerm = string(next) + return l.lexString + case '"': + l.ignore() + l.stringTerm = string(next) + return l.lexString + } + + if isSpace(next) { + l.next() + l.ignore() + continue + } + + if isAlphanumeric(next) { + return l.lexKey + } + + if next == '+' || next == '-' || isDigit(next) { + return l.lexNumber + } + + if l.next() == eof { + break + } + + return l.errorf("unexpected char: '%v'", next) + } + l.emit(tokenEOF) + return nil +} + +func (l *queryLexer) lexKey() queryLexStateFn { + for { + next := l.peek() + if !isAlphanumeric(next) { + l.emit(tokenKey) + return l.lexVoid + } + + if l.next() == eof { + break + } + } + l.emit(tokenEOF) + return nil +} + +func (l *queryLexer) lexString() queryLexStateFn { + l.pos++ + l.ignore() + growingString := "" + + for { + if l.follow(l.stringTerm) { + l.emitWithValue(tokenString, growingString) + l.pos++ + l.ignore() + return l.lexVoid + } + + if l.follow("\\\"") { + l.pos++ + growingString += "\"" + } else if l.follow("\\'") { + l.pos++ + growingString += "'" + } else if l.follow("\\n") { + l.pos++ + growingString += "\n" + } else if l.follow("\\b") { + l.pos++ + growingString += "\b" + } else if l.follow("\\f") { + l.pos++ + growingString += "\f" + } else if l.follow("\\/") { + l.pos++ + growingString += "/" + } else if l.follow("\\t") { + l.pos++ + growingString += "\t" + } else if l.follow("\\r") { + l.pos++ + growingString += "\r" + } else if l.follow("\\\\") { + l.pos++ + growingString += "\\" + } else if l.follow("\\u") { + l.pos += 2 + code := "" + for i := 0; i < 4; i++ { + c := l.peek() + l.pos++ + if !isHexDigit(c) { + return l.errorf("unfinished unicode escape") + } + code = code + string(c) + } + l.pos-- + intcode, err := strconv.ParseInt(code, 16, 32) + if err != nil { + return l.errorf("invalid unicode escape: \\u" + code) + } + growingString += string(rune(intcode)) + } else if l.follow("\\U") { + l.pos += 2 + code := "" + for i := 0; i < 8; i++ { + c := l.peek() + l.pos++ + if !isHexDigit(c) { + return l.errorf("unfinished unicode escape") + } + code = code + string(c) + } + l.pos-- + intcode, err := strconv.ParseInt(code, 16, 32) + if err != nil { + return l.errorf("invalid unicode escape: \\u" + code) + } + growingString += string(rune(intcode)) + } else if l.follow("\\") { + l.pos++ + return l.errorf("invalid escape sequence: \\" + string(l.peek())) + } else { + growingString += string(l.peek()) + } + + if l.next() == eof { + break + } + } + + return l.errorf("unclosed string") +} + +func (l *queryLexer) lexNumber() queryLexStateFn { + l.ignore() + if !l.accept("+") { + l.accept("-") + } + pointSeen := false + digitSeen := false + for { + next := l.next() + if next == '.' { + if pointSeen { + return l.errorf("cannot have two dots in one float") + } + if !isDigit(l.peek()) { + return l.errorf("float cannot end with a dot") + } + pointSeen = true + } else if isDigit(next) { + digitSeen = true + } else { + l.backup() + break + } + if pointSeen && !digitSeen { + return l.errorf("cannot start float with a dot") + } + } + + if !digitSeen { + return l.errorf("no digit in that number") + } + if pointSeen { + l.emit(tokenFloat) + } else { + l.emit(tokenInteger) + } + return l.lexVoid +} + +// Entry point +func lexQuery(input string) chan token { + l := &queryLexer{ + input: input, + tokens: make(chan token), + line: 1, + col: 1, + } + go l.run() + return l.tokens +} diff --git a/vendor/github.com/pelletier/go-toml/query/lexer_test.go b/vendor/github.com/pelletier/go-toml/query/lexer_test.go new file mode 100644 index 00000000..8ce0501f --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/query/lexer_test.go @@ -0,0 +1,179 @@ +package query + +import ( + "github.com/pelletier/go-toml" + "testing" +) + +func testQLFlow(t *testing.T, input string, expectedFlow []token) { + ch := lexQuery(input) + for idx, expected := range expectedFlow { + token := <-ch + if token != expected { + t.Log("While testing #", idx, ":", input) + t.Log("compared (got)", token, "to (expected)", expected) + t.Log("\tvalue:", token.val, "<->", expected.val) + t.Log("\tvalue as bytes:", []byte(token.val), "<->", []byte(expected.val)) + t.Log("\ttype:", token.typ.String(), "<->", expected.typ.String()) + t.Log("\tline:", token.Line, "<->", expected.Line) + t.Log("\tcolumn:", token.Col, "<->", expected.Col) + t.Log("compared", token, "to", expected) + t.FailNow() + } + } + + tok, ok := <-ch + if ok { + t.Log("channel is not closed!") + t.Log(len(ch)+1, "tokens remaining:") + + t.Log("token ->", tok) + for token := range ch { + t.Log("token ->", token) + } + t.FailNow() + } +} + +func TestLexSpecialChars(t *testing.T) { + testQLFlow(t, " .$[]..()?*", []token{ + {toml.Position{1, 2}, tokenDot, "."}, + {toml.Position{1, 3}, tokenDollar, "$"}, + {toml.Position{1, 4}, tokenLeftBracket, "["}, + {toml.Position{1, 5}, tokenRightBracket, "]"}, + {toml.Position{1, 6}, tokenDotDot, ".."}, + {toml.Position{1, 8}, tokenLeftParen, "("}, + {toml.Position{1, 9}, tokenRightParen, ")"}, + {toml.Position{1, 10}, tokenQuestion, "?"}, + {toml.Position{1, 11}, tokenStar, "*"}, + {toml.Position{1, 12}, tokenEOF, ""}, + }) +} + +func TestLexString(t *testing.T) { + testQLFlow(t, "'foo\n'", []token{ + {toml.Position{1, 2}, tokenString, "foo\n"}, + {toml.Position{2, 2}, tokenEOF, ""}, + }) +} + +func TestLexDoubleString(t *testing.T) { + testQLFlow(t, `"bar"`, []token{ + {toml.Position{1, 2}, tokenString, "bar"}, + {toml.Position{1, 6}, tokenEOF, ""}, + }) +} + +func TestLexStringEscapes(t *testing.T) { + testQLFlow(t, `"foo \" \' \b \f \/ \t \r \\ \u03A9 \U00012345 \n bar"`, []token{ + {toml.Position{1, 2}, tokenString, "foo \" ' \b \f / \t \r \\ \u03A9 \U00012345 \n bar"}, + {toml.Position{1, 55}, tokenEOF, ""}, + }) +} + +func TestLexStringUnfinishedUnicode4(t *testing.T) { + testQLFlow(t, `"\u000"`, []token{ + {toml.Position{1, 2}, tokenError, "unfinished unicode escape"}, + }) +} + +func TestLexStringUnfinishedUnicode8(t *testing.T) { + testQLFlow(t, `"\U0000"`, []token{ + {toml.Position{1, 2}, tokenError, "unfinished unicode escape"}, + }) +} + +func TestLexStringInvalidEscape(t *testing.T) { + testQLFlow(t, `"\x"`, []token{ + {toml.Position{1, 2}, tokenError, "invalid escape sequence: \\x"}, + }) +} + +func TestLexStringUnfinished(t *testing.T) { + testQLFlow(t, `"bar`, []token{ + {toml.Position{1, 2}, tokenError, "unclosed string"}, + }) +} + +func TestLexKey(t *testing.T) { + testQLFlow(t, "foo", []token{ + {toml.Position{1, 1}, tokenKey, "foo"}, + {toml.Position{1, 4}, tokenEOF, ""}, + }) +} + +func TestLexRecurse(t *testing.T) { + testQLFlow(t, "$..*", []token{ + {toml.Position{1, 1}, tokenDollar, "$"}, + {toml.Position{1, 2}, tokenDotDot, ".."}, + {toml.Position{1, 4}, tokenStar, "*"}, + {toml.Position{1, 5}, tokenEOF, ""}, + }) +} + +func TestLexBracketKey(t *testing.T) { + testQLFlow(t, "$[foo]", []token{ + {toml.Position{1, 1}, tokenDollar, "$"}, + {toml.Position{1, 2}, tokenLeftBracket, "["}, + {toml.Position{1, 3}, tokenKey, "foo"}, + {toml.Position{1, 6}, tokenRightBracket, "]"}, + {toml.Position{1, 7}, tokenEOF, ""}, + }) +} + +func TestLexSpace(t *testing.T) { + testQLFlow(t, "foo bar baz", []token{ + {toml.Position{1, 1}, tokenKey, "foo"}, + {toml.Position{1, 5}, tokenKey, "bar"}, + {toml.Position{1, 9}, tokenKey, "baz"}, + {toml.Position{1, 12}, tokenEOF, ""}, + }) +} + +func TestLexInteger(t *testing.T) { + testQLFlow(t, "100 +200 -300", []token{ + {toml.Position{1, 1}, tokenInteger, "100"}, + {toml.Position{1, 5}, tokenInteger, "+200"}, + {toml.Position{1, 10}, tokenInteger, "-300"}, + {toml.Position{1, 14}, tokenEOF, ""}, + }) +} + +func TestLexFloat(t *testing.T) { + testQLFlow(t, "100.0 +200.0 -300.0", []token{ + {toml.Position{1, 1}, tokenFloat, "100.0"}, + {toml.Position{1, 7}, tokenFloat, "+200.0"}, + {toml.Position{1, 14}, tokenFloat, "-300.0"}, + {toml.Position{1, 20}, tokenEOF, ""}, + }) +} + +func TestLexFloatWithMultipleDots(t *testing.T) { + testQLFlow(t, "4.2.", []token{ + {toml.Position{1, 1}, tokenError, "cannot have two dots in one float"}, + }) +} + +func TestLexFloatLeadingDot(t *testing.T) { + testQLFlow(t, "+.1", []token{ + {toml.Position{1, 1}, tokenError, "cannot start float with a dot"}, + }) +} + +func TestLexFloatWithTrailingDot(t *testing.T) { + testQLFlow(t, "42.", []token{ + {toml.Position{1, 1}, tokenError, "float cannot end with a dot"}, + }) +} + +func TestLexNumberWithoutDigit(t *testing.T) { + testQLFlow(t, "+", []token{ + {toml.Position{1, 1}, tokenError, "no digit in that number"}, + }) +} + +func TestLexUnknown(t *testing.T) { + testQLFlow(t, "^", []token{ + {toml.Position{1, 1}, tokenError, "unexpected char: '94'"}, + }) +} diff --git a/vendor/github.com/pelletier/go-toml/query/match.go b/vendor/github.com/pelletier/go-toml/query/match.go new file mode 100644 index 00000000..d7bb15a4 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/query/match.go @@ -0,0 +1,232 @@ +package query + +import ( + "fmt" + "github.com/pelletier/go-toml" +) + +// base match +type matchBase struct { + next pathFn +} + +func (f *matchBase) setNext(next pathFn) { + f.next = next +} + +// terminating functor - gathers results +type terminatingFn struct { + // empty +} + +func newTerminatingFn() *terminatingFn { + return &terminatingFn{} +} + +func (f *terminatingFn) setNext(next pathFn) { + // do nothing +} + +func (f *terminatingFn) call(node interface{}, ctx *queryContext) { + ctx.result.appendResult(node, ctx.lastPosition) +} + +// match single key +type matchKeyFn struct { + matchBase + Name string +} + +func newMatchKeyFn(name string) *matchKeyFn { + return &matchKeyFn{Name: name} +} + +func (f *matchKeyFn) call(node interface{}, ctx *queryContext) { + if array, ok := node.([]*toml.Tree); ok { + for _, tree := range array { + item := tree.Get(f.Name) + if item != nil { + ctx.lastPosition = tree.GetPosition(f.Name) + f.next.call(item, ctx) + } + } + } else if tree, ok := node.(*toml.Tree); ok { + item := tree.Get(f.Name) + if item != nil { + ctx.lastPosition = tree.GetPosition(f.Name) + f.next.call(item, ctx) + } + } +} + +// match single index +type matchIndexFn struct { + matchBase + Idx int +} + +func newMatchIndexFn(idx int) *matchIndexFn { + return &matchIndexFn{Idx: idx} +} + +func (f *matchIndexFn) call(node interface{}, ctx *queryContext) { + if arr, ok := node.([]interface{}); ok { + if f.Idx < len(arr) && f.Idx >= 0 { + if treesArray, ok := node.([]*toml.Tree); ok { + if len(treesArray) > 0 { + ctx.lastPosition = treesArray[0].Position() + } + } + f.next.call(arr[f.Idx], ctx) + } + } +} + +// filter by slicing +type matchSliceFn struct { + matchBase + Start, End, Step int +} + +func newMatchSliceFn(start, end, step int) *matchSliceFn { + return &matchSliceFn{Start: start, End: end, Step: step} +} + +func (f *matchSliceFn) call(node interface{}, ctx *queryContext) { + if arr, ok := node.([]interface{}); ok { + // adjust indexes for negative values, reverse ordering + realStart, realEnd := f.Start, f.End + if realStart < 0 { + realStart = len(arr) + realStart + } + if realEnd < 0 { + realEnd = len(arr) + realEnd + } + if realEnd < realStart { + realEnd, realStart = realStart, realEnd // swap + } + // loop and gather + for idx := realStart; idx < realEnd; idx += f.Step { + if treesArray, ok := node.([]*toml.Tree); ok { + if len(treesArray) > 0 { + ctx.lastPosition = treesArray[0].Position() + } + } + f.next.call(arr[idx], ctx) + } + } +} + +// match anything +type matchAnyFn struct { + matchBase +} + +func newMatchAnyFn() *matchAnyFn { + return &matchAnyFn{} +} + +func (f *matchAnyFn) call(node interface{}, ctx *queryContext) { + if tree, ok := node.(*toml.Tree); ok { + for _, k := range tree.Keys() { + v := tree.Get(k) + ctx.lastPosition = tree.GetPosition(k) + f.next.call(v, ctx) + } + } +} + +// filter through union +type matchUnionFn struct { + Union []pathFn +} + +func (f *matchUnionFn) setNext(next pathFn) { + for _, fn := range f.Union { + fn.setNext(next) + } +} + +func (f *matchUnionFn) call(node interface{}, ctx *queryContext) { + for _, fn := range f.Union { + fn.call(node, ctx) + } +} + +// match every single last node in the tree +type matchRecursiveFn struct { + matchBase +} + +func newMatchRecursiveFn() *matchRecursiveFn { + return &matchRecursiveFn{} +} + +func (f *matchRecursiveFn) call(node interface{}, ctx *queryContext) { + originalPosition := ctx.lastPosition + if tree, ok := node.(*toml.Tree); ok { + var visit func(tree *toml.Tree) + visit = func(tree *toml.Tree) { + for _, k := range tree.Keys() { + v := tree.Get(k) + ctx.lastPosition = tree.GetPosition(k) + f.next.call(v, ctx) + switch node := v.(type) { + case *toml.Tree: + visit(node) + case []*toml.Tree: + for _, subtree := range node { + visit(subtree) + } + } + } + } + ctx.lastPosition = originalPosition + f.next.call(tree, ctx) + visit(tree) + } +} + +// match based on an externally provided functional filter +type matchFilterFn struct { + matchBase + Pos toml.Position + Name string +} + +func newMatchFilterFn(name string, pos toml.Position) *matchFilterFn { + return &matchFilterFn{Name: name, Pos: pos} +} + +func (f *matchFilterFn) call(node interface{}, ctx *queryContext) { + fn, ok := (*ctx.filters)[f.Name] + if !ok { + panic(fmt.Sprintf("%s: query context does not have filter '%s'", + f.Pos.String(), f.Name)) + } + switch castNode := node.(type) { + case *toml.Tree: + for _, k := range castNode.Keys() { + v := castNode.Get(k) + if fn(v) { + ctx.lastPosition = castNode.GetPosition(k) + f.next.call(v, ctx) + } + } + case []*toml.Tree: + for _, v := range castNode { + if fn(v) { + if len(castNode) > 0 { + ctx.lastPosition = castNode[0].Position() + } + f.next.call(v, ctx) + } + } + case []interface{}: + for _, v := range castNode { + if fn(v) { + f.next.call(v, ctx) + } + } + } +} diff --git a/vendor/github.com/pelletier/go-toml/query/match_test.go b/vendor/github.com/pelletier/go-toml/query/match_test.go new file mode 100644 index 00000000..429b8f6b --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/query/match_test.go @@ -0,0 +1,202 @@ +package query + +import ( + "fmt" + "github.com/pelletier/go-toml" + "testing" +) + +// dump path tree to a string +func pathString(root pathFn) string { + result := fmt.Sprintf("%T:", root) + switch fn := root.(type) { + case *terminatingFn: + result += "{}" + case *matchKeyFn: + result += fmt.Sprintf("{%s}", fn.Name) + result += pathString(fn.next) + case *matchIndexFn: + result += fmt.Sprintf("{%d}", fn.Idx) + result += pathString(fn.next) + case *matchSliceFn: + result += fmt.Sprintf("{%d:%d:%d}", + fn.Start, fn.End, fn.Step) + result += pathString(fn.next) + case *matchAnyFn: + result += "{}" + result += pathString(fn.next) + case *matchUnionFn: + result += "{[" + for _, v := range fn.Union { + result += pathString(v) + ", " + } + result += "]}" + case *matchRecursiveFn: + result += "{}" + result += pathString(fn.next) + case *matchFilterFn: + result += fmt.Sprintf("{%s}", fn.Name) + result += pathString(fn.next) + } + return result +} + +func assertPathMatch(t *testing.T, path, ref *Query) bool { + pathStr := pathString(path.root) + refStr := pathString(ref.root) + if pathStr != refStr { + t.Errorf("paths do not match") + t.Log("test:", pathStr) + t.Log("ref: ", refStr) + return false + } + return true +} + +func assertPath(t *testing.T, query string, ref *Query) { + path, _ := parseQuery(lexQuery(query)) + assertPathMatch(t, path, ref) +} + +func buildPath(parts ...pathFn) *Query { + query := newQuery() + for _, v := range parts { + query.appendPath(v) + } + return query +} + +func TestPathRoot(t *testing.T) { + assertPath(t, + "$", + buildPath( + // empty + )) +} + +func TestPathKey(t *testing.T) { + assertPath(t, + "$.foo", + buildPath( + newMatchKeyFn("foo"), + )) +} + +func TestPathBracketKey(t *testing.T) { + assertPath(t, + "$[foo]", + buildPath( + newMatchKeyFn("foo"), + )) +} + +func TestPathBracketStringKey(t *testing.T) { + assertPath(t, + "$['foo']", + buildPath( + newMatchKeyFn("foo"), + )) +} + +func TestPathIndex(t *testing.T) { + assertPath(t, + "$[123]", + buildPath( + newMatchIndexFn(123), + )) +} + +func TestPathSliceStart(t *testing.T) { + assertPath(t, + "$[123:]", + buildPath( + newMatchSliceFn(123, maxInt, 1), + )) +} + +func TestPathSliceStartEnd(t *testing.T) { + assertPath(t, + "$[123:456]", + buildPath( + newMatchSliceFn(123, 456, 1), + )) +} + +func TestPathSliceStartEndColon(t *testing.T) { + assertPath(t, + "$[123:456:]", + buildPath( + newMatchSliceFn(123, 456, 1), + )) +} + +func TestPathSliceStartStep(t *testing.T) { + assertPath(t, + "$[123::7]", + buildPath( + newMatchSliceFn(123, maxInt, 7), + )) +} + +func TestPathSliceEndStep(t *testing.T) { + assertPath(t, + "$[:456:7]", + buildPath( + newMatchSliceFn(0, 456, 7), + )) +} + +func TestPathSliceStep(t *testing.T) { + assertPath(t, + "$[::7]", + buildPath( + newMatchSliceFn(0, maxInt, 7), + )) +} + +func TestPathSliceAll(t *testing.T) { + assertPath(t, + "$[123:456:7]", + buildPath( + newMatchSliceFn(123, 456, 7), + )) +} + +func TestPathAny(t *testing.T) { + assertPath(t, + "$.*", + buildPath( + newMatchAnyFn(), + )) +} + +func TestPathUnion(t *testing.T) { + assertPath(t, + "$[foo, bar, baz]", + buildPath( + &matchUnionFn{[]pathFn{ + newMatchKeyFn("foo"), + newMatchKeyFn("bar"), + newMatchKeyFn("baz"), + }}, + )) +} + +func TestPathRecurse(t *testing.T) { + assertPath(t, + "$..*", + buildPath( + newMatchRecursiveFn(), + )) +} + +func TestPathFilterExpr(t *testing.T) { + assertPath(t, + "$[?('foo'),?(bar)]", + buildPath( + &matchUnionFn{[]pathFn{ + newMatchFilterFn("foo", toml.Position{}), + newMatchFilterFn("bar", toml.Position{}), + }}, + )) +} diff --git a/vendor/github.com/pelletier/go-toml/query/parser.go b/vendor/github.com/pelletier/go-toml/query/parser.go new file mode 100644 index 00000000..5f69b70d --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/query/parser.go @@ -0,0 +1,275 @@ +/* + Based on the "jsonpath" spec/concept. + + http://goessner.net/articles/JsonPath/ + https://code.google.com/p/json-path/ +*/ + +package query + +import ( + "fmt" +) + +const maxInt = int(^uint(0) >> 1) + +type queryParser struct { + flow chan token + tokensBuffer []token + query *Query + union []pathFn + err error +} + +type queryParserStateFn func() queryParserStateFn + +// Formats and panics an error message based on a token +func (p *queryParser) parseError(tok *token, msg string, args ...interface{}) queryParserStateFn { + p.err = fmt.Errorf(tok.Position.String()+": "+msg, args...) + return nil // trigger parse to end +} + +func (p *queryParser) run() { + for state := p.parseStart; state != nil; { + state = state() + } +} + +func (p *queryParser) backup(tok *token) { + p.tokensBuffer = append(p.tokensBuffer, *tok) +} + +func (p *queryParser) peek() *token { + if len(p.tokensBuffer) != 0 { + return &(p.tokensBuffer[0]) + } + + tok, ok := <-p.flow + if !ok { + return nil + } + p.backup(&tok) + return &tok +} + +func (p *queryParser) lookahead(types ...tokenType) bool { + result := true + buffer := []token{} + + for _, typ := range types { + tok := p.getToken() + if tok == nil { + result = false + break + } + buffer = append(buffer, *tok) + if tok.typ != typ { + result = false + break + } + } + // add the tokens back to the buffer, and return + p.tokensBuffer = append(p.tokensBuffer, buffer...) + return result +} + +func (p *queryParser) getToken() *token { + if len(p.tokensBuffer) != 0 { + tok := p.tokensBuffer[0] + p.tokensBuffer = p.tokensBuffer[1:] + return &tok + } + tok, ok := <-p.flow + if !ok { + return nil + } + return &tok +} + +func (p *queryParser) parseStart() queryParserStateFn { + tok := p.getToken() + + if tok == nil || tok.typ == tokenEOF { + return nil + } + + if tok.typ != tokenDollar { + return p.parseError(tok, "Expected '$' at start of expression") + } + + return p.parseMatchExpr +} + +// handle '.' prefix, '[]', and '..' +func (p *queryParser) parseMatchExpr() queryParserStateFn { + tok := p.getToken() + switch tok.typ { + case tokenDotDot: + p.query.appendPath(&matchRecursiveFn{}) + // nested parse for '..' + tok := p.getToken() + switch tok.typ { + case tokenKey: + p.query.appendPath(newMatchKeyFn(tok.val)) + return p.parseMatchExpr + case tokenLeftBracket: + return p.parseBracketExpr + case tokenStar: + // do nothing - the recursive predicate is enough + return p.parseMatchExpr + } + + case tokenDot: + // nested parse for '.' + tok := p.getToken() + switch tok.typ { + case tokenKey: + p.query.appendPath(newMatchKeyFn(tok.val)) + return p.parseMatchExpr + case tokenStar: + p.query.appendPath(&matchAnyFn{}) + return p.parseMatchExpr + } + + case tokenLeftBracket: + return p.parseBracketExpr + + case tokenEOF: + return nil // allow EOF at this stage + } + return p.parseError(tok, "expected match expression") +} + +func (p *queryParser) parseBracketExpr() queryParserStateFn { + if p.lookahead(tokenInteger, tokenColon) { + return p.parseSliceExpr + } + if p.peek().typ == tokenColon { + return p.parseSliceExpr + } + return p.parseUnionExpr +} + +func (p *queryParser) parseUnionExpr() queryParserStateFn { + var tok *token + + // this state can be traversed after some sub-expressions + // so be careful when setting up state in the parser + if p.union == nil { + p.union = []pathFn{} + } + +loop: // labeled loop for easy breaking + for { + if len(p.union) > 0 { + // parse delimiter or terminator + tok = p.getToken() + switch tok.typ { + case tokenComma: + // do nothing + case tokenRightBracket: + break loop + default: + return p.parseError(tok, "expected ',' or ']', not '%s'", tok.val) + } + } + + // parse sub expression + tok = p.getToken() + switch tok.typ { + case tokenInteger: + p.union = append(p.union, newMatchIndexFn(tok.Int())) + case tokenKey: + p.union = append(p.union, newMatchKeyFn(tok.val)) + case tokenString: + p.union = append(p.union, newMatchKeyFn(tok.val)) + case tokenQuestion: + return p.parseFilterExpr + default: + return p.parseError(tok, "expected union sub expression, not '%s', %d", tok.val, len(p.union)) + } + } + + // if there is only one sub-expression, use that instead + if len(p.union) == 1 { + p.query.appendPath(p.union[0]) + } else { + p.query.appendPath(&matchUnionFn{p.union}) + } + + p.union = nil // clear out state + return p.parseMatchExpr +} + +func (p *queryParser) parseSliceExpr() queryParserStateFn { + // init slice to grab all elements + start, end, step := 0, maxInt, 1 + + // parse optional start + tok := p.getToken() + if tok.typ == tokenInteger { + start = tok.Int() + tok = p.getToken() + } + if tok.typ != tokenColon { + return p.parseError(tok, "expected ':'") + } + + // parse optional end + tok = p.getToken() + if tok.typ == tokenInteger { + end = tok.Int() + tok = p.getToken() + } + if tok.typ == tokenRightBracket { + p.query.appendPath(newMatchSliceFn(start, end, step)) + return p.parseMatchExpr + } + if tok.typ != tokenColon { + return p.parseError(tok, "expected ']' or ':'") + } + + // parse optional step + tok = p.getToken() + if tok.typ == tokenInteger { + step = tok.Int() + if step < 0 { + return p.parseError(tok, "step must be a positive value") + } + tok = p.getToken() + } + if tok.typ != tokenRightBracket { + return p.parseError(tok, "expected ']'") + } + + p.query.appendPath(newMatchSliceFn(start, end, step)) + return p.parseMatchExpr +} + +func (p *queryParser) parseFilterExpr() queryParserStateFn { + tok := p.getToken() + if tok.typ != tokenLeftParen { + return p.parseError(tok, "expected left-parenthesis for filter expression") + } + tok = p.getToken() + if tok.typ != tokenKey && tok.typ != tokenString { + return p.parseError(tok, "expected key or string for filter function name") + } + name := tok.val + tok = p.getToken() + if tok.typ != tokenRightParen { + return p.parseError(tok, "expected right-parenthesis for filter expression") + } + p.union = append(p.union, newMatchFilterFn(name, tok.Position)) + return p.parseUnionExpr +} + +func parseQuery(flow chan token) (*Query, error) { + parser := &queryParser{ + flow: flow, + tokensBuffer: []token{}, + query: newQuery(), + } + parser.run() + return parser.query, parser.err +} diff --git a/vendor/github.com/pelletier/go-toml/query/parser_test.go b/vendor/github.com/pelletier/go-toml/query/parser_test.go new file mode 100644 index 00000000..473896a0 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/query/parser_test.go @@ -0,0 +1,482 @@ +package query + +import ( + "fmt" + "github.com/pelletier/go-toml" + "io/ioutil" + "sort" + "strings" + "testing" + "time" +) + +type queryTestNode struct { + value interface{} + position toml.Position +} + +func valueString(root interface{}) string { + result := "" //fmt.Sprintf("%T:", root) + switch node := root.(type) { + case *Result: + items := []string{} + for i, v := range node.Values() { + items = append(items, fmt.Sprintf("%s:%s", + node.Positions()[i].String(), valueString(v))) + } + sort.Strings(items) + result = "[" + strings.Join(items, ", ") + "]" + case queryTestNode: + result = fmt.Sprintf("%s:%s", + node.position.String(), valueString(node.value)) + case []interface{}: + items := []string{} + for _, v := range node { + items = append(items, valueString(v)) + } + sort.Strings(items) + result = "[" + strings.Join(items, ", ") + "]" + case *toml.Tree: + // workaround for unreliable map key ordering + items := []string{} + for _, k := range node.Keys() { + v := node.GetPath([]string{k}) + items = append(items, k+":"+valueString(v)) + } + sort.Strings(items) + result = "{" + strings.Join(items, ", ") + "}" + case map[string]interface{}: + // workaround for unreliable map key ordering + items := []string{} + for k, v := range node { + items = append(items, k+":"+valueString(v)) + } + sort.Strings(items) + result = "{" + strings.Join(items, ", ") + "}" + case int64: + result += fmt.Sprintf("%d", node) + case string: + result += "'" + node + "'" + case float64: + result += fmt.Sprintf("%f", node) + case bool: + result += fmt.Sprintf("%t", node) + case time.Time: + result += fmt.Sprintf("'%v'", node) + } + return result +} + +func assertValue(t *testing.T, result, ref interface{}) { + pathStr := valueString(result) + refStr := valueString(ref) + if pathStr != refStr { + t.Errorf("values do not match") + t.Log("test:", pathStr) + t.Log("ref: ", refStr) + } +} + +func assertQueryPositions(t *testing.T, tomlDoc string, query string, ref []interface{}) { + tree, err := toml.Load(tomlDoc) + if err != nil { + t.Errorf("Non-nil toml parse error: %v", err) + return + } + q, err := Compile(query) + if err != nil { + t.Error(err) + return + } + results := q.Execute(tree) + assertValue(t, results, ref) +} + +func TestQueryRoot(t *testing.T) { + assertQueryPositions(t, + "a = 42", + "$", + []interface{}{ + queryTestNode{ + map[string]interface{}{ + "a": int64(42), + }, toml.Position{1, 1}, + }, + }) +} + +func TestQueryKey(t *testing.T) { + assertQueryPositions(t, + "[foo]\na = 42", + "$.foo.a", + []interface{}{ + queryTestNode{ + int64(42), toml.Position{2, 1}, + }, + }) +} + +func TestQueryKeyString(t *testing.T) { + assertQueryPositions(t, + "[foo]\na = 42", + "$.foo['a']", + []interface{}{ + queryTestNode{ + int64(42), toml.Position{2, 1}, + }, + }) +} + +func TestQueryIndex(t *testing.T) { + assertQueryPositions(t, + "[foo]\na = [1,2,3,4,5,6,7,8,9,0]", + "$.foo.a[5]", + []interface{}{ + queryTestNode{ + int64(6), toml.Position{2, 1}, + }, + }) +} + +func TestQuerySliceRange(t *testing.T) { + assertQueryPositions(t, + "[foo]\na = [1,2,3,4,5,6,7,8,9,0]", + "$.foo.a[0:5]", + []interface{}{ + queryTestNode{ + int64(1), toml.Position{2, 1}, + }, + queryTestNode{ + int64(2), toml.Position{2, 1}, + }, + queryTestNode{ + int64(3), toml.Position{2, 1}, + }, + queryTestNode{ + int64(4), toml.Position{2, 1}, + }, + queryTestNode{ + int64(5), toml.Position{2, 1}, + }, + }) +} + +func TestQuerySliceStep(t *testing.T) { + assertQueryPositions(t, + "[foo]\na = [1,2,3,4,5,6,7,8,9,0]", + "$.foo.a[0:5:2]", + []interface{}{ + queryTestNode{ + int64(1), toml.Position{2, 1}, + }, + queryTestNode{ + int64(3), toml.Position{2, 1}, + }, + queryTestNode{ + int64(5), toml.Position{2, 1}, + }, + }) +} + +func TestQueryAny(t *testing.T) { + assertQueryPositions(t, + "[foo.bar]\na=1\nb=2\n[foo.baz]\na=3\nb=4", + "$.foo.*", + []interface{}{ + queryTestNode{ + map[string]interface{}{ + "a": int64(1), + "b": int64(2), + }, toml.Position{1, 1}, + }, + queryTestNode{ + map[string]interface{}{ + "a": int64(3), + "b": int64(4), + }, toml.Position{4, 1}, + }, + }) +} +func TestQueryUnionSimple(t *testing.T) { + assertQueryPositions(t, + "[foo.bar]\na=1\nb=2\n[baz.foo]\na=3\nb=4\n[gorf.foo]\na=5\nb=6", + "$.*[bar,foo]", + []interface{}{ + queryTestNode{ + map[string]interface{}{ + "a": int64(1), + "b": int64(2), + }, toml.Position{1, 1}, + }, + queryTestNode{ + map[string]interface{}{ + "a": int64(3), + "b": int64(4), + }, toml.Position{4, 1}, + }, + queryTestNode{ + map[string]interface{}{ + "a": int64(5), + "b": int64(6), + }, toml.Position{7, 1}, + }, + }) +} + +func TestQueryRecursionAll(t *testing.T) { + assertQueryPositions(t, + "[foo.bar]\na=1\nb=2\n[baz.foo]\na=3\nb=4\n[gorf.foo]\na=5\nb=6", + "$..*", + []interface{}{ + queryTestNode{ + map[string]interface{}{ + "foo": map[string]interface{}{ + "bar": map[string]interface{}{ + "a": int64(1), + "b": int64(2), + }, + }, + "baz": map[string]interface{}{ + "foo": map[string]interface{}{ + "a": int64(3), + "b": int64(4), + }, + }, + "gorf": map[string]interface{}{ + "foo": map[string]interface{}{ + "a": int64(5), + "b": int64(6), + }, + }, + }, toml.Position{1, 1}, + }, + queryTestNode{ + map[string]interface{}{ + "bar": map[string]interface{}{ + "a": int64(1), + "b": int64(2), + }, + }, toml.Position{1, 1}, + }, + queryTestNode{ + map[string]interface{}{ + "a": int64(1), + "b": int64(2), + }, toml.Position{1, 1}, + }, + queryTestNode{ + int64(1), toml.Position{2, 1}, + }, + queryTestNode{ + int64(2), toml.Position{3, 1}, + }, + queryTestNode{ + map[string]interface{}{ + "foo": map[string]interface{}{ + "a": int64(3), + "b": int64(4), + }, + }, toml.Position{4, 1}, + }, + queryTestNode{ + map[string]interface{}{ + "a": int64(3), + "b": int64(4), + }, toml.Position{4, 1}, + }, + queryTestNode{ + int64(3), toml.Position{5, 1}, + }, + queryTestNode{ + int64(4), toml.Position{6, 1}, + }, + queryTestNode{ + map[string]interface{}{ + "foo": map[string]interface{}{ + "a": int64(5), + "b": int64(6), + }, + }, toml.Position{7, 1}, + }, + queryTestNode{ + map[string]interface{}{ + "a": int64(5), + "b": int64(6), + }, toml.Position{7, 1}, + }, + queryTestNode{ + int64(5), toml.Position{8, 1}, + }, + queryTestNode{ + int64(6), toml.Position{9, 1}, + }, + }) +} + +func TestQueryRecursionUnionSimple(t *testing.T) { + assertQueryPositions(t, + "[foo.bar]\na=1\nb=2\n[baz.foo]\na=3\nb=4\n[gorf.foo]\na=5\nb=6", + "$..['foo','bar']", + []interface{}{ + queryTestNode{ + map[string]interface{}{ + "bar": map[string]interface{}{ + "a": int64(1), + "b": int64(2), + }, + }, toml.Position{1, 1}, + }, + queryTestNode{ + map[string]interface{}{ + "a": int64(3), + "b": int64(4), + }, toml.Position{4, 1}, + }, + queryTestNode{ + map[string]interface{}{ + "a": int64(1), + "b": int64(2), + }, toml.Position{1, 1}, + }, + queryTestNode{ + map[string]interface{}{ + "a": int64(5), + "b": int64(6), + }, toml.Position{7, 1}, + }, + }) +} + +func TestQueryFilterFn(t *testing.T) { + buff, err := ioutil.ReadFile("../example.toml") + if err != nil { + t.Error(err) + return + } + + assertQueryPositions(t, string(buff), + "$..[?(int)]", + []interface{}{ + queryTestNode{ + int64(8001), toml.Position{13, 1}, + }, + queryTestNode{ + int64(8001), toml.Position{13, 1}, + }, + queryTestNode{ + int64(8002), toml.Position{13, 1}, + }, + queryTestNode{ + int64(5000), toml.Position{14, 1}, + }, + }) + + assertQueryPositions(t, string(buff), + "$..[?(string)]", + []interface{}{ + queryTestNode{ + "TOML Example", toml.Position{3, 1}, + }, + queryTestNode{ + "Tom Preston-Werner", toml.Position{6, 1}, + }, + queryTestNode{ + "GitHub", toml.Position{7, 1}, + }, + queryTestNode{ + "GitHub Cofounder & CEO\nLikes tater tots and beer.", + toml.Position{8, 1}, + }, + queryTestNode{ + "192.168.1.1", toml.Position{12, 1}, + }, + queryTestNode{ + "10.0.0.1", toml.Position{21, 3}, + }, + queryTestNode{ + "eqdc10", toml.Position{22, 3}, + }, + queryTestNode{ + "10.0.0.2", toml.Position{25, 3}, + }, + queryTestNode{ + "eqdc10", toml.Position{26, 3}, + }, + }) + + assertQueryPositions(t, string(buff), + "$..[?(float)]", + []interface{}{ + // no float values in document + }) + + tv, _ := time.Parse(time.RFC3339, "1979-05-27T07:32:00Z") + assertQueryPositions(t, string(buff), + "$..[?(tree)]", + []interface{}{ + queryTestNode{ + map[string]interface{}{ + "name": "Tom Preston-Werner", + "organization": "GitHub", + "bio": "GitHub Cofounder & CEO\nLikes tater tots and beer.", + "dob": tv, + }, toml.Position{5, 1}, + }, + queryTestNode{ + map[string]interface{}{ + "server": "192.168.1.1", + "ports": []interface{}{int64(8001), int64(8001), int64(8002)}, + "connection_max": int64(5000), + "enabled": true, + }, toml.Position{11, 1}, + }, + queryTestNode{ + map[string]interface{}{ + "alpha": map[string]interface{}{ + "ip": "10.0.0.1", + "dc": "eqdc10", + }, + "beta": map[string]interface{}{ + "ip": "10.0.0.2", + "dc": "eqdc10", + }, + }, toml.Position{17, 1}, + }, + queryTestNode{ + map[string]interface{}{ + "ip": "10.0.0.1", + "dc": "eqdc10", + }, toml.Position{20, 3}, + }, + queryTestNode{ + map[string]interface{}{ + "ip": "10.0.0.2", + "dc": "eqdc10", + }, toml.Position{24, 3}, + }, + queryTestNode{ + map[string]interface{}{ + "data": []interface{}{ + []interface{}{"gamma", "delta"}, + []interface{}{int64(1), int64(2)}, + }, + }, toml.Position{28, 1}, + }, + }) + + assertQueryPositions(t, string(buff), + "$..[?(time)]", + []interface{}{ + queryTestNode{ + tv, toml.Position{9, 1}, + }, + }) + + assertQueryPositions(t, string(buff), + "$..[?(bool)]", + []interface{}{ + queryTestNode{ + true, toml.Position{15, 1}, + }, + }) +} diff --git a/vendor/github.com/pelletier/go-toml/query/query.go b/vendor/github.com/pelletier/go-toml/query/query.go new file mode 100644 index 00000000..1c6cd801 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/query/query.go @@ -0,0 +1,158 @@ +package query + +import ( + "time" + + "github.com/pelletier/go-toml" +) + +// NodeFilterFn represents a user-defined filter function, for use with +// Query.SetFilter(). +// +// The return value of the function must indicate if 'node' is to be included +// at this stage of the TOML path. Returning true will include the node, and +// returning false will exclude it. +// +// NOTE: Care should be taken to write script callbacks such that they are safe +// to use from multiple goroutines. +type NodeFilterFn func(node interface{}) bool + +// Result is the result of Executing a Query. +type Result struct { + items []interface{} + positions []toml.Position +} + +// appends a value/position pair to the result set. +func (r *Result) appendResult(node interface{}, pos toml.Position) { + r.items = append(r.items, node) + r.positions = append(r.positions, pos) +} + +// Values is a set of values within a Result. The order of values is not +// guaranteed to be in document order, and may be different each time a query is +// executed. +func (r Result) Values() []interface{} { + return r.items +} + +// Positions is a set of positions for values within a Result. Each index +// in Positions() corresponds to the entry in Value() of the same index. +func (r Result) Positions() []toml.Position { + return r.positions +} + +// runtime context for executing query paths +type queryContext struct { + result *Result + filters *map[string]NodeFilterFn + lastPosition toml.Position +} + +// generic path functor interface +type pathFn interface { + setNext(next pathFn) + // it is the caller's responsibility to set the ctx.lastPosition before invoking call() + // node can be one of: *toml.Tree, []*toml.Tree, or a scalar + call(node interface{}, ctx *queryContext) +} + +// A Query is the representation of a compiled TOML path. A Query is safe +// for concurrent use by multiple goroutines. +type Query struct { + root pathFn + tail pathFn + filters *map[string]NodeFilterFn +} + +func newQuery() *Query { + return &Query{ + root: nil, + tail: nil, + filters: &defaultFilterFunctions, + } +} + +func (q *Query) appendPath(next pathFn) { + if q.root == nil { + q.root = next + } else { + q.tail.setNext(next) + } + q.tail = next + next.setNext(newTerminatingFn()) // init the next functor +} + +// Compile compiles a TOML path expression. The returned Query can be used +// to match elements within a Tree and its descendants. See Execute. +func Compile(path string) (*Query, error) { + return parseQuery(lexQuery(path)) +} + +// Execute executes a query against a Tree, and returns the result of the query. +func (q *Query) Execute(tree *toml.Tree) *Result { + result := &Result{ + items: []interface{}{}, + positions: []toml.Position{}, + } + if q.root == nil { + result.appendResult(tree, tree.GetPosition("")) + } else { + ctx := &queryContext{ + result: result, + filters: q.filters, + } + ctx.lastPosition = tree.Position() + q.root.call(tree, ctx) + } + return result +} + +// CompileAndExecute is a shorthand for Compile(path) followed by Execute(tree). +func CompileAndExecute(path string, tree *toml.Tree) (*Result, error) { + query, err := Compile(path) + if err != nil { + return nil, err + } + return query.Execute(tree), nil +} + +// SetFilter sets a user-defined filter function. These may be used inside +// "?(..)" query expressions to filter TOML document elements within a query. +func (q *Query) SetFilter(name string, fn NodeFilterFn) { + if q.filters == &defaultFilterFunctions { + // clone the static table + q.filters = &map[string]NodeFilterFn{} + for k, v := range defaultFilterFunctions { + (*q.filters)[k] = v + } + } + (*q.filters)[name] = fn +} + +var defaultFilterFunctions = map[string]NodeFilterFn{ + "tree": func(node interface{}) bool { + _, ok := node.(*toml.Tree) + return ok + }, + "int": func(node interface{}) bool { + _, ok := node.(int64) + return ok + }, + "float": func(node interface{}) bool { + _, ok := node.(float64) + return ok + }, + "string": func(node interface{}) bool { + _, ok := node.(string) + return ok + }, + "time": func(node interface{}) bool { + _, ok := node.(time.Time) + return ok + }, + "bool": func(node interface{}) bool { + _, ok := node.(bool) + return ok + }, +} diff --git a/vendor/github.com/pelletier/go-toml/query/query_test.go b/vendor/github.com/pelletier/go-toml/query/query_test.go new file mode 100644 index 00000000..903a8dc7 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/query/query_test.go @@ -0,0 +1,157 @@ +package query + +import ( + "fmt" + "testing" + + "github.com/pelletier/go-toml" +) + +func assertArrayContainsInAnyOrder(t *testing.T, array []interface{}, objects ...interface{}) { + if len(array) != len(objects) { + t.Fatalf("array contains %d objects but %d are expected", len(array), len(objects)) + } + + for _, o := range objects { + found := false + for _, a := range array { + if a == o { + found = true + break + } + } + if !found { + t.Fatal(o, "not found in array", array) + } + } +} + +func TestQueryExample(t *testing.T) { + config, _ := toml.Load(` + [[book]] + title = "The Stand" + author = "Stephen King" + [[book]] + title = "For Whom the Bell Tolls" + author = "Ernest Hemmingway" + [[book]] + title = "Neuromancer" + author = "William Gibson" + `) + authors, err := CompileAndExecute("$.book.author", config) + if err != nil { + t.Fatal("unexpected error:", err) + } + names := authors.Values() + if len(names) != 3 { + t.Fatalf("query should return 3 names but returned %d", len(names)) + } + assertArrayContainsInAnyOrder(t, names, "Stephen King", "Ernest Hemmingway", "William Gibson") +} + +func TestQueryReadmeExample(t *testing.T) { + config, _ := toml.Load(` +[postgres] +user = "pelletier" +password = "mypassword" +`) + + query, err := Compile("$..[user,password]") + if err != nil { + t.Fatal("unexpected error:", err) + } + results := query.Execute(config) + values := results.Values() + if len(values) != 2 { + t.Fatalf("query should return 2 values but returned %d", len(values)) + } + assertArrayContainsInAnyOrder(t, values, "pelletier", "mypassword") +} + +func TestQueryPathNotPresent(t *testing.T) { + config, _ := toml.Load(`a = "hello"`) + query, err := Compile("$.foo.bar") + if err != nil { + t.Fatal("unexpected error:", err) + } + results := query.Execute(config) + if err != nil { + t.Fatalf("err should be nil. got %s instead", err) + } + if len(results.items) != 0 { + t.Fatalf("no items should be matched. %d matched instead", len(results.items)) + } +} + +func ExampleNodeFilterFn_filterExample() { + tree, _ := toml.Load(` + [struct_one] + foo = "foo" + bar = "bar" + + [struct_two] + baz = "baz" + gorf = "gorf" + `) + + // create a query that references a user-defined-filter + query, _ := Compile("$[?(bazOnly)]") + + // define the filter, and assign it to the query + query.SetFilter("bazOnly", func(node interface{}) bool { + if tree, ok := node.(*toml.Tree); ok { + return tree.Has("baz") + } + return false // reject all other node types + }) + + // results contain only the 'struct_two' Tree + query.Execute(tree) +} + +func ExampleQuery_queryExample() { + config, _ := toml.Load(` + [[book]] + title = "The Stand" + author = "Stephen King" + [[book]] + title = "For Whom the Bell Tolls" + author = "Ernest Hemmingway" + [[book]] + title = "Neuromancer" + author = "William Gibson" + `) + + // find and print all the authors in the document + query, _ := Compile("$.book.author") + authors := query.Execute(config) + for _, name := range authors.Values() { + fmt.Println(name) + } +} + +func TestTomlQuery(t *testing.T) { + tree, err := toml.Load("[foo.bar]\na=1\nb=2\n[baz.foo]\na=3\nb=4\n[gorf.foo]\na=5\nb=6") + if err != nil { + t.Error(err) + return + } + query, err := Compile("$.foo.bar") + if err != nil { + t.Error(err) + return + } + result := query.Execute(tree) + values := result.Values() + if len(values) != 1 { + t.Errorf("Expected resultset of 1, got %d instead: %v", len(values), values) + } + + if tt, ok := values[0].(*toml.Tree); !ok { + t.Errorf("Expected type of Tree: %T", values[0]) + } else if tt.Get("a") != int64(1) { + t.Errorf("Expected 'a' with a value 1: %v", tt.Get("a")) + } else if tt.Get("b") != int64(2) { + t.Errorf("Expected 'b' with a value 2: %v", tt.Get("b")) + } +} diff --git a/vendor/github.com/pelletier/go-toml/query/tokens.go b/vendor/github.com/pelletier/go-toml/query/tokens.go new file mode 100644 index 00000000..9ae579de --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/query/tokens.go @@ -0,0 +1,106 @@ +package query + +import ( + "fmt" + "github.com/pelletier/go-toml" + "strconv" + "unicode" +) + +// Define tokens +type tokenType int + +const ( + eof = -(iota + 1) +) + +const ( + tokenError tokenType = iota + tokenEOF + tokenKey + tokenString + tokenInteger + tokenFloat + tokenLeftBracket + tokenRightBracket + tokenLeftParen + tokenRightParen + tokenComma + tokenColon + tokenDollar + tokenStar + tokenQuestion + tokenDot + tokenDotDot +) + +var tokenTypeNames = []string{ + "Error", + "EOF", + "Key", + "String", + "Integer", + "Float", + "[", + "]", + "(", + ")", + ",", + ":", + "$", + "*", + "?", + ".", + "..", +} + +type token struct { + toml.Position + typ tokenType + val string +} + +func (tt tokenType) String() string { + idx := int(tt) + if idx < len(tokenTypeNames) { + return tokenTypeNames[idx] + } + return "Unknown" +} + +func (t token) Int() int { + if result, err := strconv.Atoi(t.val); err != nil { + panic(err) + } else { + return result + } +} + +func (t token) String() string { + switch t.typ { + case tokenEOF: + return "EOF" + case tokenError: + return t.val + } + + return fmt.Sprintf("%q", t.val) +} + +func isSpace(r rune) bool { + return r == ' ' || r == '\t' +} + +func isAlphanumeric(r rune) bool { + return unicode.IsLetter(r) || r == '_' +} + +func isDigit(r rune) bool { + return unicode.IsNumber(r) +} + +func isHexDigit(r rune) bool { + return isDigit(r) || + (r >= 'a' && r <= 'f') || + (r >= 'A' && r <= 'F') +} diff --git a/vendor/github.com/pelletier/go-toml/test.sh b/vendor/github.com/pelletier/go-toml/test.sh new file mode 100755 index 00000000..a70a8b02 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/test.sh @@ -0,0 +1,91 @@ +#!/bin/bash +# fail out of the script if anything here fails +set -e +set -o pipefail + +# set the path to the present working directory +export GOPATH=`pwd` + +function git_clone() { + path=$1 + branch=$2 + version=$3 + if [ ! -d "src/$path" ]; then + mkdir -p src/$path + git clone https://$path.git src/$path + fi + pushd src/$path + git checkout "$branch" + git reset --hard "$version" + popd +} + +# Remove potential previous runs +rm -rf src test_program_bin toml-test + +# Run go vet +go vet ./... + +go get github.com/pelletier/go-buffruneio +go get github.com/davecgh/go-spew/spew +go get gopkg.in/yaml.v2 +go get github.com/BurntSushi/toml + +# get code for BurntSushi TOML validation +# pinning all to 'HEAD' for version 0.3.x work (TODO: pin to commit hash when tests stabilize) +git_clone github.com/BurntSushi/toml master HEAD +git_clone github.com/BurntSushi/toml-test master HEAD #was: 0.2.0 HEAD + +# build the BurntSushi test application +go build -o toml-test github.com/BurntSushi/toml-test + +# vendorize the current lib for testing +# NOTE: this basically mocks an install without having to go back out to github for code +mkdir -p src/github.com/pelletier/go-toml/cmd +mkdir -p src/github.com/pelletier/go-toml/query +cp *.go *.toml src/github.com/pelletier/go-toml +cp -R cmd/* src/github.com/pelletier/go-toml/cmd +cp -R query/* src/github.com/pelletier/go-toml/query +go build -o test_program_bin src/github.com/pelletier/go-toml/cmd/test_program.go + +# Run basic unit tests +go test github.com/pelletier/go-toml -covermode=count -coverprofile=coverage.out +go test github.com/pelletier/go-toml/cmd/tomljson +go test github.com/pelletier/go-toml/query + +# run the entire BurntSushi test suite +if [[ $# -eq 0 ]] ; then + echo "Running all BurntSushi tests" + ./toml-test ./test_program_bin | tee test_out +else + # run a specific test + test=$1 + test_path='src/github.com/BurntSushi/toml-test/tests' + valid_test="$test_path/valid/$test" + invalid_test="$test_path/invalid/$test" + + if [ -e "$valid_test.toml" ]; then + echo "Valid Test TOML for $test:" + echo "====" + cat "$valid_test.toml" + + echo "Valid Test JSON for $test:" + echo "====" + cat "$valid_test.json" + + echo "Go-TOML Output for $test:" + echo "====" + cat "$valid_test.toml" | ./test_program_bin + fi + + if [ -e "$invalid_test.toml" ]; then + echo "Invalid Test TOML for $test:" + echo "====" + cat "$invalid_test.toml" + + echo "Go-TOML Output for $test:" + echo "====" + echo "go-toml Output:" + cat "$invalid_test.toml" | ./test_program_bin + fi +fi diff --git a/vendor/github.com/pelletier/go-toml/token.go b/vendor/github.com/pelletier/go-toml/token.go new file mode 100644 index 00000000..1a908134 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/token.go @@ -0,0 +1,144 @@ +package toml + +import ( + "fmt" + "strconv" + "unicode" +) + +// Define tokens +type tokenType int + +const ( + eof = -(iota + 1) +) + +const ( + tokenError tokenType = iota + tokenEOF + tokenComment + tokenKey + tokenString + tokenInteger + tokenTrue + tokenFalse + tokenFloat + tokenInf + tokenNan + tokenEqual + tokenLeftBracket + tokenRightBracket + tokenLeftCurlyBrace + tokenRightCurlyBrace + tokenLeftParen + tokenRightParen + tokenDoubleLeftBracket + tokenDoubleRightBracket + tokenDate + tokenKeyGroup + tokenKeyGroupArray + tokenComma + tokenColon + tokenDollar + tokenStar + tokenQuestion + tokenDot + tokenDotDot + tokenEOL +) + +var tokenTypeNames = []string{ + "Error", + "EOF", + "Comment", + "Key", + "String", + "Integer", + "True", + "False", + "Float", + "Inf", + "NaN", + "=", + "[", + "]", + "{", + "}", + "(", + ")", + "]]", + "[[", + "Date", + "KeyGroup", + "KeyGroupArray", + ",", + ":", + "$", + "*", + "?", + ".", + "..", + "EOL", +} + +type token struct { + Position + typ tokenType + val string +} + +func (tt tokenType) String() string { + idx := int(tt) + if idx < len(tokenTypeNames) { + return tokenTypeNames[idx] + } + return "Unknown" +} + +func (t token) Int() int { + if result, err := strconv.Atoi(t.val); err != nil { + panic(err) + } else { + return result + } +} + +func (t token) String() string { + switch t.typ { + case tokenEOF: + return "EOF" + case tokenError: + return t.val + } + + return fmt.Sprintf("%q", t.val) +} + +func isSpace(r rune) bool { + return r == ' ' || r == '\t' +} + +func isAlphanumeric(r rune) bool { + return unicode.IsLetter(r) || r == '_' +} + +func isKeyChar(r rune) bool { + // Keys start with the first character that isn't whitespace or [ and end + // with the last non-whitespace character before the equals sign. Keys + // cannot contain a # character." + return !(r == '\r' || r == '\n' || r == eof || r == '=') +} + +func isKeyStartChar(r rune) bool { + return !(isSpace(r) || r == '\r' || r == '\n' || r == eof || r == '[') +} + +func isDigit(r rune) bool { + return unicode.IsNumber(r) +} + +func isHexDigit(r rune) bool { + return isDigit(r) || + (r >= 'a' && r <= 'f') || + (r >= 'A' && r <= 'F') +} diff --git a/vendor/github.com/pelletier/go-toml/token_test.go b/vendor/github.com/pelletier/go-toml/token_test.go new file mode 100644 index 00000000..20b560d5 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/token_test.go @@ -0,0 +1,67 @@ +package toml + +import "testing" + +func TestTokenStringer(t *testing.T) { + var tests = []struct { + tt tokenType + expect string + }{ + {tokenError, "Error"}, + {tokenEOF, "EOF"}, + {tokenComment, "Comment"}, + {tokenKey, "Key"}, + {tokenString, "String"}, + {tokenInteger, "Integer"}, + {tokenTrue, "True"}, + {tokenFalse, "False"}, + {tokenFloat, "Float"}, + {tokenEqual, "="}, + {tokenLeftBracket, "["}, + {tokenRightBracket, "]"}, + {tokenLeftCurlyBrace, "{"}, + {tokenRightCurlyBrace, "}"}, + {tokenLeftParen, "("}, + {tokenRightParen, ")"}, + {tokenDoubleLeftBracket, "]]"}, + {tokenDoubleRightBracket, "[["}, + {tokenDate, "Date"}, + {tokenKeyGroup, "KeyGroup"}, + {tokenKeyGroupArray, "KeyGroupArray"}, + {tokenComma, ","}, + {tokenColon, ":"}, + {tokenDollar, "$"}, + {tokenStar, "*"}, + {tokenQuestion, "?"}, + {tokenDot, "."}, + {tokenDotDot, ".."}, + {tokenEOL, "EOL"}, + {tokenEOL + 1, "Unknown"}, + } + + for i, test := range tests { + got := test.tt.String() + if got != test.expect { + t.Errorf("[%d] invalid string of token type; got %q, expected %q", i, got, test.expect) + } + } +} + +func TestTokenString(t *testing.T) { + var tests = []struct { + tok token + expect string + }{ + {token{Position{1, 1}, tokenEOF, ""}, "EOF"}, + {token{Position{1, 1}, tokenError, "Δt"}, "Δt"}, + {token{Position{1, 1}, tokenString, "bar"}, `"bar"`}, + {token{Position{1, 1}, tokenString, "123456789012345"}, `"123456789012345"`}, + } + + for i, test := range tests { + got := test.tok.String() + if got != test.expect { + t.Errorf("[%d] invalid of string token; got %q, expected %q", i, got, test.expect) + } + } +} diff --git a/vendor/github.com/pelletier/go-toml/toml.go b/vendor/github.com/pelletier/go-toml/toml.go new file mode 100644 index 00000000..05493a44 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/toml.go @@ -0,0 +1,309 @@ +package toml + +import ( + "errors" + "fmt" + "io" + "io/ioutil" + "os" + "runtime" + "strings" +) + +type tomlValue struct { + value interface{} // string, int64, uint64, float64, bool, time.Time, [] of any of this list + comment string + commented bool + position Position +} + +// Tree is the result of the parsing of a TOML file. +type Tree struct { + values map[string]interface{} // string -> *tomlValue, *Tree, []*Tree + comment string + commented bool + position Position +} + +func newTree() *Tree { + return &Tree{ + values: make(map[string]interface{}), + position: Position{}, + } +} + +// TreeFromMap initializes a new Tree object using the given map. +func TreeFromMap(m map[string]interface{}) (*Tree, error) { + result, err := toTree(m) + if err != nil { + return nil, err + } + return result.(*Tree), nil +} + +// Position returns the position of the tree. +func (t *Tree) Position() Position { + return t.position +} + +// Has returns a boolean indicating if the given key exists. +func (t *Tree) Has(key string) bool { + if key == "" { + return false + } + return t.HasPath(strings.Split(key, ".")) +} + +// HasPath returns true if the given path of keys exists, false otherwise. +func (t *Tree) HasPath(keys []string) bool { + return t.GetPath(keys) != nil +} + +// Keys returns the keys of the toplevel tree (does not recurse). +func (t *Tree) Keys() []string { + keys := make([]string, len(t.values)) + i := 0 + for k := range t.values { + keys[i] = k + i++ + } + return keys +} + +// Get the value at key in the Tree. +// Key is a dot-separated path (e.g. a.b.c) without single/double quoted strings. +// If you need to retrieve non-bare keys, use GetPath. +// Returns nil if the path does not exist in the tree. +// If keys is of length zero, the current tree is returned. +func (t *Tree) Get(key string) interface{} { + if key == "" { + return t + } + return t.GetPath(strings.Split(key, ".")) +} + +// GetPath returns the element in the tree indicated by 'keys'. +// If keys is of length zero, the current tree is returned. +func (t *Tree) GetPath(keys []string) interface{} { + if len(keys) == 0 { + return t + } + subtree := t + for _, intermediateKey := range keys[:len(keys)-1] { + value, exists := subtree.values[intermediateKey] + if !exists { + return nil + } + switch node := value.(type) { + case *Tree: + subtree = node + case []*Tree: + // go to most recent element + if len(node) == 0 { + return nil + } + subtree = node[len(node)-1] + default: + return nil // cannot navigate through other node types + } + } + // branch based on final node type + switch node := subtree.values[keys[len(keys)-1]].(type) { + case *tomlValue: + return node.value + default: + return node + } +} + +// GetPosition returns the position of the given key. +func (t *Tree) GetPosition(key string) Position { + if key == "" { + return t.position + } + return t.GetPositionPath(strings.Split(key, ".")) +} + +// GetPositionPath returns the element in the tree indicated by 'keys'. +// If keys is of length zero, the current tree is returned. +func (t *Tree) GetPositionPath(keys []string) Position { + if len(keys) == 0 { + return t.position + } + subtree := t + for _, intermediateKey := range keys[:len(keys)-1] { + value, exists := subtree.values[intermediateKey] + if !exists { + return Position{0, 0} + } + switch node := value.(type) { + case *Tree: + subtree = node + case []*Tree: + // go to most recent element + if len(node) == 0 { + return Position{0, 0} + } + subtree = node[len(node)-1] + default: + return Position{0, 0} + } + } + // branch based on final node type + switch node := subtree.values[keys[len(keys)-1]].(type) { + case *tomlValue: + return node.position + case *Tree: + return node.position + case []*Tree: + // go to most recent element + if len(node) == 0 { + return Position{0, 0} + } + return node[len(node)-1].position + default: + return Position{0, 0} + } +} + +// GetDefault works like Get but with a default value +func (t *Tree) GetDefault(key string, def interface{}) interface{} { + val := t.Get(key) + if val == nil { + return def + } + return val +} + +// Set an element in the tree. +// Key is a dot-separated path (e.g. a.b.c). +// Creates all necessary intermediate trees, if needed. +func (t *Tree) Set(key string, value interface{}) { + t.SetWithComment(key, "", false, value) +} + +// SetWithComment is the same as Set, but allows you to provide comment +// information to the key, that will be reused by Marshal(). +func (t *Tree) SetWithComment(key string, comment string, commented bool, value interface{}) { + t.SetPathWithComment(strings.Split(key, "."), comment, commented, value) +} + +// SetPath sets an element in the tree. +// Keys is an array of path elements (e.g. {"a","b","c"}). +// Creates all necessary intermediate trees, if needed. +func (t *Tree) SetPath(keys []string, value interface{}) { + t.SetPathWithComment(keys, "", false, value) +} + +// SetPathWithComment is the same as SetPath, but allows you to provide comment +// information to the key, that will be reused by Marshal(). +func (t *Tree) SetPathWithComment(keys []string, comment string, commented bool, value interface{}) { + subtree := t + for _, intermediateKey := range keys[:len(keys)-1] { + nextTree, exists := subtree.values[intermediateKey] + if !exists { + nextTree = newTree() + subtree.values[intermediateKey] = nextTree // add new element here + } + switch node := nextTree.(type) { + case *Tree: + subtree = node + case []*Tree: + // go to most recent element + if len(node) == 0 { + // create element if it does not exist + subtree.values[intermediateKey] = append(node, newTree()) + } + subtree = node[len(node)-1] + } + } + + var toInsert interface{} + + switch value.(type) { + case *Tree: + tt := value.(*Tree) + tt.comment = comment + toInsert = value + case []*Tree: + toInsert = value + case *tomlValue: + tt := value.(*tomlValue) + tt.comment = comment + toInsert = tt + default: + toInsert = &tomlValue{value: value, comment: comment, commented: commented} + } + + subtree.values[keys[len(keys)-1]] = toInsert +} + +// createSubTree takes a tree and a key and create the necessary intermediate +// subtrees to create a subtree at that point. In-place. +// +// e.g. passing a.b.c will create (assuming tree is empty) tree[a], tree[a][b] +// and tree[a][b][c] +// +// Returns nil on success, error object on failure +func (t *Tree) createSubTree(keys []string, pos Position) error { + subtree := t + for _, intermediateKey := range keys { + nextTree, exists := subtree.values[intermediateKey] + if !exists { + tree := newTree() + tree.position = pos + subtree.values[intermediateKey] = tree + nextTree = tree + } + + switch node := nextTree.(type) { + case []*Tree: + subtree = node[len(node)-1] + case *Tree: + subtree = node + default: + return fmt.Errorf("unknown type for path %s (%s): %T (%#v)", + strings.Join(keys, "."), intermediateKey, nextTree, nextTree) + } + } + return nil +} + +// LoadBytes creates a Tree from a []byte. +func LoadBytes(b []byte) (tree *Tree, err error) { + defer func() { + if r := recover(); r != nil { + if _, ok := r.(runtime.Error); ok { + panic(r) + } + err = errors.New(r.(string)) + } + }() + tree = parseToml(lexToml(b)) + return +} + +// LoadReader creates a Tree from any io.Reader. +func LoadReader(reader io.Reader) (tree *Tree, err error) { + inputBytes, err := ioutil.ReadAll(reader) + if err != nil { + return + } + tree, err = LoadBytes(inputBytes) + return +} + +// Load creates a Tree from a string. +func Load(content string) (tree *Tree, err error) { + return LoadBytes([]byte(content)) +} + +// LoadFile creates a Tree from a file. +func LoadFile(path string) (tree *Tree, err error) { + file, err := os.Open(path) + if err != nil { + return nil, err + } + defer file.Close() + return LoadReader(file) +} diff --git a/vendor/github.com/pelletier/go-toml/toml_test.go b/vendor/github.com/pelletier/go-toml/toml_test.go new file mode 100644 index 00000000..ab9c2425 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/toml_test.go @@ -0,0 +1,106 @@ +// Testing support for go-toml + +package toml + +import ( + "testing" +) + +func TestTomlHas(t *testing.T) { + tree, _ := Load(` + [test] + key = "value" + `) + + if !tree.Has("test.key") { + t.Errorf("Has - expected test.key to exists") + } + + if tree.Has("") { + t.Errorf("Should return false if the key is not provided") + } +} + +func TestTomlGet(t *testing.T) { + tree, _ := Load(` + [test] + key = "value" + `) + + if tree.Get("") != tree { + t.Errorf("Get should return the tree itself when given an empty path") + } + + if tree.Get("test.key") != "value" { + t.Errorf("Get should return the value") + } + if tree.Get(`\`) != nil { + t.Errorf("should return nil when the key is malformed") + } +} + +func TestTomlGetDefault(t *testing.T) { + tree, _ := Load(` + [test] + key = "value" + `) + + if tree.GetDefault("", "hello") != tree { + t.Error("GetDefault should return the tree itself when given an empty path") + } + + if tree.GetDefault("test.key", "hello") != "value" { + t.Error("Get should return the value") + } + + if tree.GetDefault("whatever", "hello") != "hello" { + t.Error("GetDefault should return the default value if the key does not exist") + } +} + +func TestTomlHasPath(t *testing.T) { + tree, _ := Load(` + [test] + key = "value" + `) + + if !tree.HasPath([]string{"test", "key"}) { + t.Errorf("HasPath - expected test.key to exists") + } +} + +func TestTomlGetPath(t *testing.T) { + node := newTree() + //TODO: set other node data + + for idx, item := range []struct { + Path []string + Expected *Tree + }{ + { // empty path test + []string{}, + node, + }, + } { + result := node.GetPath(item.Path) + if result != item.Expected { + t.Errorf("GetPath[%d] %v - expected %v, got %v instead.", idx, item.Path, item.Expected, result) + } + } + + tree, _ := Load("[foo.bar]\na=1\nb=2\n[baz.foo]\na=3\nb=4\n[gorf.foo]\na=5\nb=6") + if tree.GetPath([]string{"whatever"}) != nil { + t.Error("GetPath should return nil when the key does not exist") + } +} + +func TestTomlFromMap(t *testing.T) { + simpleMap := map[string]interface{}{"hello": 42} + tree, err := TreeFromMap(simpleMap) + if err != nil { + t.Fatal("unexpected error:", err) + } + if tree.Get("hello") != int64(42) { + t.Fatal("hello should be 42, not", tree.Get("hello")) + } +} diff --git a/vendor/github.com/pelletier/go-toml/tomltree_create.go b/vendor/github.com/pelletier/go-toml/tomltree_create.go new file mode 100644 index 00000000..79610e9b --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/tomltree_create.go @@ -0,0 +1,142 @@ +package toml + +import ( + "fmt" + "reflect" + "time" +) + +var kindToType = [reflect.String + 1]reflect.Type{ + reflect.Bool: reflect.TypeOf(true), + reflect.String: reflect.TypeOf(""), + reflect.Float32: reflect.TypeOf(float64(1)), + reflect.Float64: reflect.TypeOf(float64(1)), + reflect.Int: reflect.TypeOf(int64(1)), + reflect.Int8: reflect.TypeOf(int64(1)), + reflect.Int16: reflect.TypeOf(int64(1)), + reflect.Int32: reflect.TypeOf(int64(1)), + reflect.Int64: reflect.TypeOf(int64(1)), + reflect.Uint: reflect.TypeOf(uint64(1)), + reflect.Uint8: reflect.TypeOf(uint64(1)), + reflect.Uint16: reflect.TypeOf(uint64(1)), + reflect.Uint32: reflect.TypeOf(uint64(1)), + reflect.Uint64: reflect.TypeOf(uint64(1)), +} + +// typeFor returns a reflect.Type for a reflect.Kind, or nil if none is found. +// supported values: +// string, bool, int64, uint64, float64, time.Time, int, int8, int16, int32, uint, uint8, uint16, uint32, float32 +func typeFor(k reflect.Kind) reflect.Type { + if k > 0 && int(k) < len(kindToType) { + return kindToType[k] + } + return nil +} + +func simpleValueCoercion(object interface{}) (interface{}, error) { + switch original := object.(type) { + case string, bool, int64, uint64, float64, time.Time: + return original, nil + case int: + return int64(original), nil + case int8: + return int64(original), nil + case int16: + return int64(original), nil + case int32: + return int64(original), nil + case uint: + return uint64(original), nil + case uint8: + return uint64(original), nil + case uint16: + return uint64(original), nil + case uint32: + return uint64(original), nil + case float32: + return float64(original), nil + case fmt.Stringer: + return original.String(), nil + default: + return nil, fmt.Errorf("cannot convert type %T to Tree", object) + } +} + +func sliceToTree(object interface{}) (interface{}, error) { + // arrays are a bit tricky, since they can represent either a + // collection of simple values, which is represented by one + // *tomlValue, or an array of tables, which is represented by an + // array of *Tree. + + // holding the assumption that this function is called from toTree only when value.Kind() is Array or Slice + value := reflect.ValueOf(object) + insideType := value.Type().Elem() + length := value.Len() + if length > 0 { + insideType = reflect.ValueOf(value.Index(0).Interface()).Type() + } + if insideType.Kind() == reflect.Map { + // this is considered as an array of tables + tablesArray := make([]*Tree, 0, length) + for i := 0; i < length; i++ { + table := value.Index(i) + tree, err := toTree(table.Interface()) + if err != nil { + return nil, err + } + tablesArray = append(tablesArray, tree.(*Tree)) + } + return tablesArray, nil + } + + sliceType := typeFor(insideType.Kind()) + if sliceType == nil { + sliceType = insideType + } + + arrayValue := reflect.MakeSlice(reflect.SliceOf(sliceType), 0, length) + + for i := 0; i < length; i++ { + val := value.Index(i).Interface() + simpleValue, err := simpleValueCoercion(val) + if err != nil { + return nil, err + } + arrayValue = reflect.Append(arrayValue, reflect.ValueOf(simpleValue)) + } + return &tomlValue{value: arrayValue.Interface(), position: Position{}}, nil +} + +func toTree(object interface{}) (interface{}, error) { + value := reflect.ValueOf(object) + + if value.Kind() == reflect.Map { + values := map[string]interface{}{} + keys := value.MapKeys() + for _, key := range keys { + if key.Kind() != reflect.String { + if _, ok := key.Interface().(string); !ok { + return nil, fmt.Errorf("map key needs to be a string, not %T (%v)", key.Interface(), key.Kind()) + } + } + + v := value.MapIndex(key) + newValue, err := toTree(v.Interface()) + if err != nil { + return nil, err + } + values[key.String()] = newValue + } + return &Tree{values: values, position: Position{}}, nil + } + + if value.Kind() == reflect.Array || value.Kind() == reflect.Slice { + return sliceToTree(object) + } + + simpleValue, err := simpleValueCoercion(object) + if err != nil { + return nil, err + } + return &tomlValue{value: simpleValue, position: Position{}}, nil +} diff --git a/vendor/github.com/pelletier/go-toml/tomltree_create_test.go b/vendor/github.com/pelletier/go-toml/tomltree_create_test.go new file mode 100644 index 00000000..3465a106 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/tomltree_create_test.go @@ -0,0 +1,126 @@ +package toml + +import ( + "strconv" + "testing" + "time" +) + +type customString string + +type stringer struct{} + +func (s stringer) String() string { + return "stringer" +} + +func validate(t *testing.T, path string, object interface{}) { + switch o := object.(type) { + case *Tree: + for key, tree := range o.values { + validate(t, path+"."+key, tree) + } + case []*Tree: + for index, tree := range o { + validate(t, path+"."+strconv.Itoa(index), tree) + } + case *tomlValue: + switch o.value.(type) { + case int64, uint64, bool, string, float64, time.Time, + []int64, []uint64, []bool, []string, []float64, []time.Time: + default: + t.Fatalf("tomlValue at key %s containing incorrect type %T", path, o.value) + } + default: + t.Fatalf("value at key %s is of incorrect type %T", path, object) + } + t.Logf("validation ok %s as %T", path, object) +} + +func validateTree(t *testing.T, tree *Tree) { + validate(t, "", tree) +} + +func TestTreeCreateToTree(t *testing.T) { + data := map[string]interface{}{ + "a_string": "bar", + "an_int": 42, + "time": time.Now(), + "int8": int8(2), + "int16": int16(2), + "int32": int32(2), + "uint8": uint8(2), + "uint16": uint16(2), + "uint32": uint32(2), + "float32": float32(2), + "a_bool": false, + "stringer": stringer{}, + "nested": map[string]interface{}{ + "foo": "bar", + }, + "array": []string{"a", "b", "c"}, + "array_uint": []uint{uint(1), uint(2)}, + "array_table": []map[string]interface{}{{"sub_map": 52}}, + "array_times": []time.Time{time.Now(), time.Now()}, + "map_times": map[string]time.Time{"now": time.Now()}, + "custom_string_map_key": map[customString]interface{}{customString("custom"): "custom"}, + } + tree, err := TreeFromMap(data) + if err != nil { + t.Fatal("unexpected error:", err) + } + validateTree(t, tree) +} + +func TestTreeCreateToTreeInvalidLeafType(t *testing.T) { + _, err := TreeFromMap(map[string]interface{}{"foo": t}) + expected := "cannot convert type *testing.T to Tree" + if err.Error() != expected { + t.Fatalf("expected error %s, got %s", expected, err.Error()) + } +} + +func TestTreeCreateToTreeInvalidMapKeyType(t *testing.T) { + _, err := TreeFromMap(map[string]interface{}{"foo": map[int]interface{}{2: 1}}) + expected := "map key needs to be a string, not int (int)" + if err.Error() != expected { + t.Fatalf("expected error %s, got %s", expected, err.Error()) + } +} + +func TestTreeCreateToTreeInvalidArrayMemberType(t *testing.T) { + _, err := TreeFromMap(map[string]interface{}{"foo": []*testing.T{t}}) + expected := "cannot convert type *testing.T to Tree" + if err.Error() != expected { + t.Fatalf("expected error %s, got %s", expected, err.Error()) + } +} + +func TestTreeCreateToTreeInvalidTableGroupType(t *testing.T) { + _, err := TreeFromMap(map[string]interface{}{"foo": []map[string]interface{}{{"hello": t}}}) + expected := "cannot convert type *testing.T to Tree" + if err.Error() != expected { + t.Fatalf("expected error %s, got %s", expected, err.Error()) + } +} + +func TestRoundTripArrayOfTables(t *testing.T) { + orig := "\n[[stuff]]\n name = \"foo\"\n things = [\"a\",\"b\"]\n" + tree, err := Load(orig) + if err != nil { + t.Fatalf("unexpected error: %s", err) + } + + m := tree.ToMap() + + tree, err = TreeFromMap(m) + if err != nil { + t.Fatalf("unexpected error: %s", err) + } + want := orig + got := tree.String() + + if got != want { + t.Errorf("want:\n%s\ngot:\n%s", want, got) + } +} diff --git a/vendor/github.com/pelletier/go-toml/tomltree_write.go b/vendor/github.com/pelletier/go-toml/tomltree_write.go new file mode 100644 index 00000000..d322a976 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/tomltree_write.go @@ -0,0 +1,289 @@ +package toml + +import ( + "bytes" + "fmt" + "io" + "math" + "reflect" + "sort" + "strconv" + "strings" + "time" +) + +// encodes a string to a TOML-compliant string value +func encodeTomlString(value string) string { + var b bytes.Buffer + + for _, rr := range value { + switch rr { + case '\b': + b.WriteString(`\b`) + case '\t': + b.WriteString(`\t`) + case '\n': + b.WriteString(`\n`) + case '\f': + b.WriteString(`\f`) + case '\r': + b.WriteString(`\r`) + case '"': + b.WriteString(`\"`) + case '\\': + b.WriteString(`\\`) + default: + intRr := uint16(rr) + if intRr < 0x001F { + b.WriteString(fmt.Sprintf("\\u%0.4X", intRr)) + } else { + b.WriteRune(rr) + } + } + } + return b.String() +} + +func tomlValueStringRepresentation(v interface{}, indent string, arraysOneElementPerLine bool) (string, error) { + switch value := v.(type) { + case uint64: + return strconv.FormatUint(value, 10), nil + case int64: + return strconv.FormatInt(value, 10), nil + case float64: + // Ensure a round float does contain a decimal point. Otherwise feeding + // the output back to the parser would convert to an integer. + if math.Trunc(value) == value { + return strings.ToLower(strconv.FormatFloat(value, 'f', 1, 32)), nil + } + return strings.ToLower(strconv.FormatFloat(value, 'f', -1, 32)), nil + case string: + return "\"" + encodeTomlString(value) + "\"", nil + case []byte: + b, _ := v.([]byte) + return tomlValueStringRepresentation(string(b), indent, arraysOneElementPerLine) + case bool: + if value { + return "true", nil + } + return "false", nil + case time.Time: + return value.Format(time.RFC3339), nil + case nil: + return "", nil + } + + rv := reflect.ValueOf(v) + + if rv.Kind() == reflect.Slice { + var values []string + for i := 0; i < rv.Len(); i++ { + item := rv.Index(i).Interface() + itemRepr, err := tomlValueStringRepresentation(item, indent, arraysOneElementPerLine) + if err != nil { + return "", err + } + values = append(values, itemRepr) + } + if arraysOneElementPerLine && len(values) > 1 { + stringBuffer := bytes.Buffer{} + valueIndent := indent + ` ` // TODO: move that to a shared encoder state + + stringBuffer.WriteString("[\n") + + for i, value := range values { + stringBuffer.WriteString(valueIndent) + stringBuffer.WriteString(value) + if i != len(values)-1 { + stringBuffer.WriteString(`,`) + } + stringBuffer.WriteString("\n") + } + + stringBuffer.WriteString(indent + "]") + + return stringBuffer.String(), nil + } + return "[" + strings.Join(values, ",") + "]", nil + } + return "", fmt.Errorf("unsupported value type %T: %v", v, v) +} + +func (t *Tree) writeTo(w io.Writer, indent, keyspace string, bytesCount int64, arraysOneElementPerLine bool) (int64, error) { + simpleValuesKeys := make([]string, 0) + complexValuesKeys := make([]string, 0) + + for k := range t.values { + v := t.values[k] + switch v.(type) { + case *Tree, []*Tree: + complexValuesKeys = append(complexValuesKeys, k) + default: + simpleValuesKeys = append(simpleValuesKeys, k) + } + } + + sort.Strings(simpleValuesKeys) + sort.Strings(complexValuesKeys) + + for _, k := range simpleValuesKeys { + v, ok := t.values[k].(*tomlValue) + if !ok { + return bytesCount, fmt.Errorf("invalid value type at %s: %T", k, t.values[k]) + } + + repr, err := tomlValueStringRepresentation(v.value, indent, arraysOneElementPerLine) + if err != nil { + return bytesCount, err + } + + if v.comment != "" { + comment := strings.Replace(v.comment, "\n", "\n"+indent+"#", -1) + start := "# " + if strings.HasPrefix(comment, "#") { + start = "" + } + writtenBytesCountComment, errc := writeStrings(w, "\n", indent, start, comment, "\n") + bytesCount += int64(writtenBytesCountComment) + if errc != nil { + return bytesCount, errc + } + } + + var commented string + if v.commented { + commented = "# " + } + writtenBytesCount, err := writeStrings(w, indent, commented, k, " = ", repr, "\n") + bytesCount += int64(writtenBytesCount) + if err != nil { + return bytesCount, err + } + } + + for _, k := range complexValuesKeys { + v := t.values[k] + + combinedKey := k + if keyspace != "" { + combinedKey = keyspace + "." + combinedKey + } + var commented string + if t.commented { + commented = "# " + } + + switch node := v.(type) { + // node has to be of those two types given how keys are sorted above + case *Tree: + tv, ok := t.values[k].(*Tree) + if !ok { + return bytesCount, fmt.Errorf("invalid value type at %s: %T", k, t.values[k]) + } + if tv.comment != "" { + comment := strings.Replace(tv.comment, "\n", "\n"+indent+"#", -1) + start := "# " + if strings.HasPrefix(comment, "#") { + start = "" + } + writtenBytesCountComment, errc := writeStrings(w, "\n", indent, start, comment) + bytesCount += int64(writtenBytesCountComment) + if errc != nil { + return bytesCount, errc + } + } + writtenBytesCount, err := writeStrings(w, "\n", indent, commented, "[", combinedKey, "]\n") + bytesCount += int64(writtenBytesCount) + if err != nil { + return bytesCount, err + } + bytesCount, err = node.writeTo(w, indent+" ", combinedKey, bytesCount, arraysOneElementPerLine) + if err != nil { + return bytesCount, err + } + case []*Tree: + for _, subTree := range node { + writtenBytesCount, err := writeStrings(w, "\n", indent, commented, "[[", combinedKey, "]]\n") + bytesCount += int64(writtenBytesCount) + if err != nil { + return bytesCount, err + } + + bytesCount, err = subTree.writeTo(w, indent+" ", combinedKey, bytesCount, arraysOneElementPerLine) + if err != nil { + return bytesCount, err + } + } + } + } + + return bytesCount, nil +} + +func writeStrings(w io.Writer, s ...string) (int, error) { + var n int + for i := range s { + b, err := io.WriteString(w, s[i]) + n += b + if err != nil { + return n, err + } + } + return n, nil +} + +// WriteTo encode the Tree as Toml and writes it to the writer w. +// Returns the number of bytes written in case of success, or an error if anything happened. +func (t *Tree) WriteTo(w io.Writer) (int64, error) { + return t.writeTo(w, "", "", 0, false) +} + +// ToTomlString generates a human-readable representation of the current tree. +// Output spans multiple lines, and is suitable for ingest by a TOML parser. +// If the conversion cannot be performed, ToString returns a non-nil error. +func (t *Tree) ToTomlString() (string, error) { + var buf bytes.Buffer + _, err := t.WriteTo(&buf) + if err != nil { + return "", err + } + return buf.String(), nil +} + +// String generates a human-readable representation of the current tree. +// Alias of ToString. Present to implement the fmt.Stringer interface. +func (t *Tree) String() string { + result, _ := t.ToTomlString() + return result +} + +// ToMap recursively generates a representation of the tree using Go built-in structures. +// The following types are used: +// +// * bool +// * float64 +// * int64 +// * string +// * uint64 +// * time.Time +// * map[string]interface{} (where interface{} is any of this list) +// * []interface{} (where interface{} is any of this list) +func (t *Tree) ToMap() map[string]interface{} { + result := map[string]interface{}{} + + for k, v := range t.values { + switch node := v.(type) { + case []*Tree: + var array []interface{} + for _, item := range node { + array = append(array, item.ToMap()) + } + result[k] = array + case *Tree: + result[k] = node.ToMap() + case *tomlValue: + result[k] = node.value + } + } + return result +} diff --git a/vendor/github.com/pelletier/go-toml/tomltree_write_test.go b/vendor/github.com/pelletier/go-toml/tomltree_write_test.go new file mode 100644 index 00000000..206203b8 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/tomltree_write_test.go @@ -0,0 +1,376 @@ +package toml + +import ( + "bytes" + "errors" + "fmt" + "reflect" + "strings" + "testing" + "time" +) + +type failingWriter struct { + failAt int + written int + buffer bytes.Buffer +} + +func (f *failingWriter) Write(p []byte) (n int, err error) { + count := len(p) + toWrite := f.failAt - (count + f.written) + if toWrite < 0 { + toWrite = 0 + } + if toWrite > count { + f.written += count + f.buffer.Write(p) + return count, nil + } + + f.buffer.Write(p[:toWrite]) + f.written = f.failAt + return toWrite, fmt.Errorf("failingWriter failed after writing %d bytes", f.written) +} + +func assertErrorString(t *testing.T, expected string, err error) { + expectedErr := errors.New(expected) + if err == nil || err.Error() != expectedErr.Error() { + t.Errorf("expecting error %s, but got %s instead", expected, err) + } +} + +func TestTreeWriteToEmptyTable(t *testing.T) { + doc := `[[empty-tables]] +[[empty-tables]]` + + toml, err := Load(doc) + if err != nil { + t.Fatal("Unexpected Load error:", err) + } + tomlString, err := toml.ToTomlString() + if err != nil { + t.Fatal("Unexpected ToTomlString error:", err) + } + + expected := ` +[[empty-tables]] + +[[empty-tables]] +` + + if tomlString != expected { + t.Fatalf("Expected:\n%s\nGot:\n%s", expected, tomlString) + } +} + +func TestTreeWriteToTomlString(t *testing.T) { + toml, err := Load(`name = { first = "Tom", last = "Preston-Werner" } +points = { x = 1, y = 2 }`) + + if err != nil { + t.Fatal("Unexpected error:", err) + } + + tomlString, _ := toml.ToTomlString() + reparsedTree, err := Load(tomlString) + + assertTree(t, reparsedTree, err, map[string]interface{}{ + "name": map[string]interface{}{ + "first": "Tom", + "last": "Preston-Werner", + }, + "points": map[string]interface{}{ + "x": int64(1), + "y": int64(2), + }, + }) +} + +func TestTreeWriteToTomlStringSimple(t *testing.T) { + tree, err := Load("[foo]\n\n[[foo.bar]]\na = 42\n\n[[foo.bar]]\na = 69\n") + if err != nil { + t.Errorf("Test failed to parse: %v", err) + return + } + result, err := tree.ToTomlString() + if err != nil { + t.Errorf("Unexpected error: %s", err) + } + expected := "\n[foo]\n\n [[foo.bar]]\n a = 42\n\n [[foo.bar]]\n a = 69\n" + if result != expected { + t.Errorf("Expected got '%s', expected '%s'", result, expected) + } +} + +func TestTreeWriteToTomlStringKeysOrders(t *testing.T) { + for i := 0; i < 100; i++ { + tree, _ := Load(` + foobar = true + bar = "baz" + foo = 1 + [qux] + foo = 1 + bar = "baz2"`) + + stringRepr, _ := tree.ToTomlString() + + t.Log("Intermediate string representation:") + t.Log(stringRepr) + + r := strings.NewReader(stringRepr) + toml, err := LoadReader(r) + + if err != nil { + t.Fatal("Unexpected error:", err) + } + + assertTree(t, toml, err, map[string]interface{}{ + "foobar": true, + "bar": "baz", + "foo": 1, + "qux": map[string]interface{}{ + "foo": 1, + "bar": "baz2", + }, + }) + } +} + +func testMaps(t *testing.T, actual, expected map[string]interface{}) { + if !reflect.DeepEqual(actual, expected) { + t.Fatal("trees aren't equal.\n", "Expected:\n", expected, "\nActual:\n", actual) + } +} + +func TestTreeWriteToMapSimple(t *testing.T) { + tree, _ := Load("a = 42\nb = 17") + + expected := map[string]interface{}{ + "a": int64(42), + "b": int64(17), + } + + testMaps(t, tree.ToMap(), expected) +} + +func TestTreeWriteToInvalidTreeSimpleValue(t *testing.T) { + tree := Tree{values: map[string]interface{}{"foo": int8(1)}} + _, err := tree.ToTomlString() + assertErrorString(t, "invalid value type at foo: int8", err) +} + +func TestTreeWriteToInvalidTreeTomlValue(t *testing.T) { + tree := Tree{values: map[string]interface{}{"foo": &tomlValue{value: int8(1), comment: "", position: Position{}}}} + _, err := tree.ToTomlString() + assertErrorString(t, "unsupported value type int8: 1", err) +} + +func TestTreeWriteToInvalidTreeTomlValueArray(t *testing.T) { + tree := Tree{values: map[string]interface{}{"foo": &tomlValue{value: int8(1), comment: "", position: Position{}}}} + _, err := tree.ToTomlString() + assertErrorString(t, "unsupported value type int8: 1", err) +} + +func TestTreeWriteToFailingWriterInSimpleValue(t *testing.T) { + toml, _ := Load(`a = 2`) + writer := failingWriter{failAt: 0, written: 0} + _, err := toml.WriteTo(&writer) + assertErrorString(t, "failingWriter failed after writing 0 bytes", err) +} + +func TestTreeWriteToFailingWriterInTable(t *testing.T) { + toml, _ := Load(` +[b] +a = 2`) + writer := failingWriter{failAt: 2, written: 0} + _, err := toml.WriteTo(&writer) + assertErrorString(t, "failingWriter failed after writing 2 bytes", err) + + writer = failingWriter{failAt: 13, written: 0} + _, err = toml.WriteTo(&writer) + assertErrorString(t, "failingWriter failed after writing 13 bytes", err) +} + +func TestTreeWriteToFailingWriterInArray(t *testing.T) { + toml, _ := Load(` +[[b]] +a = 2`) + writer := failingWriter{failAt: 2, written: 0} + _, err := toml.WriteTo(&writer) + assertErrorString(t, "failingWriter failed after writing 2 bytes", err) + + writer = failingWriter{failAt: 15, written: 0} + _, err = toml.WriteTo(&writer) + assertErrorString(t, "failingWriter failed after writing 15 bytes", err) +} + +func TestTreeWriteToMapExampleFile(t *testing.T) { + tree, _ := LoadFile("example.toml") + expected := map[string]interface{}{ + "title": "TOML Example", + "owner": map[string]interface{}{ + "name": "Tom Preston-Werner", + "organization": "GitHub", + "bio": "GitHub Cofounder & CEO\nLikes tater tots and beer.", + "dob": time.Date(1979, time.May, 27, 7, 32, 0, 0, time.UTC), + }, + "database": map[string]interface{}{ + "server": "192.168.1.1", + "ports": []interface{}{int64(8001), int64(8001), int64(8002)}, + "connection_max": int64(5000), + "enabled": true, + }, + "servers": map[string]interface{}{ + "alpha": map[string]interface{}{ + "ip": "10.0.0.1", + "dc": "eqdc10", + }, + "beta": map[string]interface{}{ + "ip": "10.0.0.2", + "dc": "eqdc10", + }, + }, + "clients": map[string]interface{}{ + "data": []interface{}{ + []interface{}{"gamma", "delta"}, + []interface{}{int64(1), int64(2)}, + }, + }, + } + testMaps(t, tree.ToMap(), expected) +} + +func TestTreeWriteToMapWithTablesInMultipleChunks(t *testing.T) { + tree, _ := Load(` + [[menu.main]] + a = "menu 1" + b = "menu 2" + [[menu.main]] + c = "menu 3" + d = "menu 4"`) + expected := map[string]interface{}{ + "menu": map[string]interface{}{ + "main": []interface{}{ + map[string]interface{}{"a": "menu 1", "b": "menu 2"}, + map[string]interface{}{"c": "menu 3", "d": "menu 4"}, + }, + }, + } + treeMap := tree.ToMap() + + testMaps(t, treeMap, expected) +} + +func TestTreeWriteToMapWithArrayOfInlineTables(t *testing.T) { + tree, _ := Load(` + [params] + language_tabs = [ + { key = "shell", name = "Shell" }, + { key = "ruby", name = "Ruby" }, + { key = "python", name = "Python" } + ]`) + + expected := map[string]interface{}{ + "params": map[string]interface{}{ + "language_tabs": []interface{}{ + map[string]interface{}{ + "key": "shell", + "name": "Shell", + }, + map[string]interface{}{ + "key": "ruby", + "name": "Ruby", + }, + map[string]interface{}{ + "key": "python", + "name": "Python", + }, + }, + }, + } + + treeMap := tree.ToMap() + testMaps(t, treeMap, expected) +} + +func TestTreeWriteToFloat(t *testing.T) { + tree, err := Load(`a = 3.0`) + if err != nil { + t.Fatal(err) + } + str, err := tree.ToTomlString() + if err != nil { + t.Fatal(err) + } + expected := `a = 3.0` + if strings.TrimSpace(str) != strings.TrimSpace(expected) { + t.Fatalf("Expected:\n%s\nGot:\n%s", expected, str) + } +} + +func TestTreeWriteToSpecialFloat(t *testing.T) { + expected := `a = +inf +b = -inf +c = nan` + + tree, err := Load(expected) + if err != nil { + t.Fatal(err) + } + str, err := tree.ToTomlString() + if err != nil { + t.Fatal(err) + } + if strings.TrimSpace(str) != strings.TrimSpace(expected) { + t.Fatalf("Expected:\n%s\nGot:\n%s", expected, str) + } +} + +func BenchmarkTreeToTomlString(b *testing.B) { + toml, err := Load(sampleHard) + if err != nil { + b.Fatal("Unexpected error:", err) + } + + for i := 0; i < b.N; i++ { + _, err := toml.ToTomlString() + if err != nil { + b.Fatal(err) + } + } +} + +var sampleHard = `# Test file for TOML +# Only this one tries to emulate a TOML file written by a user of the kind of parser writers probably hate +# This part you'll really hate + +[the] +test_string = "You'll hate me after this - #" # " Annoying, isn't it? + + [the.hard] + test_array = [ "] ", " # "] # ] There you go, parse this! + test_array2 = [ "Test #11 ]proved that", "Experiment #9 was a success" ] + # You didn't think it'd as easy as chucking out the last #, did you? + another_test_string = " Same thing, but with a string #" + harder_test_string = " And when \"'s are in the string, along with # \"" # "and comments are there too" + # Things will get harder + + [the.hard."bit#"] + "what?" = "You don't think some user won't do that?" + multi_line_array = [ + "]", + # ] Oh yes I did + ] + +# Each of the following keygroups/key value pairs should produce an error. Uncomment to them to test + +#[error] if you didn't catch this, your parser is broken +#string = "Anything other than tabs, spaces and newline after a keygroup or key value pair has ended should produce an error unless it is a comment" like this +#array = [ +# "This might most likely happen in multiline arrays", +# Like here, +# "or here, +# and here" +# ] End of array comment, forgot the # +#number = 3.14 pi <--again forgot the # ` diff --git a/vendor/github.com/pkg/errors/.gitignore b/vendor/github.com/pkg/errors/.gitignore new file mode 100644 index 00000000..daf913b1 --- /dev/null +++ b/vendor/github.com/pkg/errors/.gitignore @@ -0,0 +1,24 @@ +# 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 diff --git a/vendor/github.com/pkg/errors/.travis.yml b/vendor/github.com/pkg/errors/.travis.yml new file mode 100644 index 00000000..588ceca1 --- /dev/null +++ b/vendor/github.com/pkg/errors/.travis.yml @@ -0,0 +1,11 @@ +language: go +go_import_path: github.com/pkg/errors +go: + - 1.4.3 + - 1.5.4 + - 1.6.2 + - 1.7.1 + - tip + +script: + - go test -v ./... diff --git a/vendor/github.com/pkg/errors/LICENSE b/vendor/github.com/pkg/errors/LICENSE new file mode 100644 index 00000000..835ba3e7 --- /dev/null +++ b/vendor/github.com/pkg/errors/LICENSE @@ -0,0 +1,23 @@ +Copyright (c) 2015, Dave Cheney +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* 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/pkg/errors/README.md b/vendor/github.com/pkg/errors/README.md new file mode 100644 index 00000000..273db3c9 --- /dev/null +++ b/vendor/github.com/pkg/errors/README.md @@ -0,0 +1,52 @@ +# errors [![Travis-CI](https://travis-ci.org/pkg/errors.svg)](https://travis-ci.org/pkg/errors) [![AppVeyor](https://ci.appveyor.com/api/projects/status/b98mptawhudj53ep/branch/master?svg=true)](https://ci.appveyor.com/project/davecheney/errors/branch/master) [![GoDoc](https://godoc.org/github.com/pkg/errors?status.svg)](http://godoc.org/github.com/pkg/errors) [![Report card](https://goreportcard.com/badge/github.com/pkg/errors)](https://goreportcard.com/report/github.com/pkg/errors) + +Package errors provides simple error handling primitives. + +`go get github.com/pkg/errors` + +The traditional error handling idiom in Go is roughly akin to +```go +if err != nil { + return err +} +``` +which applied recursively up the call stack results in error reports without context or debugging information. The errors package allows programmers to add context to the failure path in their code in a way that does not destroy the original value of the error. + +## Adding context to an error + +The errors.Wrap function returns a new error that adds context to the original error. For example +```go +_, err := ioutil.ReadAll(r) +if err != nil { + return errors.Wrap(err, "read failed") +} +``` +## Retrieving the cause of an error + +Using `errors.Wrap` constructs a stack of errors, adding context to the preceding error. Depending on the nature of the error it may be necessary to reverse the operation of errors.Wrap to retrieve the original error for inspection. Any error value which implements this interface can be inspected by `errors.Cause`. +```go +type causer interface { + Cause() error +} +``` +`errors.Cause` will recursively retrieve the topmost error which does not implement `causer`, which is assumed to be the original cause. For example: +```go +switch err := errors.Cause(err).(type) { +case *MyError: + // handle specifically +default: + // unknown error +} +``` + +[Read the package documentation for more information](https://godoc.org/github.com/pkg/errors). + +## 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. + +Before proposing a change, please discuss your change by raising an issue. + +## Licence + +BSD-2-Clause diff --git a/vendor/github.com/pkg/errors/appveyor.yml b/vendor/github.com/pkg/errors/appveyor.yml new file mode 100644 index 00000000..a932eade --- /dev/null +++ b/vendor/github.com/pkg/errors/appveyor.yml @@ -0,0 +1,32 @@ +version: build-{build}.{branch} + +clone_folder: C:\gopath\src\github.com\pkg\errors +shallow_clone: true # for startup speed + +environment: + GOPATH: C:\gopath + +platform: + - x64 + +# http://www.appveyor.com/docs/installed-software +install: + # some helpful output for debugging builds + - go version + - go env + # pre-installed MinGW at C:\MinGW is 32bit only + # but MSYS2 at C:\msys64 has mingw64 + - set PATH=C:\msys64\mingw64\bin;%PATH% + - gcc --version + - g++ --version + +build_script: + - go install -v ./... + +test_script: + - set PATH=C:\gopath\bin;%PATH% + - go test -v ./... + +#artifacts: +# - path: '%GOPATH%\bin\*.exe' +deploy: off diff --git a/vendor/github.com/pkg/errors/bench_test.go b/vendor/github.com/pkg/errors/bench_test.go new file mode 100644 index 00000000..0416a3cb --- /dev/null +++ b/vendor/github.com/pkg/errors/bench_test.go @@ -0,0 +1,59 @@ +// +build go1.7 + +package errors + +import ( + "fmt" + "testing" + + stderrors "errors" +) + +func noErrors(at, depth int) error { + if at >= depth { + return stderrors.New("no error") + } + return noErrors(at+1, depth) +} +func yesErrors(at, depth int) error { + if at >= depth { + return New("ye error") + } + return yesErrors(at+1, depth) +} + +func BenchmarkErrors(b *testing.B) { + var toperr error + type run struct { + stack int + std bool + } + runs := []run{ + {10, false}, + {10, true}, + {100, false}, + {100, true}, + {1000, false}, + {1000, true}, + } + for _, r := range runs { + part := "pkg/errors" + if r.std { + part = "errors" + } + name := fmt.Sprintf("%s-stack-%d", part, r.stack) + b.Run(name, func(b *testing.B) { + var err error + f := yesErrors + if r.std { + f = noErrors + } + b.ReportAllocs() + for i := 0; i < b.N; i++ { + err = f(0, r.stack) + } + b.StopTimer() + toperr = err + }) + } +} diff --git a/vendor/github.com/pkg/errors/errors.go b/vendor/github.com/pkg/errors/errors.go new file mode 100644 index 00000000..842ee804 --- /dev/null +++ b/vendor/github.com/pkg/errors/errors.go @@ -0,0 +1,269 @@ +// Package errors provides simple error handling primitives. +// +// The traditional error handling idiom in Go is roughly akin to +// +// if err != nil { +// return err +// } +// +// which applied recursively up the call stack results in error reports +// without context or debugging information. The errors package allows +// programmers to add context to the failure path in their code in a way +// that does not destroy the original value of the error. +// +// Adding context to an error +// +// The errors.Wrap function returns a new error that adds context to the +// original error by recording a stack trace at the point Wrap is called, +// and the supplied message. For example +// +// _, err := ioutil.ReadAll(r) +// if err != nil { +// return errors.Wrap(err, "read failed") +// } +// +// If additional control is required the errors.WithStack and errors.WithMessage +// functions destructure errors.Wrap into its component operations of annotating +// an error with a stack trace and an a message, respectively. +// +// Retrieving the cause of an error +// +// Using errors.Wrap constructs a stack of errors, adding context to the +// preceding error. Depending on the nature of the error it may be necessary +// to reverse the operation of errors.Wrap to retrieve the original error +// for inspection. Any error value which implements this interface +// +// type causer interface { +// Cause() error +// } +// +// can be inspected by errors.Cause. errors.Cause will recursively retrieve +// the topmost error which does not implement causer, which is assumed to be +// the original cause. For example: +// +// switch err := errors.Cause(err).(type) { +// case *MyError: +// // handle specifically +// default: +// // unknown error +// } +// +// causer interface is not exported by this package, but is considered a part +// of stable public API. +// +// Formatted printing of errors +// +// All error values returned from this package implement fmt.Formatter and can +// be formatted by the fmt package. The following verbs are supported +// +// %s print the error. If the error has a Cause it will be +// printed recursively +// %v see %s +// %+v extended format. Each Frame of the error's StackTrace will +// be printed in detail. +// +// Retrieving the stack trace of an error or wrapper +// +// New, Errorf, Wrap, and Wrapf record a stack trace at the point they are +// invoked. This information can be retrieved with the following interface. +// +// type stackTracer interface { +// StackTrace() errors.StackTrace +// } +// +// Where errors.StackTrace is defined as +// +// type StackTrace []Frame +// +// The Frame type represents a call site in the stack trace. Frame supports +// the fmt.Formatter interface that can be used for printing information about +// the stack trace of this error. For example: +// +// if err, ok := err.(stackTracer); ok { +// for _, f := range err.StackTrace() { +// fmt.Printf("%+s:%d", f) +// } +// } +// +// stackTracer interface is not exported by this package, but is considered a part +// of stable public API. +// +// See the documentation for Frame.Format for more details. +package errors + +import ( + "fmt" + "io" +) + +// New returns an error with the supplied message. +// New also records the stack trace at the point it was called. +func New(message string) error { + return &fundamental{ + msg: message, + stack: callers(), + } +} + +// Errorf formats according to a format specifier and returns the string +// as a value that satisfies error. +// Errorf also records the stack trace at the point it was called. +func Errorf(format string, args ...interface{}) error { + return &fundamental{ + msg: fmt.Sprintf(format, args...), + stack: callers(), + } +} + +// fundamental is an error that has a message and a stack, but no caller. +type fundamental struct { + msg string + *stack +} + +func (f *fundamental) Error() string { return f.msg } + +func (f *fundamental) Format(s fmt.State, verb rune) { + switch verb { + case 'v': + if s.Flag('+') { + io.WriteString(s, f.msg) + f.stack.Format(s, verb) + return + } + fallthrough + case 's': + io.WriteString(s, f.msg) + case 'q': + fmt.Fprintf(s, "%q", f.msg) + } +} + +// WithStack annotates err with a stack trace at the point WithStack was called. +// If err is nil, WithStack returns nil. +func WithStack(err error) error { + if err == nil { + return nil + } + return &withStack{ + err, + callers(), + } +} + +type withStack struct { + error + *stack +} + +func (w *withStack) Cause() error { return w.error } + +func (w *withStack) Format(s fmt.State, verb rune) { + switch verb { + case 'v': + if s.Flag('+') { + fmt.Fprintf(s, "%+v", w.Cause()) + w.stack.Format(s, verb) + return + } + fallthrough + case 's': + io.WriteString(s, w.Error()) + case 'q': + fmt.Fprintf(s, "%q", w.Error()) + } +} + +// Wrap returns an error annotating err with a stack trace +// at the point Wrap is called, and the supplied message. +// If err is nil, Wrap returns nil. +func Wrap(err error, message string) error { + if err == nil { + return nil + } + err = &withMessage{ + cause: err, + msg: message, + } + return &withStack{ + err, + callers(), + } +} + +// Wrapf returns an error annotating err with a stack trace +// at the point Wrapf is call, and the format specifier. +// If err is nil, Wrapf returns nil. +func Wrapf(err error, format string, args ...interface{}) error { + if err == nil { + return nil + } + err = &withMessage{ + cause: err, + msg: fmt.Sprintf(format, args...), + } + return &withStack{ + err, + callers(), + } +} + +// WithMessage annotates err with a new message. +// If err is nil, WithMessage returns nil. +func WithMessage(err error, message string) error { + if err == nil { + return nil + } + return &withMessage{ + cause: err, + msg: message, + } +} + +type withMessage struct { + cause error + msg string +} + +func (w *withMessage) Error() string { return w.msg + ": " + w.cause.Error() } +func (w *withMessage) Cause() error { return w.cause } + +func (w *withMessage) Format(s fmt.State, verb rune) { + switch verb { + case 'v': + if s.Flag('+') { + fmt.Fprintf(s, "%+v\n", w.Cause()) + io.WriteString(s, w.msg) + return + } + fallthrough + case 's', 'q': + io.WriteString(s, w.Error()) + } +} + +// Cause returns the underlying cause of the error, if possible. +// An error value has a cause if it implements the following +// interface: +// +// type causer interface { +// Cause() error +// } +// +// If the error does not implement Cause, the original error will +// be returned. If the error is nil, nil will be returned without further +// investigation. +func Cause(err error) error { + type causer interface { + Cause() error + } + + for err != nil { + cause, ok := err.(causer) + if !ok { + break + } + err = cause.Cause() + } + return err +} diff --git a/vendor/github.com/pkg/errors/errors_test.go b/vendor/github.com/pkg/errors/errors_test.go new file mode 100644 index 00000000..1d8c6355 --- /dev/null +++ b/vendor/github.com/pkg/errors/errors_test.go @@ -0,0 +1,226 @@ +package errors + +import ( + "errors" + "fmt" + "io" + "reflect" + "testing" +) + +func TestNew(t *testing.T) { + tests := []struct { + err string + want error + }{ + {"", fmt.Errorf("")}, + {"foo", fmt.Errorf("foo")}, + {"foo", New("foo")}, + {"string with format specifiers: %v", errors.New("string with format specifiers: %v")}, + } + + for _, tt := range tests { + got := New(tt.err) + if got.Error() != tt.want.Error() { + t.Errorf("New.Error(): got: %q, want %q", got, tt.want) + } + } +} + +func TestWrapNil(t *testing.T) { + got := Wrap(nil, "no error") + if got != nil { + t.Errorf("Wrap(nil, \"no error\"): got %#v, expected nil", got) + } +} + +func TestWrap(t *testing.T) { + tests := []struct { + err error + message string + want string + }{ + {io.EOF, "read error", "read error: EOF"}, + {Wrap(io.EOF, "read error"), "client error", "client error: read error: EOF"}, + } + + for _, tt := range tests { + got := Wrap(tt.err, tt.message).Error() + if got != tt.want { + t.Errorf("Wrap(%v, %q): got: %v, want %v", tt.err, tt.message, got, tt.want) + } + } +} + +type nilError struct{} + +func (nilError) Error() string { return "nil error" } + +func TestCause(t *testing.T) { + x := New("error") + tests := []struct { + err error + want error + }{{ + // nil error is nil + err: nil, + want: nil, + }, { + // explicit nil error is nil + err: (error)(nil), + want: nil, + }, { + // typed nil is nil + err: (*nilError)(nil), + want: (*nilError)(nil), + }, { + // uncaused error is unaffected + err: io.EOF, + want: io.EOF, + }, { + // caused error returns cause + err: Wrap(io.EOF, "ignored"), + want: io.EOF, + }, { + err: x, // return from errors.New + want: x, + }, { + WithMessage(nil, "whoops"), + nil, + }, { + WithMessage(io.EOF, "whoops"), + io.EOF, + }, { + WithStack(nil), + nil, + }, { + WithStack(io.EOF), + io.EOF, + }} + + for i, tt := range tests { + got := Cause(tt.err) + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("test %d: got %#v, want %#v", i+1, got, tt.want) + } + } +} + +func TestWrapfNil(t *testing.T) { + got := Wrapf(nil, "no error") + if got != nil { + t.Errorf("Wrapf(nil, \"no error\"): got %#v, expected nil", got) + } +} + +func TestWrapf(t *testing.T) { + tests := []struct { + err error + message string + want string + }{ + {io.EOF, "read error", "read error: EOF"}, + {Wrapf(io.EOF, "read error without format specifiers"), "client error", "client error: read error without format specifiers: EOF"}, + {Wrapf(io.EOF, "read error with %d format specifier", 1), "client error", "client error: read error with 1 format specifier: EOF"}, + } + + for _, tt := range tests { + got := Wrapf(tt.err, tt.message).Error() + if got != tt.want { + t.Errorf("Wrapf(%v, %q): got: %v, want %v", tt.err, tt.message, got, tt.want) + } + } +} + +func TestErrorf(t *testing.T) { + tests := []struct { + err error + want string + }{ + {Errorf("read error without format specifiers"), "read error without format specifiers"}, + {Errorf("read error with %d format specifier", 1), "read error with 1 format specifier"}, + } + + for _, tt := range tests { + got := tt.err.Error() + if got != tt.want { + t.Errorf("Errorf(%v): got: %q, want %q", tt.err, got, tt.want) + } + } +} + +func TestWithStackNil(t *testing.T) { + got := WithStack(nil) + if got != nil { + t.Errorf("WithStack(nil): got %#v, expected nil", got) + } +} + +func TestWithStack(t *testing.T) { + tests := []struct { + err error + want string + }{ + {io.EOF, "EOF"}, + {WithStack(io.EOF), "EOF"}, + } + + for _, tt := range tests { + got := WithStack(tt.err).Error() + if got != tt.want { + t.Errorf("WithStack(%v): got: %v, want %v", tt.err, got, tt.want) + } + } +} + +func TestWithMessageNil(t *testing.T) { + got := WithMessage(nil, "no error") + if got != nil { + t.Errorf("WithMessage(nil, \"no error\"): got %#v, expected nil", got) + } +} + +func TestWithMessage(t *testing.T) { + tests := []struct { + err error + message string + want string + }{ + {io.EOF, "read error", "read error: EOF"}, + {WithMessage(io.EOF, "read error"), "client error", "client error: read error: EOF"}, + } + + for _, tt := range tests { + got := WithMessage(tt.err, tt.message).Error() + if got != tt.want { + t.Errorf("WithMessage(%v, %q): got: %q, want %q", tt.err, tt.message, got, tt.want) + } + } + +} + +// errors.New, etc values are not expected to be compared by value +// but the change in errors#27 made them incomparable. Assert that +// various kinds of errors have a functional equality operator, even +// if the result of that equality is always false. +func TestErrorEquality(t *testing.T) { + vals := []error{ + nil, + io.EOF, + errors.New("EOF"), + New("EOF"), + Errorf("EOF"), + Wrap(io.EOF, "EOF"), + Wrapf(io.EOF, "EOF%d", 2), + WithMessage(nil, "whoops"), + WithMessage(io.EOF, "whoops"), + WithStack(io.EOF), + WithStack(nil), + } + + for i := range vals { + for j := range vals { + _ = vals[i] == vals[j] // mustn't panic + } + } +} diff --git a/vendor/github.com/pkg/errors/example_test.go b/vendor/github.com/pkg/errors/example_test.go new file mode 100644 index 00000000..c1fc13e3 --- /dev/null +++ b/vendor/github.com/pkg/errors/example_test.go @@ -0,0 +1,205 @@ +package errors_test + +import ( + "fmt" + + "github.com/pkg/errors" +) + +func ExampleNew() { + err := errors.New("whoops") + fmt.Println(err) + + // Output: whoops +} + +func ExampleNew_printf() { + err := errors.New("whoops") + fmt.Printf("%+v", err) + + // Example output: + // whoops + // github.com/pkg/errors_test.ExampleNew_printf + // /home/dfc/src/github.com/pkg/errors/example_test.go:17 + // testing.runExample + // /home/dfc/go/src/testing/example.go:114 + // testing.RunExamples + // /home/dfc/go/src/testing/example.go:38 + // testing.(*M).Run + // /home/dfc/go/src/testing/testing.go:744 + // main.main + // /github.com/pkg/errors/_test/_testmain.go:106 + // runtime.main + // /home/dfc/go/src/runtime/proc.go:183 + // runtime.goexit + // /home/dfc/go/src/runtime/asm_amd64.s:2059 +} + +func ExampleWithMessage() { + cause := errors.New("whoops") + err := errors.WithMessage(cause, "oh noes") + fmt.Println(err) + + // Output: oh noes: whoops +} + +func ExampleWithStack() { + cause := errors.New("whoops") + err := errors.WithStack(cause) + fmt.Println(err) + + // Output: whoops +} + +func ExampleWithStack_printf() { + cause := errors.New("whoops") + err := errors.WithStack(cause) + fmt.Printf("%+v", err) + + // Example Output: + // whoops + // github.com/pkg/errors_test.ExampleWithStack_printf + // /home/fabstu/go/src/github.com/pkg/errors/example_test.go:55 + // testing.runExample + // /usr/lib/go/src/testing/example.go:114 + // testing.RunExamples + // /usr/lib/go/src/testing/example.go:38 + // testing.(*M).Run + // /usr/lib/go/src/testing/testing.go:744 + // main.main + // github.com/pkg/errors/_test/_testmain.go:106 + // runtime.main + // /usr/lib/go/src/runtime/proc.go:183 + // runtime.goexit + // /usr/lib/go/src/runtime/asm_amd64.s:2086 + // github.com/pkg/errors_test.ExampleWithStack_printf + // /home/fabstu/go/src/github.com/pkg/errors/example_test.go:56 + // testing.runExample + // /usr/lib/go/src/testing/example.go:114 + // testing.RunExamples + // /usr/lib/go/src/testing/example.go:38 + // testing.(*M).Run + // /usr/lib/go/src/testing/testing.go:744 + // main.main + // github.com/pkg/errors/_test/_testmain.go:106 + // runtime.main + // /usr/lib/go/src/runtime/proc.go:183 + // runtime.goexit + // /usr/lib/go/src/runtime/asm_amd64.s:2086 +} + +func ExampleWrap() { + cause := errors.New("whoops") + err := errors.Wrap(cause, "oh noes") + fmt.Println(err) + + // Output: oh noes: whoops +} + +func fn() error { + e1 := errors.New("error") + e2 := errors.Wrap(e1, "inner") + e3 := errors.Wrap(e2, "middle") + return errors.Wrap(e3, "outer") +} + +func ExampleCause() { + err := fn() + fmt.Println(err) + fmt.Println(errors.Cause(err)) + + // Output: outer: middle: inner: error + // error +} + +func ExampleWrap_extended() { + err := fn() + fmt.Printf("%+v\n", err) + + // Example output: + // error + // github.com/pkg/errors_test.fn + // /home/dfc/src/github.com/pkg/errors/example_test.go:47 + // github.com/pkg/errors_test.ExampleCause_printf + // /home/dfc/src/github.com/pkg/errors/example_test.go:63 + // testing.runExample + // /home/dfc/go/src/testing/example.go:114 + // testing.RunExamples + // /home/dfc/go/src/testing/example.go:38 + // testing.(*M).Run + // /home/dfc/go/src/testing/testing.go:744 + // main.main + // /github.com/pkg/errors/_test/_testmain.go:104 + // runtime.main + // /home/dfc/go/src/runtime/proc.go:183 + // runtime.goexit + // /home/dfc/go/src/runtime/asm_amd64.s:2059 + // github.com/pkg/errors_test.fn + // /home/dfc/src/github.com/pkg/errors/example_test.go:48: inner + // github.com/pkg/errors_test.fn + // /home/dfc/src/github.com/pkg/errors/example_test.go:49: middle + // github.com/pkg/errors_test.fn + // /home/dfc/src/github.com/pkg/errors/example_test.go:50: outer +} + +func ExampleWrapf() { + cause := errors.New("whoops") + err := errors.Wrapf(cause, "oh noes #%d", 2) + fmt.Println(err) + + // Output: oh noes #2: whoops +} + +func ExampleErrorf_extended() { + err := errors.Errorf("whoops: %s", "foo") + fmt.Printf("%+v", err) + + // Example output: + // whoops: foo + // github.com/pkg/errors_test.ExampleErrorf + // /home/dfc/src/github.com/pkg/errors/example_test.go:101 + // testing.runExample + // /home/dfc/go/src/testing/example.go:114 + // testing.RunExamples + // /home/dfc/go/src/testing/example.go:38 + // testing.(*M).Run + // /home/dfc/go/src/testing/testing.go:744 + // main.main + // /github.com/pkg/errors/_test/_testmain.go:102 + // runtime.main + // /home/dfc/go/src/runtime/proc.go:183 + // runtime.goexit + // /home/dfc/go/src/runtime/asm_amd64.s:2059 +} + +func Example_stackTrace() { + type stackTracer interface { + StackTrace() errors.StackTrace + } + + err, ok := errors.Cause(fn()).(stackTracer) + if !ok { + panic("oops, err does not implement stackTracer") + } + + st := err.StackTrace() + fmt.Printf("%+v", st[0:2]) // top two frames + + // Example output: + // github.com/pkg/errors_test.fn + // /home/dfc/src/github.com/pkg/errors/example_test.go:47 + // github.com/pkg/errors_test.Example_stackTrace + // /home/dfc/src/github.com/pkg/errors/example_test.go:127 +} + +func ExampleCause_printf() { + err := errors.Wrap(func() error { + return func() error { + return errors.Errorf("hello %s", fmt.Sprintf("world")) + }() + }(), "failed") + + fmt.Printf("%v", err) + + // Output: failed: hello world +} diff --git a/vendor/github.com/pkg/errors/format_test.go b/vendor/github.com/pkg/errors/format_test.go new file mode 100644 index 00000000..15fd7d89 --- /dev/null +++ b/vendor/github.com/pkg/errors/format_test.go @@ -0,0 +1,535 @@ +package errors + +import ( + "errors" + "fmt" + "io" + "regexp" + "strings" + "testing" +) + +func TestFormatNew(t *testing.T) { + tests := []struct { + error + format string + want string + }{{ + New("error"), + "%s", + "error", + }, { + New("error"), + "%v", + "error", + }, { + New("error"), + "%+v", + "error\n" + + "github.com/pkg/errors.TestFormatNew\n" + + "\t.+/github.com/pkg/errors/format_test.go:26", + }, { + New("error"), + "%q", + `"error"`, + }} + + for i, tt := range tests { + testFormatRegexp(t, i, tt.error, tt.format, tt.want) + } +} + +func TestFormatErrorf(t *testing.T) { + tests := []struct { + error + format string + want string + }{{ + Errorf("%s", "error"), + "%s", + "error", + }, { + Errorf("%s", "error"), + "%v", + "error", + }, { + Errorf("%s", "error"), + "%+v", + "error\n" + + "github.com/pkg/errors.TestFormatErrorf\n" + + "\t.+/github.com/pkg/errors/format_test.go:56", + }} + + for i, tt := range tests { + testFormatRegexp(t, i, tt.error, tt.format, tt.want) + } +} + +func TestFormatWrap(t *testing.T) { + tests := []struct { + error + format string + want string + }{{ + Wrap(New("error"), "error2"), + "%s", + "error2: error", + }, { + Wrap(New("error"), "error2"), + "%v", + "error2: error", + }, { + Wrap(New("error"), "error2"), + "%+v", + "error\n" + + "github.com/pkg/errors.TestFormatWrap\n" + + "\t.+/github.com/pkg/errors/format_test.go:82", + }, { + Wrap(io.EOF, "error"), + "%s", + "error: EOF", + }, { + Wrap(io.EOF, "error"), + "%v", + "error: EOF", + }, { + Wrap(io.EOF, "error"), + "%+v", + "EOF\n" + + "error\n" + + "github.com/pkg/errors.TestFormatWrap\n" + + "\t.+/github.com/pkg/errors/format_test.go:96", + }, { + Wrap(Wrap(io.EOF, "error1"), "error2"), + "%+v", + "EOF\n" + + "error1\n" + + "github.com/pkg/errors.TestFormatWrap\n" + + "\t.+/github.com/pkg/errors/format_test.go:103\n", + }, { + Wrap(New("error with space"), "context"), + "%q", + `"context: error with space"`, + }} + + for i, tt := range tests { + testFormatRegexp(t, i, tt.error, tt.format, tt.want) + } +} + +func TestFormatWrapf(t *testing.T) { + tests := []struct { + error + format string + want string + }{{ + Wrapf(io.EOF, "error%d", 2), + "%s", + "error2: EOF", + }, { + Wrapf(io.EOF, "error%d", 2), + "%v", + "error2: EOF", + }, { + Wrapf(io.EOF, "error%d", 2), + "%+v", + "EOF\n" + + "error2\n" + + "github.com/pkg/errors.TestFormatWrapf\n" + + "\t.+/github.com/pkg/errors/format_test.go:134", + }, { + Wrapf(New("error"), "error%d", 2), + "%s", + "error2: error", + }, { + Wrapf(New("error"), "error%d", 2), + "%v", + "error2: error", + }, { + Wrapf(New("error"), "error%d", 2), + "%+v", + "error\n" + + "github.com/pkg/errors.TestFormatWrapf\n" + + "\t.+/github.com/pkg/errors/format_test.go:149", + }} + + for i, tt := range tests { + testFormatRegexp(t, i, tt.error, tt.format, tt.want) + } +} + +func TestFormatWithStack(t *testing.T) { + tests := []struct { + error + format string + want []string + }{{ + WithStack(io.EOF), + "%s", + []string{"EOF"}, + }, { + WithStack(io.EOF), + "%v", + []string{"EOF"}, + }, { + WithStack(io.EOF), + "%+v", + []string{"EOF", + "github.com/pkg/errors.TestFormatWithStack\n" + + "\t.+/github.com/pkg/errors/format_test.go:175"}, + }, { + WithStack(New("error")), + "%s", + []string{"error"}, + }, { + WithStack(New("error")), + "%v", + []string{"error"}, + }, { + WithStack(New("error")), + "%+v", + []string{"error", + "github.com/pkg/errors.TestFormatWithStack\n" + + "\t.+/github.com/pkg/errors/format_test.go:189", + "github.com/pkg/errors.TestFormatWithStack\n" + + "\t.+/github.com/pkg/errors/format_test.go:189"}, + }, { + WithStack(WithStack(io.EOF)), + "%+v", + []string{"EOF", + "github.com/pkg/errors.TestFormatWithStack\n" + + "\t.+/github.com/pkg/errors/format_test.go:197", + "github.com/pkg/errors.TestFormatWithStack\n" + + "\t.+/github.com/pkg/errors/format_test.go:197"}, + }, { + WithStack(WithStack(Wrapf(io.EOF, "message"))), + "%+v", + []string{"EOF", + "message", + "github.com/pkg/errors.TestFormatWithStack\n" + + "\t.+/github.com/pkg/errors/format_test.go:205", + "github.com/pkg/errors.TestFormatWithStack\n" + + "\t.+/github.com/pkg/errors/format_test.go:205", + "github.com/pkg/errors.TestFormatWithStack\n" + + "\t.+/github.com/pkg/errors/format_test.go:205"}, + }, { + WithStack(Errorf("error%d", 1)), + "%+v", + []string{"error1", + "github.com/pkg/errors.TestFormatWithStack\n" + + "\t.+/github.com/pkg/errors/format_test.go:216", + "github.com/pkg/errors.TestFormatWithStack\n" + + "\t.+/github.com/pkg/errors/format_test.go:216"}, + }} + + for i, tt := range tests { + testFormatCompleteCompare(t, i, tt.error, tt.format, tt.want, true) + } +} + +func TestFormatWithMessage(t *testing.T) { + tests := []struct { + error + format string + want []string + }{{ + WithMessage(New("error"), "error2"), + "%s", + []string{"error2: error"}, + }, { + WithMessage(New("error"), "error2"), + "%v", + []string{"error2: error"}, + }, { + WithMessage(New("error"), "error2"), + "%+v", + []string{ + "error", + "github.com/pkg/errors.TestFormatWithMessage\n" + + "\t.+/github.com/pkg/errors/format_test.go:244", + "error2"}, + }, { + WithMessage(io.EOF, "addition1"), + "%s", + []string{"addition1: EOF"}, + }, { + WithMessage(io.EOF, "addition1"), + "%v", + []string{"addition1: EOF"}, + }, { + WithMessage(io.EOF, "addition1"), + "%+v", + []string{"EOF", "addition1"}, + }, { + WithMessage(WithMessage(io.EOF, "addition1"), "addition2"), + "%v", + []string{"addition2: addition1: EOF"}, + }, { + WithMessage(WithMessage(io.EOF, "addition1"), "addition2"), + "%+v", + []string{"EOF", "addition1", "addition2"}, + }, { + Wrap(WithMessage(io.EOF, "error1"), "error2"), + "%+v", + []string{"EOF", "error1", "error2", + "github.com/pkg/errors.TestFormatWithMessage\n" + + "\t.+/github.com/pkg/errors/format_test.go:272"}, + }, { + WithMessage(Errorf("error%d", 1), "error2"), + "%+v", + []string{"error1", + "github.com/pkg/errors.TestFormatWithMessage\n" + + "\t.+/github.com/pkg/errors/format_test.go:278", + "error2"}, + }, { + WithMessage(WithStack(io.EOF), "error"), + "%+v", + []string{ + "EOF", + "github.com/pkg/errors.TestFormatWithMessage\n" + + "\t.+/github.com/pkg/errors/format_test.go:285", + "error"}, + }, { + WithMessage(Wrap(WithStack(io.EOF), "inside-error"), "outside-error"), + "%+v", + []string{ + "EOF", + "github.com/pkg/errors.TestFormatWithMessage\n" + + "\t.+/github.com/pkg/errors/format_test.go:293", + "inside-error", + "github.com/pkg/errors.TestFormatWithMessage\n" + + "\t.+/github.com/pkg/errors/format_test.go:293", + "outside-error"}, + }} + + for i, tt := range tests { + testFormatCompleteCompare(t, i, tt.error, tt.format, tt.want, true) + } +} + +func TestFormatGeneric(t *testing.T) { + starts := []struct { + err error + want []string + }{ + {New("new-error"), []string{ + "new-error", + "github.com/pkg/errors.TestFormatGeneric\n" + + "\t.+/github.com/pkg/errors/format_test.go:315"}, + }, {Errorf("errorf-error"), []string{ + "errorf-error", + "github.com/pkg/errors.TestFormatGeneric\n" + + "\t.+/github.com/pkg/errors/format_test.go:319"}, + }, {errors.New("errors-new-error"), []string{ + "errors-new-error"}, + }, + } + + wrappers := []wrapper{ + { + func(err error) error { return WithMessage(err, "with-message") }, + []string{"with-message"}, + }, { + func(err error) error { return WithStack(err) }, + []string{ + "github.com/pkg/errors.(func·002|TestFormatGeneric.func2)\n\t" + + ".+/github.com/pkg/errors/format_test.go:333", + }, + }, { + func(err error) error { return Wrap(err, "wrap-error") }, + []string{ + "wrap-error", + "github.com/pkg/errors.(func·003|TestFormatGeneric.func3)\n\t" + + ".+/github.com/pkg/errors/format_test.go:339", + }, + }, { + func(err error) error { return Wrapf(err, "wrapf-error%d", 1) }, + []string{ + "wrapf-error1", + "github.com/pkg/errors.(func·004|TestFormatGeneric.func4)\n\t" + + ".+/github.com/pkg/errors/format_test.go:346", + }, + }, + } + + for s := range starts { + err := starts[s].err + want := starts[s].want + testFormatCompleteCompare(t, s, err, "%+v", want, false) + testGenericRecursive(t, err, want, wrappers, 3) + } +} + +func testFormatRegexp(t *testing.T, n int, arg interface{}, format, want string) { + got := fmt.Sprintf(format, arg) + gotLines := strings.SplitN(got, "\n", -1) + wantLines := strings.SplitN(want, "\n", -1) + + if len(wantLines) > len(gotLines) { + t.Errorf("test %d: wantLines(%d) > gotLines(%d):\n got: %q\nwant: %q", n+1, len(wantLines), len(gotLines), got, want) + return + } + + for i, w := range wantLines { + match, err := regexp.MatchString(w, gotLines[i]) + if err != nil { + t.Fatal(err) + } + if !match { + t.Errorf("test %d: line %d: fmt.Sprintf(%q, err):\n got: %q\nwant: %q", n+1, i+1, format, got, want) + } + } +} + +var stackLineR = regexp.MustCompile(`\.`) + +// parseBlocks parses input into a slice, where: +// - incase entry contains a newline, its a stacktrace +// - incase entry contains no newline, its a solo line. +// +// Detecting stack boundaries only works incase the WithStack-calls are +// to be found on the same line, thats why it is optionally here. +// +// Example use: +// +// for _, e := range blocks { +// if strings.ContainsAny(e, "\n") { +// // Match as stack +// } else { +// // Match as line +// } +// } +// +func parseBlocks(input string, detectStackboundaries bool) ([]string, error) { + var blocks []string + + stack := "" + wasStack := false + lines := map[string]bool{} // already found lines + + for _, l := range strings.Split(input, "\n") { + isStackLine := stackLineR.MatchString(l) + + switch { + case !isStackLine && wasStack: + blocks = append(blocks, stack, l) + stack = "" + lines = map[string]bool{} + case isStackLine: + if wasStack { + // Detecting two stacks after another, possible cause lines match in + // our tests due to WithStack(WithStack(io.EOF)) on same line. + if detectStackboundaries { + if lines[l] { + if len(stack) == 0 { + return nil, errors.New("len of block must not be zero here") + } + + blocks = append(blocks, stack) + stack = l + lines = map[string]bool{l: true} + continue + } + } + + stack = stack + "\n" + l + } else { + stack = l + } + lines[l] = true + case !isStackLine && !wasStack: + blocks = append(blocks, l) + default: + return nil, errors.New("must not happen") + } + + wasStack = isStackLine + } + + // Use up stack + if stack != "" { + blocks = append(blocks, stack) + } + return blocks, nil +} + +func testFormatCompleteCompare(t *testing.T, n int, arg interface{}, format string, want []string, detectStackBoundaries bool) { + gotStr := fmt.Sprintf(format, arg) + + got, err := parseBlocks(gotStr, detectStackBoundaries) + if err != nil { + t.Fatal(err) + } + + if len(got) != len(want) { + t.Fatalf("test %d: fmt.Sprintf(%s, err) -> wrong number of blocks: got(%d) want(%d)\n got: %s\nwant: %s\ngotStr: %q", + n+1, format, len(got), len(want), prettyBlocks(got), prettyBlocks(want), gotStr) + } + + for i := range got { + if strings.ContainsAny(want[i], "\n") { + // Match as stack + match, err := regexp.MatchString(want[i], got[i]) + if err != nil { + t.Fatal(err) + } + if !match { + t.Fatalf("test %d: block %d: fmt.Sprintf(%q, err):\ngot:\n%q\nwant:\n%q\nall-got:\n%s\nall-want:\n%s\n", + n+1, i+1, format, got[i], want[i], prettyBlocks(got), prettyBlocks(want)) + } + } else { + // Match as message + if got[i] != want[i] { + t.Fatalf("test %d: fmt.Sprintf(%s, err) at block %d got != want:\n got: %q\nwant: %q", n+1, format, i+1, got[i], want[i]) + } + } + } +} + +type wrapper struct { + wrap func(err error) error + want []string +} + +func prettyBlocks(blocks []string, prefix ...string) string { + var out []string + + for _, b := range blocks { + out = append(out, fmt.Sprintf("%v", b)) + } + + return " " + strings.Join(out, "\n ") +} + +func testGenericRecursive(t *testing.T, beforeErr error, beforeWant []string, list []wrapper, maxDepth int) { + if len(beforeWant) == 0 { + panic("beforeWant must not be empty") + } + for _, w := range list { + if len(w.want) == 0 { + panic("want must not be empty") + } + + err := w.wrap(beforeErr) + + // Copy required cause append(beforeWant, ..) modified beforeWant subtly. + beforeCopy := make([]string, len(beforeWant)) + copy(beforeCopy, beforeWant) + + beforeWant := beforeCopy + last := len(beforeWant) - 1 + var want []string + + // Merge two stacks behind each other. + if strings.ContainsAny(beforeWant[last], "\n") && strings.ContainsAny(w.want[0], "\n") { + want = append(beforeWant[:last], append([]string{beforeWant[last] + "((?s).*)" + w.want[0]}, w.want[1:]...)...) + } else { + want = append(beforeWant, w.want...) + } + + testFormatCompleteCompare(t, maxDepth, err, "%+v", want, false) + if maxDepth > 0 { + testGenericRecursive(t, err, want, list, maxDepth-1) + } + } +} diff --git a/vendor/github.com/pkg/errors/stack.go b/vendor/github.com/pkg/errors/stack.go new file mode 100644 index 00000000..6b1f2891 --- /dev/null +++ b/vendor/github.com/pkg/errors/stack.go @@ -0,0 +1,178 @@ +package errors + +import ( + "fmt" + "io" + "path" + "runtime" + "strings" +) + +// Frame represents a program counter inside a stack frame. +type Frame uintptr + +// pc returns the program counter for this frame; +// multiple frames may have the same PC value. +func (f Frame) pc() uintptr { return uintptr(f) - 1 } + +// file returns the full path to the file that contains the +// function for this Frame's pc. +func (f Frame) file() string { + fn := runtime.FuncForPC(f.pc()) + if fn == nil { + return "unknown" + } + file, _ := fn.FileLine(f.pc()) + return file +} + +// line returns the line number of source code of the +// function for this Frame's pc. +func (f Frame) line() int { + fn := runtime.FuncForPC(f.pc()) + if fn == nil { + return 0 + } + _, line := fn.FileLine(f.pc()) + return line +} + +// Format formats the frame according to the fmt.Formatter interface. +// +// %s source file +// %d source line +// %n function name +// %v equivalent to %s:%d +// +// Format accepts flags that alter the printing of some verbs, as follows: +// +// %+s path of source file relative to the compile time GOPATH +// %+v equivalent to %+s:%d +func (f Frame) Format(s fmt.State, verb rune) { + switch verb { + 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) + } + default: + io.WriteString(s, path.Base(f.file())) + } + case 'd': + fmt.Fprintf(s, "%d", f.line()) + case 'n': + name := runtime.FuncForPC(f.pc()).Name() + io.WriteString(s, funcname(name)) + case 'v': + f.Format(s, 's') + io.WriteString(s, ":") + f.Format(s, 'd') + } +} + +// StackTrace is stack of Frames from innermost (newest) to outermost (oldest). +type StackTrace []Frame + +func (st StackTrace) Format(s fmt.State, verb rune) { + switch verb { + case 'v': + switch { + case s.Flag('+'): + for _, f := range st { + fmt.Fprintf(s, "\n%+v", f) + } + case s.Flag('#'): + fmt.Fprintf(s, "%#v", []Frame(st)) + default: + fmt.Fprintf(s, "%v", []Frame(st)) + } + case 's': + fmt.Fprintf(s, "%s", []Frame(st)) + } +} + +// stack represents a stack of program counters. +type stack []uintptr + +func (s *stack) Format(st fmt.State, verb rune) { + switch verb { + case 'v': + switch { + case st.Flag('+'): + for _, pc := range *s { + f := Frame(pc) + fmt.Fprintf(st, "\n%+v", f) + } + } + } +} + +func (s *stack) StackTrace() StackTrace { + f := make([]Frame, len(*s)) + for i := 0; i < len(f); i++ { + f[i] = Frame((*s)[i]) + } + return f +} + +func callers() *stack { + const depth = 32 + var pcs [depth]uintptr + n := runtime.Callers(3, pcs[:]) + var st stack = pcs[0:n] + return &st +} + +// funcname removes the path prefix component of a function's name reported by func.Name(). +func funcname(name string) string { + i := strings.LastIndex(name, "/") + name = name[i+1:] + i = strings.Index(name, ".") + return name[i+1:] +} + +func trimGOPATH(name, file string) string { + // Here we want to get the source file path relative to the compile time + // GOPATH. As of Go 1.6.x there is no direct way to know the compiled + // GOPATH at runtime, but we can infer the number of path segments in the + // GOPATH. We note that fn.Name() returns the function name qualified by + // the import path, which does not include the GOPATH. Thus we can trim + // segments from the beginning of the file path until the number of path + // separators remaining is one more than the number of path separators in + // the function name. For example, given: + // + // GOPATH /home/user + // file /home/user/src/pkg/sub/file.go + // fn.Name() pkg/sub.Type.Method + // + // We want to produce: + // + // pkg/sub/file.go + // + // From this we can easily see that fn.Name() has one less path separator + // than our desired output. We count separators from the end of the file + // path until it finds two more than in the function name and then move + // one character forward to preserve the initial path segment without a + // leading separator. + const sep = "/" + goal := strings.Count(name, sep) + 2 + i := len(file) + for n := 0; n < goal; n++ { + i = strings.LastIndex(file[:i], sep) + if i == -1 { + // not enough separators found, set i so that the slice expression + // below leaves file unmodified + i = -len(sep) + break + } + } + // get back to 0 or trim the leading separator + file = file[i+len(sep):] + return file +} diff --git a/vendor/github.com/pkg/errors/stack_test.go b/vendor/github.com/pkg/errors/stack_test.go new file mode 100644 index 00000000..510c27a9 --- /dev/null +++ b/vendor/github.com/pkg/errors/stack_test.go @@ -0,0 +1,292 @@ +package errors + +import ( + "fmt" + "runtime" + "testing" +) + +var initpc, _, _, _ = runtime.Caller(0) + +func TestFrameLine(t *testing.T) { + var tests = []struct { + Frame + want int + }{{ + Frame(initpc), + 9, + }, { + func() Frame { + var pc, _, _, _ = runtime.Caller(0) + return Frame(pc) + }(), + 20, + }, { + func() Frame { + var pc, _, _, _ = runtime.Caller(1) + return Frame(pc) + }(), + 28, + }, { + Frame(0), // invalid PC + 0, + }} + + for _, tt := range tests { + got := tt.Frame.line() + want := tt.want + if want != got { + t.Errorf("Frame(%v): want: %v, got: %v", uintptr(tt.Frame), want, got) + } + } +} + +type X struct{} + +func (x X) val() Frame { + var pc, _, _, _ = runtime.Caller(0) + return Frame(pc) +} + +func (x *X) ptr() Frame { + var pc, _, _, _ = runtime.Caller(0) + return Frame(pc) +} + +func TestFrameFormat(t *testing.T) { + var tests = []struct { + Frame + format string + want string + }{{ + Frame(initpc), + "%s", + "stack_test.go", + }, { + Frame(initpc), + "%+s", + "github.com/pkg/errors.init\n" + + "\t.+/github.com/pkg/errors/stack_test.go", + }, { + Frame(0), + "%s", + "unknown", + }, { + Frame(0), + "%+s", + "unknown", + }, { + Frame(initpc), + "%d", + "9", + }, { + Frame(0), + "%d", + "0", + }, { + Frame(initpc), + "%n", + "init", + }, { + func() Frame { + var x X + return x.ptr() + }(), + "%n", + `\(\*X\).ptr`, + }, { + func() Frame { + var x X + return x.val() + }(), + "%n", + "X.val", + }, { + Frame(0), + "%n", + "", + }, { + Frame(initpc), + "%v", + "stack_test.go:9", + }, { + Frame(initpc), + "%+v", + "github.com/pkg/errors.init\n" + + "\t.+/github.com/pkg/errors/stack_test.go:9", + }, { + Frame(0), + "%v", + "unknown:0", + }} + + for i, tt := range tests { + testFormatRegexp(t, i, tt.Frame, tt.format, tt.want) + } +} + +func TestFuncname(t *testing.T) { + tests := []struct { + name, want string + }{ + {"", ""}, + {"runtime.main", "main"}, + {"github.com/pkg/errors.funcname", "funcname"}, + {"funcname", "funcname"}, + {"io.copyBuffer", "copyBuffer"}, + {"main.(*R).Write", "(*R).Write"}, + } + + for _, tt := range tests { + got := funcname(tt.name) + want := tt.want + if got != want { + t.Errorf("funcname(%q): want: %q, got %q", tt.name, want, got) + } + } +} + +func TestTrimGOPATH(t *testing.T) { + var tests = []struct { + Frame + want string + }{{ + Frame(initpc), + "github.com/pkg/errors/stack_test.go", + }} + + for i, tt := range tests { + pc := tt.Frame.pc() + fn := runtime.FuncForPC(pc) + file, _ := fn.FileLine(pc) + got := trimGOPATH(fn.Name(), file) + testFormatRegexp(t, i, got, "%s", tt.want) + } +} + +func TestStackTrace(t *testing.T) { + tests := []struct { + err error + want []string + }{{ + New("ooh"), []string{ + "github.com/pkg/errors.TestStackTrace\n" + + "\t.+/github.com/pkg/errors/stack_test.go:172", + }, + }, { + Wrap(New("ooh"), "ahh"), []string{ + "github.com/pkg/errors.TestStackTrace\n" + + "\t.+/github.com/pkg/errors/stack_test.go:177", // this is the stack of Wrap, not New + }, + }, { + Cause(Wrap(New("ooh"), "ahh")), []string{ + "github.com/pkg/errors.TestStackTrace\n" + + "\t.+/github.com/pkg/errors/stack_test.go:182", // this is the stack of New + }, + }, { + func() error { return New("ooh") }(), []string{ + `github.com/pkg/errors.(func·009|TestStackTrace.func1)` + + "\n\t.+/github.com/pkg/errors/stack_test.go:187", // this is the stack of New + "github.com/pkg/errors.TestStackTrace\n" + + "\t.+/github.com/pkg/errors/stack_test.go:187", // this is the stack of New's caller + }, + }, { + Cause(func() error { + return func() error { + return Errorf("hello %s", fmt.Sprintf("world")) + }() + }()), []string{ + `github.com/pkg/errors.(func·010|TestStackTrace.func2.1)` + + "\n\t.+/github.com/pkg/errors/stack_test.go:196", // this is the stack of Errorf + `github.com/pkg/errors.(func·011|TestStackTrace.func2)` + + "\n\t.+/github.com/pkg/errors/stack_test.go:197", // this is the stack of Errorf's caller + "github.com/pkg/errors.TestStackTrace\n" + + "\t.+/github.com/pkg/errors/stack_test.go:198", // this is the stack of Errorf's caller's caller + }, + }} + for i, tt := range tests { + x, ok := tt.err.(interface { + StackTrace() StackTrace + }) + if !ok { + t.Errorf("expected %#v to implement StackTrace() StackTrace", tt.err) + continue + } + st := x.StackTrace() + for j, want := range tt.want { + testFormatRegexp(t, i, st[j], "%+v", want) + } + } +} + +func stackTrace() StackTrace { + const depth = 8 + var pcs [depth]uintptr + n := runtime.Callers(1, pcs[:]) + var st stack = pcs[0:n] + return st.StackTrace() +} + +func TestStackTraceFormat(t *testing.T) { + tests := []struct { + StackTrace + format string + want string + }{{ + nil, + "%s", + `\[\]`, + }, { + nil, + "%v", + `\[\]`, + }, { + nil, + "%+v", + "", + }, { + nil, + "%#v", + `\[\]errors.Frame\(nil\)`, + }, { + make(StackTrace, 0), + "%s", + `\[\]`, + }, { + make(StackTrace, 0), + "%v", + `\[\]`, + }, { + make(StackTrace, 0), + "%+v", + "", + }, { + make(StackTrace, 0), + "%#v", + `\[\]errors.Frame{}`, + }, { + stackTrace()[:2], + "%s", + `\[stack_test.go stack_test.go\]`, + }, { + stackTrace()[:2], + "%v", + `\[stack_test.go:225 stack_test.go:272\]`, + }, { + stackTrace()[:2], + "%+v", + "\n" + + "github.com/pkg/errors.stackTrace\n" + + "\t.+/github.com/pkg/errors/stack_test.go:225\n" + + "github.com/pkg/errors.TestStackTraceFormat\n" + + "\t.+/github.com/pkg/errors/stack_test.go:276", + }, { + stackTrace()[:2], + "%#v", + `\[\]errors.Frame{stack_test.go:225, stack_test.go:284}`, + }} + + for i, tt := range tests { + testFormatRegexp(t, i, tt.StackTrace, tt.format, tt.want) + } +} diff --git a/vendor/github.com/sdboyer/constext/LICENSE b/vendor/github.com/sdboyer/constext/LICENSE new file mode 100644 index 00000000..fdbc31c7 --- /dev/null +++ b/vendor/github.com/sdboyer/constext/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2017 Sam Boyer + +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/sdboyer/constext/README.md b/vendor/github.com/sdboyer/constext/README.md new file mode 100644 index 00000000..e267fd54 --- /dev/null +++ b/vendor/github.com/sdboyer/constext/README.md @@ -0,0 +1,78 @@ +# constext [![Doc Status](https://godoc.org/github.com/sdboyer/constext?status.png)](https://godoc.org/github.com/sdboyer/constext) + +constext allows you to [`cons`](https://en.wikipedia.org/wiki/Cons) `Context`s +together as a pair, conjoining them for the purpose of all `Context` behaviors: + +1. If either parent context is canceled, the constext is canceled. The + err is set to whatever the err of the parent that was canceled. +2. If either parent has a deadline, the constext uses that same + deadline. If both have a deadline, it uses the sooner/lesser one. +3. Values from both parents are unioned together. When a key is present in both + parent trees, the left (first) context supercedes the right (second). + +Paired contexts can be recombined using the standard `context.With*()` +functions. + +## Usage + +Use is simple, and patterned after the `context` package. The `constext.Cons()` +function takes two `context.Context` arguments and returns a single, unified +one, along with a `context.CancelFunc`. + +```go +cctx, cancelFunc := constext.Cons(context.Background(), context.Background()) +``` + +True to the spirit of `cons`, recursive trees can be formed through +nesting: + +```go +bg := context.Background() +cctx := constext.Cons(bg, constext.Cons(bg, constext.Cons(bg, bg))) +``` + +This probably isn't a good idea, but it's possible. + +## Rationale + +While the unary model of context works well for the original vision - an object +operating within an [HTTP] request's scope - there are times when we need a +little more. + +For example: in [dep](https://github.com/golang/dep), the subsystem that +manages interaction with source repositories is called a +[`SourceManager`](https://godoc.org/github.com/sdboyer/gps#SourceManager). It +is a long-lived object; generally, only one is created over the course of any +single `dep` invocation. The `SourceManager` has a number of methods on it that +may initiate network and/or disk interaction. As such, these methods need to +take a `context.Context`, so that the caller can cancel them if needed. + +However, this is not sufficient. The `SourceManager` itself may need to be +terminated (e.g., if the process received a signal). In such a case, in-flight +method calls also need to be canceled, to avoid leaving disk in inconsistent +state. + +As a result, each in-flight request serves two parents - the initator of the +request, and the `SourceManager` itself. We can abstract away this complexity +by having a `Context` for each, and `Cons`ing them together on a per-call +basis. + +## Caveats + +_tl;dr: GC doesn't work right, so explicitly cancel constexts when done with them._ + +The stdlib context packages uses internal tree-walking trickery to avoid +spawning goroutines unless it actually has to. We can't rely on that same +trickery, in part because we can't access the tree internals, but also because +it's not so straightforward when multiple parents are involved. Consequently, +`Cons()` almost always must spawn a goroutine to ensure correct cancellation +behavior, whereas e.g. `context.WithCancel()` rarely has to. + +If, as in the use case above, your constext has one short-lived and one +long-lived parent, and the short-lived parent is not explicitly canceled (which +is typical), then until the long-lived parent is canceled, neither the +constext, nor any otherwise-unreachable members of the short-lived context tree +will be GCed. + +So, for now, explicitly cancel your constexts before they go out of scope, +otherwise you'll leak memory. diff --git a/vendor/github.com/sdboyer/constext/constext.go b/vendor/github.com/sdboyer/constext/constext.go new file mode 100644 index 00000000..09e37709 --- /dev/null +++ b/vendor/github.com/sdboyer/constext/constext.go @@ -0,0 +1,123 @@ +// Package constext provides facilities for pairing contexts together so that +// they behave as one. + +package constext + +import ( + "context" + "sync" + "time" +) + +type constext struct { + car, cdr context.Context + done chan struct{} // chan closed on cancelFunc() call, or parent done + once sync.Once // protects cancel func + mu sync.Mutex // protects timer and err + err error // err set on cancel or timeout +} + +// Cons takes two Contexts and combines them into a pair, conjoining their +// behavior: +// +// - If either parent context is canceled, the constext is canceled. The err is +// set to whatever the err of the parent that was canceled. +// - If either parent has a deadline, the constext uses that same deadline. If +// both have a deadline, it uses the sooner/lesser one. +// - Values from both parents are unioned together. When a key is present in +// both parent trees, the left (first) context supercedes the right (second). +// +// All the normal context.With*() funcs should incorporate constexts correctly. +// +// If the two parent contexts both return a nil channel from Done() (which can +// occur if both parents are Background, or were created only through +// context.WithValue()), then the returned cancelFunc() is a no-op; calling it +// will NOT result in the termination of any sub-contexts later created. +func Cons(l, r context.Context) (context.Context, context.CancelFunc) { + cc := &constext{ + car: l, + cdr: r, + done: make(chan struct{}), + } + + if cc.car.Done() == nil && cc.cdr.Done() == nil { + // Both parents are un-cancelable, so it's more technically correct to + // return a no-op func here. + return cc, func() {} + } + + if cc.car.Err() != nil { + cc.cancel(cc.car.Err()) + return cc, func() {} + } + if cc.cdr.Err() != nil { + cc.cancel(cc.cdr.Err()) + return cc, func() {} + } + + go func() { + select { + case <-cc.car.Done(): + cc.cancel(cc.car.Err()) + case <-cc.cdr.Done(): + cc.cancel(cc.cdr.Err()) + case <-cc.done: + // Ensure the goroutine dies when canceled + } + }() + + return cc, func() { cc.cancel(context.Canceled) } +} + +func (cc *constext) cancel(err error) { + cc.once.Do(func() { + if err == nil { + panic("constext: internal error: missing cancel error") + } + + cc.mu.Lock() + if cc.err == nil { + cc.err = err + close(cc.done) + } + cc.mu.Unlock() + }) +} + +func (cc *constext) Deadline() (time.Time, bool) { + hdeadline, hok := cc.car.Deadline() + tdeadline, tok := cc.cdr.Deadline() + if !hok && !tok { + return time.Time{}, false + } + + if hok && !tok { + return hdeadline, true + } + if !hok && tok { + return tdeadline, true + } + + if hdeadline.Before(tdeadline) { + return hdeadline, true + } + return tdeadline, true +} + +func (cc *constext) Done() <-chan struct{} { + return cc.done +} + +func (cc *constext) Err() error { + cc.mu.Lock() + defer cc.mu.Unlock() + return cc.err +} + +func (cc *constext) Value(key interface{}) interface{} { + v := cc.car.Value(key) + if v != nil { + return v + } + return cc.cdr.Value(key) +} diff --git a/vendor/github.com/sdboyer/constext/constext_test.go b/vendor/github.com/sdboyer/constext/constext_test.go new file mode 100644 index 00000000..907483b2 --- /dev/null +++ b/vendor/github.com/sdboyer/constext/constext_test.go @@ -0,0 +1,156 @@ +package constext + +import ( + "context" + "runtime" + "testing" + "time" +) + +var bgc = context.Background() + +func TestConsCancel(t *testing.T) { + c1, cancel1 := context.WithCancel(bgc) + c2, cancel2 := context.WithCancel(bgc) + + cc, _ := Cons(c1, c2) + if _, has := cc.Deadline(); has { + t.Fatal("constext should not have a deadline if parents do not") + } + + cancel1() + select { + case <-cc.Done(): + case <-time.After(1 * time.Second): + buf := make([]byte, 10<<10) + n := runtime.Stack(buf, true) + t.Fatalf("timed out waiting for parent to quit; stacks:\n%s", buf[:n]) + } + + cc, _ = Cons(c1, c2) + if cc.Err() == nil { + t.Fatal("pre-canceled car constext did not begin canceled") + } + + cc, _ = Cons(c2, c1) + if cc.Err() == nil { + t.Fatal("pre-canceled cdr constext did not begin canceled") + } + + c3, _ := context.WithCancel(bgc) + cc, _ = Cons(c3, c2) + cancel2() + select { + case <-cc.Done(): + case <-time.After(1 * time.Second): + buf := make([]byte, 10<<10) + n := runtime.Stack(buf, true) + t.Fatalf("timed out waiting for cdr to quit; stacks:\n%s", buf[:n]) + } +} + +func TestCancelPassdown(t *testing.T) { + c1, cancel1 := context.WithCancel(bgc) + c2, _ := context.WithCancel(bgc) + cc, _ := Cons(c1, c2) + c3, _ := context.WithCancel(cc) + + cancel1() + select { + case <-c3.Done(): + case <-time.After(1 * time.Second): + buf := make([]byte, 10<<10) + n := runtime.Stack(buf, true) + t.Fatalf("timed out waiting for parent to quit; stacks:\n%s", buf[:n]) + } + + c1, cancel1 = context.WithCancel(bgc) + cc, _ = Cons(c1, c2) + c3 = context.WithValue(cc, "foo", "bar") + + cancel1() + select { + case <-c3.Done(): + case <-time.After(1 * time.Second): + buf := make([]byte, 10<<10) + n := runtime.Stack(buf, true) + t.Fatalf("timed out waiting for parent to quit; stacks:\n%s", buf[:n]) + } +} + +func TestValueUnion(t *testing.T) { + c1 := context.WithValue(bgc, "foo", "bar") + c2 := context.WithValue(bgc, "foo", "baz") + cc, _ := Cons(c1, c2) + + v := cc.Value("foo") + if v != "bar" { + t.Fatalf("wanted value of \"foo\" from car, \"bar\", got %q", v) + } + + c3 := context.WithValue(bgc, "bar", "quux") + cc2, _ := Cons(c1, c3) + v = cc2.Value("bar") + if v != "quux" { + t.Fatalf("wanted value from cdr, \"quux\", got %q", v) + } + + cc, _ = Cons(cc, c3) + v = cc.Value("bar") + if v != "quux" { + t.Fatalf("wanted value from nested cdr, \"quux\", got %q", v) + } +} + +func TestDeadline(t *testing.T) { + t1 := time.Now().Add(1 * time.Second) + c1, _ := context.WithDeadline(bgc, t1) + cc, _ := Cons(c1, bgc) + + cct, ok := cc.Deadline() + if !ok { + t.Fatal("constext claimed to not have any deadline, but car did") + } + if cct != t1 { + t.Fatal("constext did not have correct deadline") + } + + cc, _ = Cons(bgc, c1) + cct, ok = cc.Deadline() + if !ok { + t.Fatal("constext claimed to not have any deadline, but cdr did") + } + if cct != t1 { + t.Fatal("constext did not have correct deadline") + } + + t2 := time.Now().Add(1 * time.Second) + c2, _ := context.WithDeadline(bgc, t2) + cc, _ = Cons(c1, c2) + cct, ok = cc.Deadline() + if !ok { + t.Fatal("constext claimed to not have any deadline, but both parents did") + } + + if cct != t1 { + t.Fatal("got wrong deadline time back") + } + + cc, _ = Cons(c2, c1) + cct, ok = cc.Deadline() + if !ok { + t.Fatal("constext claimed to not have any deadline, but both parents did") + } + + if cct != t1 { + t.Fatal("got wrong deadline time back") + } + + select { + case <-cc.Done(): + case <-time.After(t1.Sub(time.Now()) + 5*time.Millisecond): + buf := make([]byte, 10<<10) + n := runtime.Stack(buf, true) + t.Fatalf("car did not quit after deadline; stacks:\n%s", buf[:n]) + } +} diff --git a/vendor/golang.org/x/sync/AUTHORS b/vendor/golang.org/x/sync/AUTHORS new file mode 100644 index 00000000..15167cd7 --- /dev/null +++ b/vendor/golang.org/x/sync/AUTHORS @@ -0,0 +1,3 @@ +# This source code refers to The Go Authors for copyright purposes. +# The master list of authors is in the main Go distribution, +# visible at http://tip.golang.org/AUTHORS. diff --git a/vendor/golang.org/x/sync/CONTRIBUTING.md b/vendor/golang.org/x/sync/CONTRIBUTING.md new file mode 100644 index 00000000..88dff59b --- /dev/null +++ b/vendor/golang.org/x/sync/CONTRIBUTING.md @@ -0,0 +1,31 @@ +# Contributing to Go + +Go is an open source project. + +It is the work of hundreds of contributors. We appreciate your help! + + +## Filing issues + +When [filing an issue](https://golang.org/issue/new), make sure to answer these five questions: + +1. What version of Go are you using (`go version`)? +2. What operating system and processor architecture are you using? +3. What did you do? +4. What did you expect to see? +5. What did you see instead? + +General questions should go to the [golang-nuts mailing list](https://groups.google.com/group/golang-nuts) instead of the issue tracker. +The gophers there will answer or ask you to file an issue if you've tripped over a bug. + +## Contributing code + +Please read the [Contribution Guidelines](https://golang.org/doc/contribute.html) +before sending patches. + +**We do not accept GitHub pull requests** +(we use [Gerrit](https://code.google.com/p/gerrit/) instead for code review). + +Unless otherwise noted, the Go source files are distributed under +the BSD-style license found in the LICENSE file. + diff --git a/vendor/golang.org/x/sync/CONTRIBUTORS b/vendor/golang.org/x/sync/CONTRIBUTORS new file mode 100644 index 00000000..1c4577e9 --- /dev/null +++ b/vendor/golang.org/x/sync/CONTRIBUTORS @@ -0,0 +1,3 @@ +# This source code was written by the Go contributors. +# The master list of contributors is in the main Go distribution, +# visible at http://tip.golang.org/CONTRIBUTORS. diff --git a/vendor/golang.org/x/sync/LICENSE b/vendor/golang.org/x/sync/LICENSE new file mode 100644 index 00000000..6a66aea5 --- /dev/null +++ b/vendor/golang.org/x/sync/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2009 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * 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. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +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 +OWNER 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/golang.org/x/sync/PATENTS b/vendor/golang.org/x/sync/PATENTS new file mode 100644 index 00000000..73309904 --- /dev/null +++ b/vendor/golang.org/x/sync/PATENTS @@ -0,0 +1,22 @@ +Additional IP Rights Grant (Patents) + +"This implementation" means the copyrightable works distributed by +Google as part of the Go project. + +Google hereby grants to You a perpetual, worldwide, non-exclusive, +no-charge, royalty-free, irrevocable (except as stated in this section) +patent license to make, have made, use, offer to sell, sell, import, +transfer and otherwise run, modify and propagate the contents of this +implementation of Go, where such license applies only to those patent +claims, both currently owned or controlled by Google and acquired in +the future, licensable by Google that are necessarily infringed by this +implementation of Go. This grant does not include claims that would be +infringed only as a consequence of further modification of this +implementation. If you or your agent or exclusive licensee institute or +order or agree to the institution of patent litigation against any +entity (including a cross-claim or counterclaim in a lawsuit) alleging +that this implementation of Go or any code incorporated within this +implementation of Go constitutes direct or contributory patent +infringement, or inducement of patent infringement, then any patent +rights granted to you under this License for this implementation of Go +shall terminate as of the date such litigation is filed. diff --git a/vendor/golang.org/x/sync/README.md b/vendor/golang.org/x/sync/README.md new file mode 100644 index 00000000..1f8436cc --- /dev/null +++ b/vendor/golang.org/x/sync/README.md @@ -0,0 +1,18 @@ +# Go Sync + +This repository provides Go concurrency primitives in addition to the +ones provided by the language and "sync" and "sync/atomic" packages. + +## Download/Install + +The easiest way to install is to run `go get -u golang.org/x/sync`. You can +also manually git clone the repository to `$GOPATH/src/golang.org/x/sync`. + +## Report Issues / Send Patches + +This repository uses Gerrit for code changes. To learn how to submit changes to +this repository, see https://golang.org/doc/contribute.html. + +The main issue tracker for the sync repository is located at +https://github.com/golang/go/issues. Prefix your issue with "x/sync:" in the +subject line, so it is easy to find. diff --git a/vendor/golang.org/x/sync/codereview.cfg b/vendor/golang.org/x/sync/codereview.cfg new file mode 100644 index 00000000..3f8b14b6 --- /dev/null +++ b/vendor/golang.org/x/sync/codereview.cfg @@ -0,0 +1 @@ +issuerepo: golang/go diff --git a/vendor/golang.org/x/sync/errgroup/errgroup.go b/vendor/golang.org/x/sync/errgroup/errgroup.go new file mode 100644 index 00000000..533438d9 --- /dev/null +++ b/vendor/golang.org/x/sync/errgroup/errgroup.go @@ -0,0 +1,67 @@ +// Copyright 2016 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 errgroup provides synchronization, error propagation, and Context +// cancelation for groups of goroutines working on subtasks of a common task. +package errgroup + +import ( + "sync" + + "golang.org/x/net/context" +) + +// A Group is a collection of goroutines working on subtasks that are part of +// the same overall task. +// +// A zero Group is valid and does not cancel on error. +type Group struct { + cancel func() + + wg sync.WaitGroup + + errOnce sync.Once + err error +} + +// WithContext returns a new Group and an associated Context derived from ctx. +// +// The derived Context is canceled the first time a function passed to Go +// returns a non-nil error or the first time Wait returns, whichever occurs +// first. +func WithContext(ctx context.Context) (*Group, context.Context) { + ctx, cancel := context.WithCancel(ctx) + return &Group{cancel: cancel}, ctx +} + +// Wait blocks until all function calls from the Go method have returned, then +// returns the first non-nil error (if any) from them. +func (g *Group) Wait() error { + g.wg.Wait() + if g.cancel != nil { + g.cancel() + } + return g.err +} + +// Go calls the given function in a new goroutine. +// +// The first call to return a non-nil error cancels the group; its error will be +// returned by Wait. +func (g *Group) Go(f func() error) { + g.wg.Add(1) + + go func() { + defer g.wg.Done() + + if err := f(); err != nil { + g.errOnce.Do(func() { + g.err = err + if g.cancel != nil { + g.cancel() + } + }) + } + }() +} diff --git a/vendor/golang.org/x/sync/errgroup/errgroup_example_md5all_test.go b/vendor/golang.org/x/sync/errgroup/errgroup_example_md5all_test.go new file mode 100644 index 00000000..714b5aea --- /dev/null +++ b/vendor/golang.org/x/sync/errgroup/errgroup_example_md5all_test.go @@ -0,0 +1,101 @@ +// Copyright 2016 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 errgroup_test + +import ( + "crypto/md5" + "fmt" + "io/ioutil" + "log" + "os" + "path/filepath" + + "golang.org/x/net/context" + "golang.org/x/sync/errgroup" +) + +// Pipeline demonstrates the use of a Group to implement a multi-stage +// pipeline: a version of the MD5All function with bounded parallelism from +// https://blog.golang.org/pipelines. +func ExampleGroup_pipeline() { + m, err := MD5All(context.Background(), ".") + if err != nil { + log.Fatal(err) + } + + for k, sum := range m { + fmt.Printf("%s:\t%x\n", k, sum) + } +} + +type result struct { + path string + sum [md5.Size]byte +} + +// MD5All reads all the files in the file tree rooted at root and returns a map +// from file path to the MD5 sum of the file's contents. If the directory walk +// fails or any read operation fails, MD5All returns an error. +func MD5All(ctx context.Context, root string) (map[string][md5.Size]byte, error) { + // ctx is canceled when g.Wait() returns. When this version of MD5All returns + // - even in case of error! - we know that all of the goroutines have finished + // and the memory they were using can be garbage-collected. + g, ctx := errgroup.WithContext(ctx) + paths := make(chan string) + + g.Go(func() error { + defer close(paths) + return filepath.Walk(root, func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + if !info.Mode().IsRegular() { + return nil + } + select { + case paths <- path: + case <-ctx.Done(): + return ctx.Err() + } + return nil + }) + }) + + // Start a fixed number of goroutines to read and digest files. + c := make(chan result) + const numDigesters = 20 + for i := 0; i < numDigesters; i++ { + g.Go(func() error { + for path := range paths { + data, err := ioutil.ReadFile(path) + if err != nil { + return err + } + select { + case c <- result{path, md5.Sum(data)}: + case <-ctx.Done(): + return ctx.Err() + } + } + return nil + }) + } + go func() { + g.Wait() + close(c) + }() + + m := make(map[string][md5.Size]byte) + for r := range c { + m[r.path] = r.sum + } + // Check whether any of the goroutines failed. Since g is accumulating the + // errors, we don't need to send them (or check for them) in the individual + // results sent on the channel. + if err := g.Wait(); err != nil { + return nil, err + } + return m, nil +} diff --git a/vendor/golang.org/x/sync/errgroup/errgroup_test.go b/vendor/golang.org/x/sync/errgroup/errgroup_test.go new file mode 100644 index 00000000..6a9696ef --- /dev/null +++ b/vendor/golang.org/x/sync/errgroup/errgroup_test.go @@ -0,0 +1,176 @@ +// Copyright 2016 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 errgroup_test + +import ( + "errors" + "fmt" + "net/http" + "os" + "testing" + + "golang.org/x/net/context" + "golang.org/x/sync/errgroup" +) + +var ( + Web = fakeSearch("web") + Image = fakeSearch("image") + Video = fakeSearch("video") +) + +type Result string +type Search func(ctx context.Context, query string) (Result, error) + +func fakeSearch(kind string) Search { + return func(_ context.Context, query string) (Result, error) { + return Result(fmt.Sprintf("%s result for %q", kind, query)), nil + } +} + +// JustErrors illustrates the use of a Group in place of a sync.WaitGroup to +// simplify goroutine counting and error handling. This example is derived from +// the sync.WaitGroup example at https://golang.org/pkg/sync/#example_WaitGroup. +func ExampleGroup_justErrors() { + var g errgroup.Group + var urls = []string{ + "http://www.golang.org/", + "http://www.google.com/", + "http://www.somestupidname.com/", + } + for _, url := range urls { + // Launch a goroutine to fetch the URL. + url := url // https://golang.org/doc/faq#closures_and_goroutines + g.Go(func() error { + // Fetch the URL. + resp, err := http.Get(url) + if err == nil { + resp.Body.Close() + } + return err + }) + } + // Wait for all HTTP fetches to complete. + if err := g.Wait(); err == nil { + fmt.Println("Successfully fetched all URLs.") + } +} + +// Parallel illustrates the use of a Group for synchronizing a simple parallel +// task: the "Google Search 2.0" function from +// https://talks.golang.org/2012/concurrency.slide#46, augmented with a Context +// and error-handling. +func ExampleGroup_parallel() { + Google := func(ctx context.Context, query string) ([]Result, error) { + g, ctx := errgroup.WithContext(ctx) + + searches := []Search{Web, Image, Video} + results := make([]Result, len(searches)) + for i, search := range searches { + i, search := i, search // https://golang.org/doc/faq#closures_and_goroutines + g.Go(func() error { + result, err := search(ctx, query) + if err == nil { + results[i] = result + } + return err + }) + } + if err := g.Wait(); err != nil { + return nil, err + } + return results, nil + } + + results, err := Google(context.Background(), "golang") + if err != nil { + fmt.Fprintln(os.Stderr, err) + return + } + for _, result := range results { + fmt.Println(result) + } + + // Output: + // web result for "golang" + // image result for "golang" + // video result for "golang" +} + +func TestZeroGroup(t *testing.T) { + err1 := errors.New("errgroup_test: 1") + err2 := errors.New("errgroup_test: 2") + + cases := []struct { + errs []error + }{ + {errs: []error{}}, + {errs: []error{nil}}, + {errs: []error{err1}}, + {errs: []error{err1, nil}}, + {errs: []error{err1, nil, err2}}, + } + + for _, tc := range cases { + var g errgroup.Group + + var firstErr error + for i, err := range tc.errs { + err := err + g.Go(func() error { return err }) + + if firstErr == nil && err != nil { + firstErr = err + } + + if gErr := g.Wait(); gErr != firstErr { + t.Errorf("after %T.Go(func() error { return err }) for err in %v\n"+ + "g.Wait() = %v; want %v", + g, tc.errs[:i+1], err, firstErr) + } + } + } +} + +func TestWithContext(t *testing.T) { + errDoom := errors.New("group_test: doomed") + + cases := []struct { + errs []error + want error + }{ + {want: nil}, + {errs: []error{nil}, want: nil}, + {errs: []error{errDoom}, want: errDoom}, + {errs: []error{errDoom, nil}, want: errDoom}, + } + + for _, tc := range cases { + g, ctx := errgroup.WithContext(context.Background()) + + for _, err := range tc.errs { + err := err + g.Go(func() error { return err }) + } + + if err := g.Wait(); err != tc.want { + t.Errorf("after %T.Go(func() error { return err }) for err in %v\n"+ + "g.Wait() = %v; want %v", + g, tc.errs, err, tc.want) + } + + canceled := false + select { + case <-ctx.Done(): + canceled = true + default: + } + if !canceled { + t.Errorf("after %T.Go(func() error { return err }) for err in %v\n"+ + "ctx.Done() was not closed", + g, tc.errs) + } + } +} diff --git a/vendor/golang.org/x/sync/semaphore/semaphore.go b/vendor/golang.org/x/sync/semaphore/semaphore.go new file mode 100644 index 00000000..e9d2d79a --- /dev/null +++ b/vendor/golang.org/x/sync/semaphore/semaphore.go @@ -0,0 +1,131 @@ +// Copyright 2017 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 semaphore provides a weighted semaphore implementation. +package semaphore // import "golang.org/x/sync/semaphore" + +import ( + "container/list" + "sync" + + // Use the old context because packages that depend on this one + // (e.g. cloud.google.com/go/...) must run on Go 1.6. + // TODO(jba): update to "context" when possible. + "golang.org/x/net/context" +) + +type waiter struct { + n int64 + ready chan<- struct{} // Closed when semaphore acquired. +} + +// NewWeighted creates a new weighted semaphore with the given +// maximum combined weight for concurrent access. +func NewWeighted(n int64) *Weighted { + w := &Weighted{size: n} + return w +} + +// Weighted provides a way to bound concurrent access to a resource. +// The callers can request access with a given weight. +type Weighted struct { + size int64 + cur int64 + mu sync.Mutex + waiters list.List +} + +// Acquire acquires the semaphore with a weight of n, blocking only until ctx +// is done. On success, returns nil. On failure, returns ctx.Err() and leaves +// the semaphore unchanged. +// +// If ctx is already done, Acquire may still succeed without blocking. +func (s *Weighted) Acquire(ctx context.Context, n int64) error { + s.mu.Lock() + if s.size-s.cur >= n && s.waiters.Len() == 0 { + s.cur += n + s.mu.Unlock() + return nil + } + + if n > s.size { + // Don't make other Acquire calls block on one that's doomed to fail. + s.mu.Unlock() + <-ctx.Done() + return ctx.Err() + } + + ready := make(chan struct{}) + w := waiter{n: n, ready: ready} + elem := s.waiters.PushBack(w) + s.mu.Unlock() + + select { + case <-ctx.Done(): + err := ctx.Err() + s.mu.Lock() + select { + case <-ready: + // Acquired the semaphore after we were canceled. Rather than trying to + // fix up the queue, just pretend we didn't notice the cancelation. + err = nil + default: + s.waiters.Remove(elem) + } + s.mu.Unlock() + return err + + case <-ready: + return nil + } +} + +// TryAcquire acquires the semaphore with a weight of n without blocking. +// On success, returns true. On failure, returns false and leaves the semaphore unchanged. +func (s *Weighted) TryAcquire(n int64) bool { + s.mu.Lock() + success := s.size-s.cur >= n && s.waiters.Len() == 0 + if success { + s.cur += n + } + s.mu.Unlock() + return success +} + +// Release releases the semaphore with a weight of n. +func (s *Weighted) Release(n int64) { + s.mu.Lock() + s.cur -= n + if s.cur < 0 { + s.mu.Unlock() + panic("semaphore: bad release") + } + for { + next := s.waiters.Front() + if next == nil { + break // No more waiters blocked. + } + + w := next.Value.(waiter) + if s.size-s.cur < w.n { + // Not enough tokens for the next waiter. We could keep going (to try to + // find a waiter with a smaller request), but under load that could cause + // starvation for large requests; instead, we leave all remaining waiters + // blocked. + // + // Consider a semaphore used as a read-write lock, with N tokens, N + // readers, and one writer. Each reader can Acquire(1) to obtain a read + // lock. The writer can Acquire(N) to obtain a write lock, excluding all + // of the readers. If we allow the readers to jump ahead in the queue, + // the writer will starve — there is always one token available for every + // reader. + break + } + + s.cur += w.n + s.waiters.Remove(next) + close(w.ready) + } + s.mu.Unlock() +} diff --git a/vendor/golang.org/x/sync/semaphore/semaphore_bench_test.go b/vendor/golang.org/x/sync/semaphore/semaphore_bench_test.go new file mode 100644 index 00000000..1e3ab75f --- /dev/null +++ b/vendor/golang.org/x/sync/semaphore/semaphore_bench_test.go @@ -0,0 +1,131 @@ +// Copyright 2017 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. + +// +build go1.7 + +package semaphore_test + +import ( + "fmt" + "testing" + + "golang.org/x/net/context" + "golang.org/x/sync/semaphore" +) + +// weighted is an interface matching a subset of *Weighted. It allows +// alternate implementations for testing and benchmarking. +type weighted interface { + Acquire(context.Context, int64) error + TryAcquire(int64) bool + Release(int64) +} + +// semChan implements Weighted using a channel for +// comparing against the condition variable-based implementation. +type semChan chan struct{} + +func newSemChan(n int64) semChan { + return semChan(make(chan struct{}, n)) +} + +func (s semChan) Acquire(_ context.Context, n int64) error { + for i := int64(0); i < n; i++ { + s <- struct{}{} + } + return nil +} + +func (s semChan) TryAcquire(n int64) bool { + if int64(len(s))+n > int64(cap(s)) { + return false + } + + for i := int64(0); i < n; i++ { + s <- struct{}{} + } + return true +} + +func (s semChan) Release(n int64) { + for i := int64(0); i < n; i++ { + <-s + } +} + +// acquireN calls Acquire(size) on sem N times and then calls Release(size) N times. +func acquireN(b *testing.B, sem weighted, size int64, N int) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + for j := 0; j < N; j++ { + sem.Acquire(context.Background(), size) + } + for j := 0; j < N; j++ { + sem.Release(size) + } + } +} + +// tryAcquireN calls TryAcquire(size) on sem N times and then calls Release(size) N times. +func tryAcquireN(b *testing.B, sem weighted, size int64, N int) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + for j := 0; j < N; j++ { + if !sem.TryAcquire(size) { + b.Fatalf("TryAcquire(%v) = false, want true", size) + } + } + for j := 0; j < N; j++ { + sem.Release(size) + } + } +} + +func BenchmarkNewSeq(b *testing.B) { + for _, cap := range []int64{1, 128} { + b.Run(fmt.Sprintf("Weighted-%d", cap), func(b *testing.B) { + for i := 0; i < b.N; i++ { + _ = semaphore.NewWeighted(cap) + } + }) + b.Run(fmt.Sprintf("semChan-%d", cap), func(b *testing.B) { + for i := 0; i < b.N; i++ { + _ = newSemChan(cap) + } + }) + } +} + +func BenchmarkAcquireSeq(b *testing.B) { + for _, c := range []struct { + cap, size int64 + N int + }{ + {1, 1, 1}, + {2, 1, 1}, + {16, 1, 1}, + {128, 1, 1}, + {2, 2, 1}, + {16, 2, 8}, + {128, 2, 64}, + {2, 1, 2}, + {16, 8, 2}, + {128, 64, 2}, + } { + for _, w := range []struct { + name string + w weighted + }{ + {"Weighted", semaphore.NewWeighted(c.cap)}, + {"semChan", newSemChan(c.cap)}, + } { + b.Run(fmt.Sprintf("%s-acquire-%d-%d-%d", w.name, c.cap, c.size, c.N), func(b *testing.B) { + acquireN(b, w.w, c.size, c.N) + }) + b.Run(fmt.Sprintf("%s-tryAcquire-%d-%d-%d", w.name, c.cap, c.size, c.N), func(b *testing.B) { + tryAcquireN(b, w.w, c.size, c.N) + }) + } + } +} diff --git a/vendor/golang.org/x/sync/semaphore/semaphore_example_test.go b/vendor/golang.org/x/sync/semaphore/semaphore_example_test.go new file mode 100644 index 00000000..e75cd79f --- /dev/null +++ b/vendor/golang.org/x/sync/semaphore/semaphore_example_test.go @@ -0,0 +1,84 @@ +// Copyright 2017 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 semaphore_test + +import ( + "context" + "fmt" + "log" + "runtime" + + "golang.org/x/sync/semaphore" +) + +// Example_workerPool demonstrates how to use a semaphore to limit the number of +// goroutines working on parallel tasks. +// +// This use of a semaphore mimics a typical “worker pool” pattern, but without +// the need to explicitly shut down idle workers when the work is done. +func Example_workerPool() { + ctx := context.TODO() + + var ( + maxWorkers = runtime.GOMAXPROCS(0) + sem = semaphore.NewWeighted(int64(maxWorkers)) + out = make([]int, 32) + ) + + // Compute the output using up to maxWorkers goroutines at a time. + for i := range out { + // When maxWorkers goroutines are in flight, Acquire blocks until one of the + // workers finishes. + if err := sem.Acquire(ctx, 1); err != nil { + log.Printf("Failed to acquire semaphore: %v", err) + break + } + + go func(i int) { + defer sem.Release(1) + out[i] = collatzSteps(i + 1) + }(i) + } + + // Acquire all of the tokens to wait for any remaining workers to finish. + // + // If you are already waiting for the workers by some other means (such as an + // errgroup.Group), you can omit this final Acquire call. + if err := sem.Acquire(ctx, int64(maxWorkers)); err != nil { + log.Printf("Failed to acquire semaphore: %v", err) + } + + fmt.Println(out) + + // Output: + // [0 1 7 2 5 8 16 3 19 6 14 9 9 17 17 4 12 20 20 7 7 15 15 10 23 10 111 18 18 18 106 5] +} + +// collatzSteps computes the number of steps to reach 1 under the Collatz +// conjecture. (See https://en.wikipedia.org/wiki/Collatz_conjecture.) +func collatzSteps(n int) (steps int) { + if n <= 0 { + panic("nonpositive input") + } + + for ; n > 1; steps++ { + if steps < 0 { + panic("too many steps") + } + + if n%2 == 0 { + n /= 2 + continue + } + + const maxInt = int(^uint(0) >> 1) + if n > (maxInt-1)/3 { + panic("overflow") + } + n = 3*n + 1 + } + + return steps +} diff --git a/vendor/golang.org/x/sync/semaphore/semaphore_test.go b/vendor/golang.org/x/sync/semaphore/semaphore_test.go new file mode 100644 index 00000000..2541b906 --- /dev/null +++ b/vendor/golang.org/x/sync/semaphore/semaphore_test.go @@ -0,0 +1,171 @@ +// Copyright 2017 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 semaphore_test + +import ( + "math/rand" + "runtime" + "sync" + "testing" + "time" + + "golang.org/x/net/context" + "golang.org/x/sync/errgroup" + "golang.org/x/sync/semaphore" +) + +const maxSleep = 1 * time.Millisecond + +func HammerWeighted(sem *semaphore.Weighted, n int64, loops int) { + for i := 0; i < loops; i++ { + sem.Acquire(context.Background(), n) + time.Sleep(time.Duration(rand.Int63n(int64(maxSleep/time.Nanosecond))) * time.Nanosecond) + sem.Release(n) + } +} + +func TestWeighted(t *testing.T) { + t.Parallel() + + n := runtime.GOMAXPROCS(0) + loops := 10000 / n + sem := semaphore.NewWeighted(int64(n)) + var wg sync.WaitGroup + wg.Add(n) + for i := 0; i < n; i++ { + i := i + go func() { + defer wg.Done() + HammerWeighted(sem, int64(i), loops) + }() + } + wg.Wait() +} + +func TestWeightedPanic(t *testing.T) { + t.Parallel() + + defer func() { + if recover() == nil { + t.Fatal("release of an unacquired weighted semaphore did not panic") + } + }() + w := semaphore.NewWeighted(1) + w.Release(1) +} + +func TestWeightedTryAcquire(t *testing.T) { + t.Parallel() + + ctx := context.Background() + sem := semaphore.NewWeighted(2) + tries := []bool{} + sem.Acquire(ctx, 1) + tries = append(tries, sem.TryAcquire(1)) + tries = append(tries, sem.TryAcquire(1)) + + sem.Release(2) + + tries = append(tries, sem.TryAcquire(1)) + sem.Acquire(ctx, 1) + tries = append(tries, sem.TryAcquire(1)) + + want := []bool{true, false, true, false} + for i := range tries { + if tries[i] != want[i] { + t.Errorf("tries[%d]: got %t, want %t", i, tries[i], want[i]) + } + } +} + +func TestWeightedAcquire(t *testing.T) { + t.Parallel() + + ctx := context.Background() + sem := semaphore.NewWeighted(2) + tryAcquire := func(n int64) bool { + ctx, cancel := context.WithTimeout(ctx, 10*time.Millisecond) + defer cancel() + return sem.Acquire(ctx, n) == nil + } + + tries := []bool{} + sem.Acquire(ctx, 1) + tries = append(tries, tryAcquire(1)) + tries = append(tries, tryAcquire(1)) + + sem.Release(2) + + tries = append(tries, tryAcquire(1)) + sem.Acquire(ctx, 1) + tries = append(tries, tryAcquire(1)) + + want := []bool{true, false, true, false} + for i := range tries { + if tries[i] != want[i] { + t.Errorf("tries[%d]: got %t, want %t", i, tries[i], want[i]) + } + } +} + +func TestWeightedDoesntBlockIfTooBig(t *testing.T) { + t.Parallel() + + const n = 2 + sem := semaphore.NewWeighted(n) + { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + go sem.Acquire(ctx, n+1) + } + + g, ctx := errgroup.WithContext(context.Background()) + for i := n * 3; i > 0; i-- { + g.Go(func() error { + err := sem.Acquire(ctx, 1) + if err == nil { + time.Sleep(1 * time.Millisecond) + sem.Release(1) + } + return err + }) + } + if err := g.Wait(); err != nil { + t.Errorf("semaphore.NewWeighted(%v) failed to AcquireCtx(_, 1) with AcquireCtx(_, %v) pending", n, n+1) + } +} + +// TestLargeAcquireDoesntStarve times out if a large call to Acquire starves. +// Merely returning from the test function indicates success. +func TestLargeAcquireDoesntStarve(t *testing.T) { + t.Parallel() + + ctx := context.Background() + n := int64(runtime.GOMAXPROCS(0)) + sem := semaphore.NewWeighted(n) + running := true + + var wg sync.WaitGroup + wg.Add(int(n)) + for i := n; i > 0; i-- { + sem.Acquire(ctx, 1) + go func() { + defer func() { + sem.Release(1) + wg.Done() + }() + for running { + time.Sleep(1 * time.Millisecond) + sem.Release(1) + sem.Acquire(ctx, 1) + } + }() + } + + sem.Acquire(ctx, n) + running = false + sem.Release(n) + wg.Wait() +} diff --git a/vendor/golang.org/x/sync/singleflight/singleflight.go b/vendor/golang.org/x/sync/singleflight/singleflight.go new file mode 100644 index 00000000..9a4f8d59 --- /dev/null +++ b/vendor/golang.org/x/sync/singleflight/singleflight.go @@ -0,0 +1,111 @@ +// Copyright 2013 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 singleflight provides a duplicate function call suppression +// mechanism. +package singleflight // import "golang.org/x/sync/singleflight" + +import "sync" + +// call is an in-flight or completed singleflight.Do call +type call struct { + wg sync.WaitGroup + + // These fields are written once before the WaitGroup is done + // and are only read after the WaitGroup is done. + val interface{} + err error + + // These fields are read and written with the singleflight + // mutex held before the WaitGroup is done, and are read but + // not written after the WaitGroup is done. + dups int + chans []chan<- Result +} + +// Group represents a class of work and forms a namespace in +// which units of work can be executed with duplicate suppression. +type Group struct { + mu sync.Mutex // protects m + m map[string]*call // lazily initialized +} + +// Result holds the results of Do, so they can be passed +// on a channel. +type Result struct { + Val interface{} + Err error + Shared bool +} + +// Do executes and returns the results of the given function, making +// sure that only one execution is in-flight for a given key at a +// time. If a duplicate comes in, the duplicate caller waits for the +// original to complete and receives the same results. +// The return value shared indicates whether v was given to multiple callers. +func (g *Group) Do(key string, fn func() (interface{}, error)) (v interface{}, err error, shared bool) { + g.mu.Lock() + if g.m == nil { + g.m = make(map[string]*call) + } + if c, ok := g.m[key]; ok { + c.dups++ + g.mu.Unlock() + c.wg.Wait() + return c.val, c.err, true + } + c := new(call) + c.wg.Add(1) + g.m[key] = c + g.mu.Unlock() + + g.doCall(c, key, fn) + return c.val, c.err, c.dups > 0 +} + +// DoChan is like Do but returns a channel that will receive the +// results when they are ready. +func (g *Group) DoChan(key string, fn func() (interface{}, error)) <-chan Result { + ch := make(chan Result, 1) + g.mu.Lock() + if g.m == nil { + g.m = make(map[string]*call) + } + if c, ok := g.m[key]; ok { + c.dups++ + c.chans = append(c.chans, ch) + g.mu.Unlock() + return ch + } + c := &call{chans: []chan<- Result{ch}} + c.wg.Add(1) + g.m[key] = c + g.mu.Unlock() + + go g.doCall(c, key, fn) + + return ch +} + +// doCall handles the single call for a key. +func (g *Group) doCall(c *call, key string, fn func() (interface{}, error)) { + c.val, c.err = fn() + c.wg.Done() + + g.mu.Lock() + delete(g.m, key) + for _, ch := range c.chans { + ch <- Result{c.val, c.err, c.dups > 0} + } + g.mu.Unlock() +} + +// Forget tells the singleflight to forget about a key. Future calls +// to Do for this key will call the function rather than waiting for +// an earlier call to complete. +func (g *Group) Forget(key string) { + g.mu.Lock() + delete(g.m, key) + g.mu.Unlock() +} diff --git a/vendor/golang.org/x/sync/singleflight/singleflight_test.go b/vendor/golang.org/x/sync/singleflight/singleflight_test.go new file mode 100644 index 00000000..5e6f1b32 --- /dev/null +++ b/vendor/golang.org/x/sync/singleflight/singleflight_test.go @@ -0,0 +1,87 @@ +// Copyright 2013 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 singleflight + +import ( + "errors" + "fmt" + "sync" + "sync/atomic" + "testing" + "time" +) + +func TestDo(t *testing.T) { + var g Group + v, err, _ := g.Do("key", func() (interface{}, error) { + return "bar", nil + }) + if got, want := fmt.Sprintf("%v (%T)", v, v), "bar (string)"; got != want { + t.Errorf("Do = %v; want %v", got, want) + } + if err != nil { + t.Errorf("Do error = %v", err) + } +} + +func TestDoErr(t *testing.T) { + var g Group + someErr := errors.New("Some error") + v, err, _ := g.Do("key", func() (interface{}, error) { + return nil, someErr + }) + if err != someErr { + t.Errorf("Do error = %v; want someErr %v", err, someErr) + } + if v != nil { + t.Errorf("unexpected non-nil value %#v", v) + } +} + +func TestDoDupSuppress(t *testing.T) { + var g Group + var wg1, wg2 sync.WaitGroup + c := make(chan string, 1) + var calls int32 + fn := func() (interface{}, error) { + if atomic.AddInt32(&calls, 1) == 1 { + // First invocation. + wg1.Done() + } + v := <-c + c <- v // pump; make available for any future calls + + time.Sleep(10 * time.Millisecond) // let more goroutines enter Do + + return v, nil + } + + const n = 10 + wg1.Add(1) + for i := 0; i < n; i++ { + wg1.Add(1) + wg2.Add(1) + go func() { + defer wg2.Done() + wg1.Done() + v, err, _ := g.Do("key", fn) + if err != nil { + t.Errorf("Do error: %v", err) + return + } + if s, _ := v.(string); s != "bar" { + t.Errorf("Do = %T %v; want %q", v, v, "bar") + } + }() + } + wg1.Wait() + // At least one goroutine is in fn now and all of them have at + // least reached the line before the Do. + c <- "bar" + wg2.Wait() + if got := atomic.LoadInt32(&calls); got <= 0 || got >= n { + t.Errorf("number of calls = %d; want over 0 and less than %d", got, n) + } +} diff --git a/vendor/golang.org/x/sync/syncmap/map.go b/vendor/golang.org/x/sync/syncmap/map.go new file mode 100644 index 00000000..80e15847 --- /dev/null +++ b/vendor/golang.org/x/sync/syncmap/map.go @@ -0,0 +1,372 @@ +// Copyright 2016 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 syncmap provides a concurrent map implementation. +// It is a prototype for a proposed addition to the sync package +// in the standard library. +// (https://golang.org/issue/18177) +package syncmap + +import ( + "sync" + "sync/atomic" + "unsafe" +) + +// Map is a concurrent map with amortized-constant-time loads, stores, and deletes. +// It is safe for multiple goroutines to call a Map's methods concurrently. +// +// The zero Map is valid and empty. +// +// A Map must not be copied after first use. +type Map struct { + mu sync.Mutex + + // read contains the portion of the map's contents that are safe for + // concurrent access (with or without mu held). + // + // The read field itself is always safe to load, but must only be stored with + // mu held. + // + // Entries stored in read may be updated concurrently without mu, but updating + // a previously-expunged entry requires that the entry be copied to the dirty + // map and unexpunged with mu held. + read atomic.Value // readOnly + + // dirty contains the portion of the map's contents that require mu to be + // held. To ensure that the dirty map can be promoted to the read map quickly, + // it also includes all of the non-expunged entries in the read map. + // + // Expunged entries are not stored in the dirty map. An expunged entry in the + // clean map must be unexpunged and added to the dirty map before a new value + // can be stored to it. + // + // If the dirty map is nil, the next write to the map will initialize it by + // making a shallow copy of the clean map, omitting stale entries. + dirty map[interface{}]*entry + + // misses counts the number of loads since the read map was last updated that + // needed to lock mu to determine whether the key was present. + // + // Once enough misses have occurred to cover the cost of copying the dirty + // map, the dirty map will be promoted to the read map (in the unamended + // state) and the next store to the map will make a new dirty copy. + misses int +} + +// readOnly is an immutable struct stored atomically in the Map.read field. +type readOnly struct { + m map[interface{}]*entry + amended bool // true if the dirty map contains some key not in m. +} + +// expunged is an arbitrary pointer that marks entries which have been deleted +// from the dirty map. +var expunged = unsafe.Pointer(new(interface{})) + +// An entry is a slot in the map corresponding to a particular key. +type entry struct { + // p points to the interface{} value stored for the entry. + // + // If p == nil, the entry has been deleted and m.dirty == nil. + // + // If p == expunged, the entry has been deleted, m.dirty != nil, and the entry + // is missing from m.dirty. + // + // Otherwise, the entry is valid and recorded in m.read.m[key] and, if m.dirty + // != nil, in m.dirty[key]. + // + // An entry can be deleted by atomic replacement with nil: when m.dirty is + // next created, it will atomically replace nil with expunged and leave + // m.dirty[key] unset. + // + // An entry's associated value can be updated by atomic replacement, provided + // p != expunged. If p == expunged, an entry's associated value can be updated + // only after first setting m.dirty[key] = e so that lookups using the dirty + // map find the entry. + p unsafe.Pointer // *interface{} +} + +func newEntry(i interface{}) *entry { + return &entry{p: unsafe.Pointer(&i)} +} + +// Load returns the value stored in the map for a key, or nil if no +// value is present. +// The ok result indicates whether value was found in the map. +func (m *Map) Load(key interface{}) (value interface{}, ok bool) { + read, _ := m.read.Load().(readOnly) + e, ok := read.m[key] + if !ok && read.amended { + m.mu.Lock() + // Avoid reporting a spurious miss if m.dirty got promoted while we were + // blocked on m.mu. (If further loads of the same key will not miss, it's + // not worth copying the dirty map for this key.) + read, _ = m.read.Load().(readOnly) + e, ok = read.m[key] + if !ok && read.amended { + e, ok = m.dirty[key] + // Regardless of whether the entry was present, record a miss: this key + // will take the slow path until the dirty map is promoted to the read + // map. + m.missLocked() + } + m.mu.Unlock() + } + if !ok { + return nil, false + } + return e.load() +} + +func (e *entry) load() (value interface{}, ok bool) { + p := atomic.LoadPointer(&e.p) + if p == nil || p == expunged { + return nil, false + } + return *(*interface{})(p), true +} + +// Store sets the value for a key. +func (m *Map) Store(key, value interface{}) { + read, _ := m.read.Load().(readOnly) + if e, ok := read.m[key]; ok && e.tryStore(&value) { + return + } + + m.mu.Lock() + read, _ = m.read.Load().(readOnly) + if e, ok := read.m[key]; ok { + if e.unexpungeLocked() { + // The entry was previously expunged, which implies that there is a + // non-nil dirty map and this entry is not in it. + m.dirty[key] = e + } + e.storeLocked(&value) + } else if e, ok := m.dirty[key]; ok { + e.storeLocked(&value) + } else { + if !read.amended { + // We're adding the first new key to the dirty map. + // Make sure it is allocated and mark the read-only map as incomplete. + m.dirtyLocked() + m.read.Store(readOnly{m: read.m, amended: true}) + } + m.dirty[key] = newEntry(value) + } + m.mu.Unlock() +} + +// tryStore stores a value if the entry has not been expunged. +// +// If the entry is expunged, tryStore returns false and leaves the entry +// unchanged. +func (e *entry) tryStore(i *interface{}) bool { + p := atomic.LoadPointer(&e.p) + if p == expunged { + return false + } + for { + if atomic.CompareAndSwapPointer(&e.p, p, unsafe.Pointer(i)) { + return true + } + p = atomic.LoadPointer(&e.p) + if p == expunged { + return false + } + } +} + +// unexpungeLocked ensures that the entry is not marked as expunged. +// +// If the entry was previously expunged, it must be added to the dirty map +// before m.mu is unlocked. +func (e *entry) unexpungeLocked() (wasExpunged bool) { + return atomic.CompareAndSwapPointer(&e.p, expunged, nil) +} + +// storeLocked unconditionally stores a value to the entry. +// +// The entry must be known not to be expunged. +func (e *entry) storeLocked(i *interface{}) { + atomic.StorePointer(&e.p, unsafe.Pointer(i)) +} + +// LoadOrStore returns the existing value for the key if present. +// Otherwise, it stores and returns the given value. +// The loaded result is true if the value was loaded, false if stored. +func (m *Map) LoadOrStore(key, value interface{}) (actual interface{}, loaded bool) { + // Avoid locking if it's a clean hit. + read, _ := m.read.Load().(readOnly) + if e, ok := read.m[key]; ok { + actual, loaded, ok := e.tryLoadOrStore(value) + if ok { + return actual, loaded + } + } + + m.mu.Lock() + read, _ = m.read.Load().(readOnly) + if e, ok := read.m[key]; ok { + if e.unexpungeLocked() { + m.dirty[key] = e + } + actual, loaded, _ = e.tryLoadOrStore(value) + } else if e, ok := m.dirty[key]; ok { + actual, loaded, _ = e.tryLoadOrStore(value) + m.missLocked() + } else { + if !read.amended { + // We're adding the first new key to the dirty map. + // Make sure it is allocated and mark the read-only map as incomplete. + m.dirtyLocked() + m.read.Store(readOnly{m: read.m, amended: true}) + } + m.dirty[key] = newEntry(value) + actual, loaded = value, false + } + m.mu.Unlock() + + return actual, loaded +} + +// tryLoadOrStore atomically loads or stores a value if the entry is not +// expunged. +// +// If the entry is expunged, tryLoadOrStore leaves the entry unchanged and +// returns with ok==false. +func (e *entry) tryLoadOrStore(i interface{}) (actual interface{}, loaded, ok bool) { + p := atomic.LoadPointer(&e.p) + if p == expunged { + return nil, false, false + } + if p != nil { + return *(*interface{})(p), true, true + } + + // Copy the interface after the first load to make this method more amenable + // to escape analysis: if we hit the "load" path or the entry is expunged, we + // shouldn't bother heap-allocating. + ic := i + for { + if atomic.CompareAndSwapPointer(&e.p, nil, unsafe.Pointer(&ic)) { + return i, false, true + } + p = atomic.LoadPointer(&e.p) + if p == expunged { + return nil, false, false + } + if p != nil { + return *(*interface{})(p), true, true + } + } +} + +// Delete deletes the value for a key. +func (m *Map) Delete(key interface{}) { + read, _ := m.read.Load().(readOnly) + e, ok := read.m[key] + if !ok && read.amended { + m.mu.Lock() + read, _ = m.read.Load().(readOnly) + e, ok = read.m[key] + if !ok && read.amended { + delete(m.dirty, key) + } + m.mu.Unlock() + } + if ok { + e.delete() + } +} + +func (e *entry) delete() (hadValue bool) { + for { + p := atomic.LoadPointer(&e.p) + if p == nil || p == expunged { + return false + } + if atomic.CompareAndSwapPointer(&e.p, p, nil) { + return true + } + } +} + +// Range calls f sequentially for each key and value present in the map. +// If f returns false, range stops the iteration. +// +// Range does not necessarily correspond to any consistent snapshot of the Map's +// contents: no key will be visited more than once, but if the value for any key +// is stored or deleted concurrently, Range may reflect any mapping for that key +// from any point during the Range call. +// +// Range may be O(N) with the number of elements in the map even if f returns +// false after a constant number of calls. +func (m *Map) Range(f func(key, value interface{}) bool) { + // We need to be able to iterate over all of the keys that were already + // present at the start of the call to Range. + // If read.amended is false, then read.m satisfies that property without + // requiring us to hold m.mu for a long time. + read, _ := m.read.Load().(readOnly) + if read.amended { + // m.dirty contains keys not in read.m. Fortunately, Range is already O(N) + // (assuming the caller does not break out early), so a call to Range + // amortizes an entire copy of the map: we can promote the dirty copy + // immediately! + m.mu.Lock() + read, _ = m.read.Load().(readOnly) + if read.amended { + read = readOnly{m: m.dirty} + m.read.Store(read) + m.dirty = nil + m.misses = 0 + } + m.mu.Unlock() + } + + for k, e := range read.m { + v, ok := e.load() + if !ok { + continue + } + if !f(k, v) { + break + } + } +} + +func (m *Map) missLocked() { + m.misses++ + if m.misses < len(m.dirty) { + return + } + m.read.Store(readOnly{m: m.dirty}) + m.dirty = nil + m.misses = 0 +} + +func (m *Map) dirtyLocked() { + if m.dirty != nil { + return + } + + read, _ := m.read.Load().(readOnly) + m.dirty = make(map[interface{}]*entry, len(read.m)) + for k, e := range read.m { + if !e.tryExpungeLocked() { + m.dirty[k] = e + } + } +} + +func (e *entry) tryExpungeLocked() (isExpunged bool) { + p := atomic.LoadPointer(&e.p) + for p == nil { + if atomic.CompareAndSwapPointer(&e.p, nil, expunged) { + return true + } + p = atomic.LoadPointer(&e.p) + } + return p == expunged +} diff --git a/vendor/golang.org/x/sync/syncmap/map_bench_test.go b/vendor/golang.org/x/sync/syncmap/map_bench_test.go new file mode 100644 index 00000000..b279b4f7 --- /dev/null +++ b/vendor/golang.org/x/sync/syncmap/map_bench_test.go @@ -0,0 +1,216 @@ +// Copyright 2016 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 syncmap_test + +import ( + "fmt" + "reflect" + "sync/atomic" + "testing" + + "golang.org/x/sync/syncmap" +) + +type bench struct { + setup func(*testing.B, mapInterface) + perG func(b *testing.B, pb *testing.PB, i int, m mapInterface) +} + +func benchMap(b *testing.B, bench bench) { + for _, m := range [...]mapInterface{&DeepCopyMap{}, &RWMutexMap{}, &syncmap.Map{}} { + b.Run(fmt.Sprintf("%T", m), func(b *testing.B) { + m = reflect.New(reflect.TypeOf(m).Elem()).Interface().(mapInterface) + if bench.setup != nil { + bench.setup(b, m) + } + + b.ResetTimer() + + var i int64 + b.RunParallel(func(pb *testing.PB) { + id := int(atomic.AddInt64(&i, 1) - 1) + bench.perG(b, pb, id*b.N, m) + }) + }) + } +} + +func BenchmarkLoadMostlyHits(b *testing.B) { + const hits, misses = 1023, 1 + + benchMap(b, bench{ + setup: func(_ *testing.B, m mapInterface) { + for i := 0; i < hits; i++ { + m.LoadOrStore(i, i) + } + // Prime the map to get it into a steady state. + for i := 0; i < hits*2; i++ { + m.Load(i % hits) + } + }, + + perG: func(b *testing.B, pb *testing.PB, i int, m mapInterface) { + for ; pb.Next(); i++ { + m.Load(i % (hits + misses)) + } + }, + }) +} + +func BenchmarkLoadMostlyMisses(b *testing.B) { + const hits, misses = 1, 1023 + + benchMap(b, bench{ + setup: func(_ *testing.B, m mapInterface) { + for i := 0; i < hits; i++ { + m.LoadOrStore(i, i) + } + // Prime the map to get it into a steady state. + for i := 0; i < hits*2; i++ { + m.Load(i % hits) + } + }, + + perG: func(b *testing.B, pb *testing.PB, i int, m mapInterface) { + for ; pb.Next(); i++ { + m.Load(i % (hits + misses)) + } + }, + }) +} + +func BenchmarkLoadOrStoreBalanced(b *testing.B) { + const hits, misses = 128, 128 + + benchMap(b, bench{ + setup: func(b *testing.B, m mapInterface) { + if _, ok := m.(*DeepCopyMap); ok { + b.Skip("DeepCopyMap has quadratic running time.") + } + for i := 0; i < hits; i++ { + m.LoadOrStore(i, i) + } + // Prime the map to get it into a steady state. + for i := 0; i < hits*2; i++ { + m.Load(i % hits) + } + }, + + perG: func(b *testing.B, pb *testing.PB, i int, m mapInterface) { + for ; pb.Next(); i++ { + j := i % (hits + misses) + if j < hits { + if _, ok := m.LoadOrStore(j, i); !ok { + b.Fatalf("unexpected miss for %v", j) + } + } else { + if v, loaded := m.LoadOrStore(i, i); loaded { + b.Fatalf("failed to store %v: existing value %v", i, v) + } + } + } + }, + }) +} + +func BenchmarkLoadOrStoreUnique(b *testing.B) { + benchMap(b, bench{ + setup: func(b *testing.B, m mapInterface) { + if _, ok := m.(*DeepCopyMap); ok { + b.Skip("DeepCopyMap has quadratic running time.") + } + }, + + perG: func(b *testing.B, pb *testing.PB, i int, m mapInterface) { + for ; pb.Next(); i++ { + m.LoadOrStore(i, i) + } + }, + }) +} + +func BenchmarkLoadOrStoreCollision(b *testing.B) { + benchMap(b, bench{ + setup: func(_ *testing.B, m mapInterface) { + m.LoadOrStore(0, 0) + }, + + perG: func(b *testing.B, pb *testing.PB, i int, m mapInterface) { + for ; pb.Next(); i++ { + m.LoadOrStore(0, 0) + } + }, + }) +} + +func BenchmarkRange(b *testing.B) { + const mapSize = 1 << 10 + + benchMap(b, bench{ + setup: func(_ *testing.B, m mapInterface) { + for i := 0; i < mapSize; i++ { + m.Store(i, i) + } + }, + + perG: func(b *testing.B, pb *testing.PB, i int, m mapInterface) { + for ; pb.Next(); i++ { + m.Range(func(_, _ interface{}) bool { return true }) + } + }, + }) +} + +// BenchmarkAdversarialAlloc tests performance when we store a new value +// immediately whenever the map is promoted to clean and otherwise load a +// unique, missing key. +// +// This forces the Load calls to always acquire the map's mutex. +func BenchmarkAdversarialAlloc(b *testing.B) { + benchMap(b, bench{ + perG: func(b *testing.B, pb *testing.PB, i int, m mapInterface) { + var stores, loadsSinceStore int64 + for ; pb.Next(); i++ { + m.Load(i) + if loadsSinceStore++; loadsSinceStore > stores { + m.LoadOrStore(i, stores) + loadsSinceStore = 0 + stores++ + } + } + }, + }) +} + +// BenchmarkAdversarialDelete tests performance when we periodically delete +// one key and add a different one in a large map. +// +// This forces the Load calls to always acquire the map's mutex and periodically +// makes a full copy of the map despite changing only one entry. +func BenchmarkAdversarialDelete(b *testing.B) { + const mapSize = 1 << 10 + + benchMap(b, bench{ + setup: func(_ *testing.B, m mapInterface) { + for i := 0; i < mapSize; i++ { + m.Store(i, i) + } + }, + + perG: func(b *testing.B, pb *testing.PB, i int, m mapInterface) { + for ; pb.Next(); i++ { + m.Load(i) + + if i%mapSize == 0 { + m.Range(func(k, _ interface{}) bool { + m.Delete(k) + return false + }) + m.Store(i, i) + } + } + }, + }) +} diff --git a/vendor/golang.org/x/sync/syncmap/map_reference_test.go b/vendor/golang.org/x/sync/syncmap/map_reference_test.go new file mode 100644 index 00000000..923c51b7 --- /dev/null +++ b/vendor/golang.org/x/sync/syncmap/map_reference_test.go @@ -0,0 +1,151 @@ +// Copyright 2016 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 syncmap_test + +import ( + "sync" + "sync/atomic" +) + +// This file contains reference map implementations for unit-tests. + +// mapInterface is the interface Map implements. +type mapInterface interface { + Load(interface{}) (interface{}, bool) + Store(key, value interface{}) + LoadOrStore(key, value interface{}) (actual interface{}, loaded bool) + Delete(interface{}) + Range(func(key, value interface{}) (shouldContinue bool)) +} + +// RWMutexMap is an implementation of mapInterface using a sync.RWMutex. +type RWMutexMap struct { + mu sync.RWMutex + dirty map[interface{}]interface{} +} + +func (m *RWMutexMap) Load(key interface{}) (value interface{}, ok bool) { + m.mu.RLock() + value, ok = m.dirty[key] + m.mu.RUnlock() + return +} + +func (m *RWMutexMap) Store(key, value interface{}) { + m.mu.Lock() + if m.dirty == nil { + m.dirty = make(map[interface{}]interface{}) + } + m.dirty[key] = value + m.mu.Unlock() +} + +func (m *RWMutexMap) LoadOrStore(key, value interface{}) (actual interface{}, loaded bool) { + m.mu.Lock() + actual, loaded = m.dirty[key] + if !loaded { + actual = value + if m.dirty == nil { + m.dirty = make(map[interface{}]interface{}) + } + m.dirty[key] = value + } + m.mu.Unlock() + return actual, loaded +} + +func (m *RWMutexMap) Delete(key interface{}) { + m.mu.Lock() + delete(m.dirty, key) + m.mu.Unlock() +} + +func (m *RWMutexMap) Range(f func(key, value interface{}) (shouldContinue bool)) { + m.mu.RLock() + keys := make([]interface{}, 0, len(m.dirty)) + for k := range m.dirty { + keys = append(keys, k) + } + m.mu.RUnlock() + + for _, k := range keys { + v, ok := m.Load(k) + if !ok { + continue + } + if !f(k, v) { + break + } + } +} + +// DeepCopyMap is an implementation of mapInterface using a Mutex and +// atomic.Value. It makes deep copies of the map on every write to avoid +// acquiring the Mutex in Load. +type DeepCopyMap struct { + mu sync.Mutex + clean atomic.Value +} + +func (m *DeepCopyMap) Load(key interface{}) (value interface{}, ok bool) { + clean, _ := m.clean.Load().(map[interface{}]interface{}) + value, ok = clean[key] + return value, ok +} + +func (m *DeepCopyMap) Store(key, value interface{}) { + m.mu.Lock() + dirty := m.dirty() + dirty[key] = value + m.clean.Store(dirty) + m.mu.Unlock() +} + +func (m *DeepCopyMap) LoadOrStore(key, value interface{}) (actual interface{}, loaded bool) { + clean, _ := m.clean.Load().(map[interface{}]interface{}) + actual, loaded = clean[key] + if loaded { + return actual, loaded + } + + m.mu.Lock() + // Reload clean in case it changed while we were waiting on m.mu. + clean, _ = m.clean.Load().(map[interface{}]interface{}) + actual, loaded = clean[key] + if !loaded { + dirty := m.dirty() + dirty[key] = value + actual = value + m.clean.Store(dirty) + } + m.mu.Unlock() + return actual, loaded +} + +func (m *DeepCopyMap) Delete(key interface{}) { + m.mu.Lock() + dirty := m.dirty() + delete(dirty, key) + m.clean.Store(dirty) + m.mu.Unlock() +} + +func (m *DeepCopyMap) Range(f func(key, value interface{}) (shouldContinue bool)) { + clean, _ := m.clean.Load().(map[interface{}]interface{}) + for k, v := range clean { + if !f(k, v) { + break + } + } +} + +func (m *DeepCopyMap) dirty() map[interface{}]interface{} { + clean, _ := m.clean.Load().(map[interface{}]interface{}) + dirty := make(map[interface{}]interface{}, len(clean)+1) + for k, v := range clean { + dirty[k] = v + } + return dirty +} diff --git a/vendor/golang.org/x/sync/syncmap/map_test.go b/vendor/golang.org/x/sync/syncmap/map_test.go new file mode 100644 index 00000000..c883f176 --- /dev/null +++ b/vendor/golang.org/x/sync/syncmap/map_test.go @@ -0,0 +1,172 @@ +// Copyright 2016 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 syncmap_test + +import ( + "math/rand" + "reflect" + "runtime" + "sync" + "testing" + "testing/quick" + + "golang.org/x/sync/syncmap" +) + +type mapOp string + +const ( + opLoad = mapOp("Load") + opStore = mapOp("Store") + opLoadOrStore = mapOp("LoadOrStore") + opDelete = mapOp("Delete") +) + +var mapOps = [...]mapOp{opLoad, opStore, opLoadOrStore, opDelete} + +// mapCall is a quick.Generator for calls on mapInterface. +type mapCall struct { + op mapOp + k, v interface{} +} + +func (c mapCall) apply(m mapInterface) (interface{}, bool) { + switch c.op { + case opLoad: + return m.Load(c.k) + case opStore: + m.Store(c.k, c.v) + return nil, false + case opLoadOrStore: + return m.LoadOrStore(c.k, c.v) + case opDelete: + m.Delete(c.k) + return nil, false + default: + panic("invalid mapOp") + } +} + +type mapResult struct { + value interface{} + ok bool +} + +func randValue(r *rand.Rand) interface{} { + b := make([]byte, r.Intn(4)) + for i := range b { + b[i] = 'a' + byte(rand.Intn(26)) + } + return string(b) +} + +func (mapCall) Generate(r *rand.Rand, size int) reflect.Value { + c := mapCall{op: mapOps[rand.Intn(len(mapOps))], k: randValue(r)} + switch c.op { + case opStore, opLoadOrStore: + c.v = randValue(r) + } + return reflect.ValueOf(c) +} + +func applyCalls(m mapInterface, calls []mapCall) (results []mapResult, final map[interface{}]interface{}) { + for _, c := range calls { + v, ok := c.apply(m) + results = append(results, mapResult{v, ok}) + } + + final = make(map[interface{}]interface{}) + m.Range(func(k, v interface{}) bool { + final[k] = v + return true + }) + + return results, final +} + +func applyMap(calls []mapCall) ([]mapResult, map[interface{}]interface{}) { + return applyCalls(new(syncmap.Map), calls) +} + +func applyRWMutexMap(calls []mapCall) ([]mapResult, map[interface{}]interface{}) { + return applyCalls(new(RWMutexMap), calls) +} + +func applyDeepCopyMap(calls []mapCall) ([]mapResult, map[interface{}]interface{}) { + return applyCalls(new(DeepCopyMap), calls) +} + +func TestMapMatchesRWMutex(t *testing.T) { + if err := quick.CheckEqual(applyMap, applyRWMutexMap, nil); err != nil { + t.Error(err) + } +} + +func TestMapMatchesDeepCopy(t *testing.T) { + if err := quick.CheckEqual(applyMap, applyDeepCopyMap, nil); err != nil { + t.Error(err) + } +} + +func TestConcurrentRange(t *testing.T) { + const mapSize = 1 << 10 + + m := new(syncmap.Map) + for n := int64(1); n <= mapSize; n++ { + m.Store(n, int64(n)) + } + + done := make(chan struct{}) + var wg sync.WaitGroup + defer func() { + close(done) + wg.Wait() + }() + for g := int64(runtime.GOMAXPROCS(0)); g > 0; g-- { + r := rand.New(rand.NewSource(g)) + wg.Add(1) + go func(g int64) { + defer wg.Done() + for i := int64(0); ; i++ { + select { + case <-done: + return + default: + } + for n := int64(1); n < mapSize; n++ { + if r.Int63n(mapSize) == 0 { + m.Store(n, n*i*g) + } else { + m.Load(n) + } + } + } + }(g) + } + + iters := 1 << 10 + if testing.Short() { + iters = 16 + } + for n := iters; n > 0; n-- { + seen := make(map[int64]bool, mapSize) + + m.Range(func(ki, vi interface{}) bool { + k, v := ki.(int64), vi.(int64) + if v%k != 0 { + t.Fatalf("while Storing multiples of %v, Range saw value %v", k, v) + } + if seen[k] { + t.Fatalf("Range visited key %v twice", k) + } + seen[k] = true + return true + }) + + if len(seen) != mapSize { + t.Fatalf("Range visited %v elements of %v-element Map", len(seen), mapSize) + } + } +} From 7c59b35d5a98c28a114b69d0c7b942a57840147d Mon Sep 17 00:00:00 2001 From: tyru Date: Sun, 28 Jan 2018 01:57:32 +0900 Subject: [PATCH 02/11] Bump version: v0.3.1 -> v0.3.2-beta --- cmd/version.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/version.go b/cmd/version.go index 01d6a959..02b44aca 100644 --- a/cmd/version.go +++ b/cmd/version.go @@ -9,7 +9,7 @@ import ( "strconv" ) -var voltVersion string = "v0.3.1" +var voltVersion string = "v0.3.2-beta" func init() { cmdMap["version"] = &versionCmd{} From 433e14568ae1ffe2fb462bc3509ddde970ce4d18 Mon Sep 17 00:00:00 2001 From: tyru Date: Sun, 18 Feb 2018 00:29:42 +0900 Subject: [PATCH 03/11] Fix segfault (fix #189) --- cmd/get.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/get.go b/cmd/get.go index fe117c0f..e4fdc56b 100644 --- a/cmd/get.go +++ b/cmd/get.go @@ -376,7 +376,7 @@ func (cmd *getCmd) installPlugin(reposPath pathutil.ReposPath, repos *lockjson.R } done <- getParallelResult{ reposPath: reposPath, - status: fmt.Sprintf(fmtUpgradeFailed, reposPath, err.Error()), + status: fmt.Sprintf(fmtUpgradeFailed, reposPath, result.Error()), err: result, } return From 7c47cd72c04bb4f433073776eced9e13abb2c802 Mon Sep 17 00:00:00 2001 From: tyru Date: Sun, 18 Feb 2018 00:53:41 +0900 Subject: [PATCH 04/11] cmd/get: Show message when worktree is not updated (fix #191) Show message when worktree is not updated but Worktree.Pull() returned nil. e.g.: upstream remote URL is changed but the repository is identical. Before: https://github.com/tyru/dummy After: git@github.com:tyru/dummy.git --- cmd/get.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/cmd/get.go b/cmd/get.go index e4fdc56b..a483081f 100644 --- a/cmd/get.go +++ b/cmd/get.go @@ -304,6 +304,7 @@ const ( // Upgraded fmtRevUpdate = "* %s > updated lock.json revision (%s..%s)" fmtUpgraded = "* %s > upgraded (%s..%s)" + fmtFetched = "* %s > fetched objects (worktree is not updated)" ) // This function is executed in goroutine of each plugin. @@ -431,9 +432,12 @@ func (cmd *getCmd) installPlugin(reposPath pathutil.ReposPath, repos *lockjson.R } } - // Show old and new revisions: "upgraded ({from}..{to})". if upgraded { - status = fmt.Sprintf(fmtUpgraded, reposPath, fromHash, toHash) + if fromHash != toHash { + status = fmt.Sprintf(fmtUpgraded, reposPath, fromHash, toHash) + } else { + status = fmt.Sprintf(fmtFetched, reposPath) + } } if checkRevision && repos != nil && repos.Version != toHash { From d76a11316007445217fe85d57587d56a299b58c0 Mon Sep 17 00:00:00 2001 From: tyru Date: Sun, 18 Feb 2018 01:55:27 +0900 Subject: [PATCH 05/11] refactor: Rename method name --- cmd/get.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/get.go b/cmd/get.go index a483081f..bc21d9be 100644 --- a/cmd/get.go +++ b/cmd/get.go @@ -390,7 +390,7 @@ func (cmd *getCmd) installPlugin(reposPath pathutil.ReposPath, repos *lockjson.R } else if doInstall { // Install plugin logger.Debug("Installing " + reposPath + " ...") - err := cmd.fetchPlugin(reposPath) + err := cmd.clonePlugin(reposPath) if err != nil { result := errors.New("failed to install plugin: " + err.Error()) logger.Debug("Rollbacking " + fullReposPath + " ...") @@ -527,7 +527,7 @@ func (cmd *getCmd) upgradePlugin(reposPath pathutil.ReposPath) error { var errRepoExists = errors.New("repository exists") -func (cmd *getCmd) fetchPlugin(reposPath pathutil.ReposPath) error { +func (cmd *getCmd) clonePlugin(reposPath pathutil.ReposPath) error { fullpath := pathutil.FullReposPath(reposPath) if pathutil.Exists(fullpath) { return errRepoExists From fa2bf3a7e677476202e39965ecd991716718c87d Mon Sep 17 00:00:00 2001 From: tyru Date: Sun, 18 Feb 2018 01:55:42 +0900 Subject: [PATCH 06/11] fix: "volt get -u" did not fetch/clone from upstream (fix #192) "volt get -u" did git-fetch(bare)/git-clone(non-bare) from only remote "origin". Implemented pulling from upstream remote. --- cmd/get.go | 11 ++++++++--- gitutil/gitutil.go | 35 +++++++++++++++++++++++++++++++---- 2 files changed, 39 insertions(+), 7 deletions(-) diff --git a/cmd/get.go b/cmd/get.go index bc21d9be..747d7a96 100644 --- a/cmd/get.go +++ b/cmd/get.go @@ -509,9 +509,14 @@ func (cmd *getCmd) upgradePlugin(reposPath pathutil.ReposPath) error { return err } + remote, err := gitutil.GetUpstreamRemote(repos) + if err != nil { + return err + } + if cfg.Core.IsBare { return repos.Fetch(&git.FetchOptions{ - RemoteName: "origin", + RemoteName: remote, }) } else { wt, err := repos.Worktree() @@ -519,7 +524,7 @@ func (cmd *getCmd) upgradePlugin(reposPath pathutil.ReposPath) error { return err } return wt.Pull(&git.PullOptions{ - RemoteName: "origin", + RemoteName: remote, RecurseSubmodules: 10, }) } @@ -548,7 +553,7 @@ func (cmd *getCmd) clonePlugin(reposPath pathutil.ReposPath) error { return err } - return gitutil.SetUpstreamBranch(r) + return gitutil.SetUpstreamRemote(r, "origin") } func (cmd *getCmd) fetchPlugconf(reposPath pathutil.ReposPath) error { diff --git a/gitutil/gitutil.go b/gitutil/gitutil.go index 41c074b8..9e7d3853 100644 --- a/gitutil/gitutil.go +++ b/gitutil/gitutil.go @@ -2,6 +2,7 @@ package gitutil import ( "errors" + "fmt" "regexp" "github.com/vim-volt/volt/pathutil" @@ -56,7 +57,8 @@ func GetHEAD(reposPath pathutil.ReposPath) (string, error) { return ref.Hash().String(), nil } -func SetUpstreamBranch(r *git.Repository) error { +// SetUpstreamRemote sets current branch's upstream remote name to remote. +func SetUpstreamRemote(r *git.Repository, remote string) error { cfg, err := r.Config() if err != nil { return err @@ -73,10 +75,35 @@ func SetUpstreamBranch(r *git.Repository) error { return errors.New("HEAD is not matched to refs/heads/...: " + refBranch) } - sec := cfg.Raw.Section("branch") - subsec := sec.Subsection(branch[1]) - subsec.AddOption("remote", "origin") + subsec := cfg.Raw.Section("branch").Subsection(branch[1]) + subsec.AddOption("remote", remote) subsec.AddOption("merge", refBranch) return r.Storer.SetConfig(cfg) } + +// GetUpstreamRemote gets current branch's upstream remote name (e.g. "origin"). +func GetUpstreamRemote(r *git.Repository) (string, error) { + cfg, err := r.Config() + if err != nil { + return "", err + } + + head, err := r.Head() + if err != nil { + return "", err + } + + refBranch := head.Name().String() + branch := refHeadsRx.FindStringSubmatch(refBranch) + if len(branch) == 0 { + return "", errors.New("HEAD is not matched to refs/heads/...: " + refBranch) + } + + subsec := cfg.Raw.Section("branch").Subsection(branch[1]) + remote := subsec.Option("remote") + if remote == "" { + return "", fmt.Errorf("gitconfig 'branch.%s.remote' is not found", subsec.Name) + } + return remote, nil +} From dc073c95e4c7f9d79d002fd17e8c4a9db1d70243 Mon Sep 17 00:00:00 2001 From: tyru Date: Sun, 18 Feb 2018 03:07:36 +0900 Subject: [PATCH 07/11] cmd/get: More concise error output getParallelResult's "status" and "err" have duplicate information. It is hard to see what's real cause if these information are output twice. --- cmd/get.go | 19 +++++++++---------- cmd/get_test.go | 2 +- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/cmd/get.go b/cmd/get.go index 747d7a96..87bd46da 100644 --- a/cmd/get.go +++ b/cmd/get.go @@ -293,8 +293,8 @@ type getParallelResult struct { const ( statusPrefixFailed = "!" // Failed - fmtInstallFailed = "! %s > install failed > %s" - fmtUpgradeFailed = "! %s > upgrade failed > %s" + fmtInstallFailed = "! %s > install failed" + fmtUpgradeFailed = "! %s > upgrade failed" // No change fmtNoChange = "# %s > no change" fmtAlreadyExists = "# %s > already exists" @@ -343,7 +343,7 @@ func (cmd *getCmd) installPlugin(reposPath pathutil.ReposPath, repos *lockjson.R } done <- getParallelResult{ reposPath: reposPath, - status: fmt.Sprintf(fmtInstallFailed, reposPath, result.Error()), + status: fmt.Sprintf(fmtInstallFailed, reposPath), err: result, } return @@ -357,11 +357,10 @@ func (cmd *getCmd) installPlugin(reposPath pathutil.ReposPath, repos *lockjson.R if doUpgrade { // when cmd.upgrade is true, repos must not be nil. if repos == nil { - msg := "-u was specified but repos == nil" done <- getParallelResult{ reposPath: reposPath, - status: fmt.Sprintf(fmtUpgradeFailed, reposPath, msg), - err: errors.New("failed to upgrade plugin: " + msg), + status: fmt.Sprintf(fmtUpgradeFailed, reposPath), + err: errors.New("failed to upgrade plugin: -u was specified but repos == nil"), } return } @@ -377,7 +376,7 @@ func (cmd *getCmd) installPlugin(reposPath pathutil.ReposPath, repos *lockjson.R } done <- getParallelResult{ reposPath: reposPath, - status: fmt.Sprintf(fmtUpgradeFailed, reposPath, result.Error()), + status: fmt.Sprintf(fmtUpgradeFailed, reposPath), err: result, } return @@ -400,7 +399,7 @@ func (cmd *getCmd) installPlugin(reposPath pathutil.ReposPath, repos *lockjson.R } done <- getParallelResult{ reposPath: reposPath, - status: fmt.Sprintf(fmtInstallFailed, reposPath, result.Error()), + status: fmt.Sprintf(fmtInstallFailed, reposPath), err: result, } return @@ -425,7 +424,7 @@ func (cmd *getCmd) installPlugin(reposPath pathutil.ReposPath, repos *lockjson.R } done <- getParallelResult{ reposPath: reposPath, - status: fmt.Sprintf(fmtInstallFailed, reposPath, result.Error()), + status: fmt.Sprintf(fmtInstallFailed, reposPath), err: result, } return @@ -466,7 +465,7 @@ func (cmd *getCmd) installPlugconf(reposPath pathutil.ReposPath, pluginResult *g } done <- getParallelResult{ reposPath: reposPath, - status: fmt.Sprintf(fmtInstallFailed, reposPath, result.Error()), + status: fmt.Sprintf(fmtInstallFailed, reposPath), err: result, } return diff --git a/cmd/get_test.go b/cmd/get_test.go index 4cf16a79..6cf4d4f4 100644 --- a/cmd/get_test.go +++ b/cmd/get_test.go @@ -459,7 +459,7 @@ func TestErrVoltGetNotFound(t *testing.T) { } // (H) - msg := fmt.Sprintf(fmtInstallFailed, reposPath, "") + msg := fmt.Sprintf(fmtInstallFailed, reposPath) if !bytes.Contains(out, []byte(msg)) { t.Errorf("Output does not contain %q\n%s", msg, string(out)) } From 6dd54c088384075dc264ee74ba23f56c2cfb3d35 Mon Sep 17 00:00:00 2001 From: tyru Date: Sun, 18 Feb 2018 03:55:48 +0900 Subject: [PATCH 08/11] refactor: Add gitutil.GetHEADRepository() --- cmd/builder/copy.go | 14 +++++++------- cmd/builder/symlink.go | 20 +++++++++++--------- gitutil/gitutil.go | 3 +++ 3 files changed, 21 insertions(+), 16 deletions(-) diff --git a/cmd/builder/copy.go b/cmd/builder/copy.go index 114c879e..52df4f47 100644 --- a/cmd/builder/copy.go +++ b/cmd/builder/copy.go @@ -148,8 +148,14 @@ func (builder *copyBuilder) copyReposList(buildReposMap map[pathutil.ReposPath]* func (builder *copyBuilder) copyReposGit(repos *lockjson.Repos, buildRepos *buildinfo.Repos, vimExePath string, done chan actionReposResult) (int, error) { src := pathutil.FullReposPath(repos.Path) + // Open ~/volt/repos/{repos} + r, err := git.PlainOpen(src) + if err != nil { + return 0, errors.New("failed to open repository: " + err.Error()) + } + // Show warning when HEAD and locked revision are different - head, err := gitutil.GetHEAD(repos.Path) + head, err := gitutil.GetHEADRepository(r) if err != nil { return 0, fmt.Errorf("failed to get HEAD revision of %q: %s", src, err.Error()) } @@ -160,12 +166,6 @@ func (builder *copyBuilder) copyReposGit(repos *lockjson.Repos, buildRepos *buil logger.Warn(" Please run 'volt get -l' to update locked revision.") } - // Open ~/volt/repos/{repos} - r, err := git.PlainOpen(src) - if err != nil { - return 0, errors.New("failed to open repository: " + err.Error()) - } - cfg, err := r.Config() if err != nil { return 0, errors.New("failed to get repository config: " + err.Error()) diff --git a/cmd/builder/symlink.go b/cmd/builder/symlink.go index e252bda9..b3f704c2 100644 --- a/cmd/builder/symlink.go +++ b/cmd/builder/symlink.go @@ -107,8 +107,17 @@ func (builder *symlinkBuilder) installRepos(repos *lockjson.Repos, vimExePath st copied := false if repos.Type == lockjson.ReposGitType { + // Open a repository to determine it is bare repository or not + r, err := git.PlainOpen(src) + if err != nil { + done <- actionReposResult{ + err: fmt.Errorf("repository %q: %s", src, err.Error()), + } + return + } + // Show warning when HEAD and locked revision are different - head, err := gitutil.GetHEAD(repos.Path) + head, err := gitutil.GetHEADRepository(r) if err != nil { done <- actionReposResult{ err: fmt.Errorf("failed to get HEAD revision of %q: %s", src, err.Error()), @@ -122,14 +131,6 @@ func (builder *symlinkBuilder) installRepos(repos *lockjson.Repos, vimExePath st logger.Warn(" Please run 'volt get -l' to update locked revision.") } - // Open a repository to determine it is bare repository or not - r, err := git.PlainOpen(src) - if err != nil { - done <- actionReposResult{ - err: fmt.Errorf("repository %q: %s", src, err.Error()), - } - return - } cfg, err := r.Config() if err != nil { done <- actionReposResult{ @@ -150,6 +151,7 @@ func (builder *symlinkBuilder) installRepos(repos *lockjson.Repos, vimExePath st copied = true } } + if !copied { // Make symlinks under vim dir if err := builder.symlink(src, dst); err != nil { diff --git a/gitutil/gitutil.go b/gitutil/gitutil.go index 9e7d3853..759172c6 100644 --- a/gitutil/gitutil.go +++ b/gitutil/gitutil.go @@ -22,7 +22,10 @@ func GetHEAD(reposPath pathutil.ReposPath) (string, error) { if err != nil { return "", err } + return GetHEADRepository(repos) +} +func GetHEADRepository(repos *git.Repository) (string, error) { head, err := repos.Head() if err != nil { return "", err From 53b706f9a8d5ac0a40d9d79a1570d1ef70ee4c46 Mon Sep 17 00:00:00 2001 From: tyru Date: Sun, 18 Feb 2018 03:56:16 +0900 Subject: [PATCH 09/11] feat: Implement config.get.fallback_git_cmd (fix #193) When the config value is true, "volt get" or "volt get -u" fail and "git" command is installed, it tries to execute "git clone" or "git pull" as a fallback. --- README.md | 5 ++ cmd/get.go | 159 +++++++++++++++++++++++++++++++++++++---------- config/config.go | 5 ++ 3 files changed, 136 insertions(+), 33 deletions(-) diff --git a/README.md b/README.md index 42590456..659620b9 100644 --- a/README.md +++ b/README.md @@ -142,6 +142,11 @@ strategy = "symlink" # * true (default): "volt get" creates skeleton plugconf file at "$VOLTPATH/plugconf/.vim" # * false: It does not creates skeleton plugconf file create_skeleton_plugconf = true + +# * true (default): When "volt get" or "volt get -u" fail and "git" command is +# installed, it tries to execute "git clone" or "git pull" as a fallback +# * false: "volt get" or "volt get -u" won't try to execute fallback commands +fallback_git_cmd = true ``` ## Self upgrade diff --git a/cmd/get.go b/cmd/get.go index 87bd46da..1903039d 100644 --- a/cmd/get.go +++ b/cmd/get.go @@ -6,10 +6,14 @@ import ( "fmt" "io/ioutil" "os" + "os/exec" "path/filepath" + "runtime" "sort" "strings" + "gopkg.in/src-d/go-git.v4" + "github.com/vim-volt/volt/config" "github.com/vim-volt/volt/fileutil" "github.com/vim-volt/volt/gitutil" @@ -20,7 +24,6 @@ import ( "github.com/vim-volt/volt/transaction" multierror "github.com/hashicorp/go-multierror" - "gopkg.in/src-d/go-git.v4" ) func init() { @@ -211,7 +214,7 @@ func (cmd *getCmd) doGet(reposPathList []pathutil.ReposPath, lockJSON *lockjson. repos = nil } if repos == nil || repos.Type == lockjson.ReposGitType { - go cmd.getParallel(reposPath, repos, *cfg.Get.CreateSkeletonPlugconf, done) + go cmd.getParallel(reposPath, repos, cfg, done) getCount++ } } @@ -310,11 +313,11 @@ const ( // This function is executed in goroutine of each plugin. // 1. install plugin if it does not exist // 2. install plugconf if it does not exist and createPlugconf=true -func (cmd *getCmd) getParallel(reposPath pathutil.ReposPath, repos *lockjson.Repos, createPlugconf bool, done chan<- getParallelResult) { +func (cmd *getCmd) getParallel(reposPath pathutil.ReposPath, repos *lockjson.Repos, cfg *config.Config, done chan<- getParallelResult) { pluginDone := make(chan getParallelResult) - go cmd.installPlugin(reposPath, repos, pluginDone) + go cmd.installPlugin(reposPath, repos, cfg, pluginDone) pluginResult := <-pluginDone - if pluginResult.err != nil || !createPlugconf { + if pluginResult.err != nil || !*cfg.Get.CreateSkeletonPlugconf { done <- pluginResult return } @@ -323,7 +326,7 @@ func (cmd *getCmd) getParallel(reposPath pathutil.ReposPath, repos *lockjson.Rep done <- (<-plugconfDone) } -func (cmd *getCmd) installPlugin(reposPath pathutil.ReposPath, repos *lockjson.Repos, done chan<- getParallelResult) { +func (cmd *getCmd) installPlugin(reposPath pathutil.ReposPath, repos *lockjson.Repos, cfg *config.Config, done chan<- getParallelResult) { // true:upgrade, false:install fullReposPath := pathutil.FullReposPath(reposPath) doUpgrade := cmd.upgrade && pathutil.Exists(fullReposPath) @@ -366,7 +369,7 @@ func (cmd *getCmd) installPlugin(reposPath pathutil.ReposPath, repos *lockjson.R } // Upgrade plugin logger.Debug("Upgrading " + reposPath + " ...") - err := cmd.upgradePlugin(reposPath) + err := cmd.upgradePlugin(reposPath, cfg) if err != git.NoErrAlreadyUpToDate && err != nil { result := errors.New("failed to upgrade plugin: " + err.Error()) logger.Debug("Rollbacking " + fullReposPath + " ...") @@ -389,7 +392,7 @@ func (cmd *getCmd) installPlugin(reposPath pathutil.ReposPath, repos *lockjson.R } else if doInstall { // Install plugin logger.Debug("Installing " + reposPath + " ...") - err := cmd.clonePlugin(reposPath) + err := cmd.clonePlugin(reposPath, cfg) if err != nil { result := errors.New("failed to install plugin: " + err.Error()) logger.Debug("Rollbacking " + fullReposPath + " ...") @@ -495,7 +498,7 @@ func (*getCmd) rollbackRepos(fullReposPath string) error { return nil } -func (cmd *getCmd) upgradePlugin(reposPath pathutil.ReposPath) error { +func (cmd *getCmd) upgradePlugin(reposPath pathutil.ReposPath, cfg *config.Config) error { fullpath := pathutil.FullReposPath(reposPath) repos, err := git.PlainOpen(fullpath) @@ -503,7 +506,7 @@ func (cmd *getCmd) upgradePlugin(reposPath pathutil.ReposPath) error { return err } - cfg, err := repos.Config() + reposCfg, err := repos.Config() if err != nil { return err } @@ -513,25 +516,16 @@ func (cmd *getCmd) upgradePlugin(reposPath pathutil.ReposPath) error { return err } - if cfg.Core.IsBare { - return repos.Fetch(&git.FetchOptions{ - RemoteName: remote, - }) + if reposCfg.Core.IsBare { + return cmd.gitFetch(repos, fullpath, remote, cfg) } else { - wt, err := repos.Worktree() - if err != nil { - return err - } - return wt.Pull(&git.PullOptions{ - RemoteName: remote, - RecurseSubmodules: 10, - }) + return cmd.gitPull(repos, fullpath, remote, cfg) } } var errRepoExists = errors.New("repository exists") -func (cmd *getCmd) clonePlugin(reposPath pathutil.ReposPath) error { +func (cmd *getCmd) clonePlugin(reposPath pathutil.ReposPath, cfg *config.Config) error { fullpath := pathutil.FullReposPath(reposPath) if pathutil.Exists(fullpath) { return errRepoExists @@ -543,16 +537,7 @@ func (cmd *getCmd) clonePlugin(reposPath pathutil.ReposPath) error { } // Clone repository to $VOLTPATH/repos/{site}/{user}/{name} - isBare := false - r, err := git.PlainClone(fullpath, isBare, &git.CloneOptions{ - URL: pathutil.CloneURL(reposPath), - RecurseSubmodules: 10, - }) - if err != nil { - return err - } - - return gitutil.SetUpstreamRemote(r, "origin") + return cmd.gitClone(pathutil.CloneURL(reposPath), fullpath, cfg) } func (cmd *getCmd) fetchPlugconf(reposPath pathutil.ReposPath) error { @@ -616,3 +601,111 @@ func (*getCmd) updateReposVersion(lockJSON *lockjson.LockJSON, reposPath pathuti } return added } + +func (cmd *getCmd) gitFetch(r *git.Repository, workDir string, remote string, cfg *config.Config) error { + err := r.Fetch(&git.FetchOptions{ + RemoteName: remote, + }) + if err == nil || err == git.NoErrAlreadyUpToDate { + return err + } + + // When fallback_git_cmd is true and git command is installed, + // try to invoke git-fetch command + if !*cfg.Get.FallbackGitCmd || !cmd.hasGitCmd() { + return err + } + logger.Warnf("failed to fetch, try to execute \"git fetch %s\" instead...: %s", remote, err.Error()) + + before, err := gitutil.GetHEADRepository(r) + fetch := exec.Command("git", "fetch", remote) + fetch.Dir = workDir + err = fetch.Run() + if err != nil { + return err + } + if changed, err := cmd.getWorktreeChanges(r, before); err != nil { + return err + } else if !changed { + return git.NoErrAlreadyUpToDate + } + return nil +} + +func (cmd *getCmd) gitPull(r *git.Repository, workDir string, remote string, cfg *config.Config) error { + wt, err := r.Worktree() + if err != nil { + return err + } + err = wt.Pull(&git.PullOptions{ + RemoteName: remote, + RecurseSubmodules: 10, + }) + if err == nil || err == git.NoErrAlreadyUpToDate { + return err + } + + // When fallback_git_cmd is true and git command is installed, + // try to invoke git-pull command + if !*cfg.Get.FallbackGitCmd || !cmd.hasGitCmd() { + return err + } + logger.Warnf("failed to pull, try to execute \"git pull\" instead...: %s", err.Error()) + + before, err := gitutil.GetHEADRepository(r) + pull := exec.Command("git", "pull") + pull.Dir = workDir + err = pull.Run() + if err != nil { + return err + } + if changed, err := cmd.getWorktreeChanges(r, before); err != nil { + return err + } else if !changed { + return git.NoErrAlreadyUpToDate + } + return nil +} + +func (cmd *getCmd) getWorktreeChanges(r *git.Repository, before string) (bool, error) { + after, err := gitutil.GetHEADRepository(r) + if err != nil { + return false, err + } + return before != after, nil +} + +func (cmd *getCmd) gitClone(cloneURL, dstDir string, cfg *config.Config) error { + isBare := false + r, err := git.PlainClone(dstDir, isBare, &git.CloneOptions{ + URL: cloneURL, + RecurseSubmodules: 10, + }) + if err != nil { + // When fallback_git_cmd is true and git command is installed, + // try to invoke git-clone command + if !*cfg.Get.FallbackGitCmd || !cmd.hasGitCmd() { + return err + } + logger.Warnf("failed to clone, try to execute \"git clone --recursive %s %s\" instead...: %s", cloneURL, dstDir, err.Error()) + err = os.RemoveAll(dstDir) + if err != nil { + return err + } + out, err := exec.Command("git", "clone", "--recursive", cloneURL, dstDir).CombinedOutput() + if err != nil { + return fmt.Errorf("\"git clone --recursive %s %s\" failed, out=%s: %s", cloneURL, dstDir, string(out), err.Error()) + } + } + + return gitutil.SetUpstreamRemote(r, "origin") +} + +func (cmd *getCmd) hasGitCmd() bool { + exeName := "git" + if runtime.GOOS == "windows" { + exeName = "git.exe" + } + _, err := exec.LookPath(exeName) + return err == nil +} diff --git a/config/config.go b/config/config.go index 5ad8b5a8..424c4e8a 100644 --- a/config/config.go +++ b/config/config.go @@ -18,6 +18,7 @@ type ConfigBuild struct { type ConfigGet struct { CreateSkeletonPlugconf *bool `toml:"create_skeleton_plugconf"` + FallbackGitCmd *bool `toml:"fallback_git_cmd"` } const ( @@ -33,6 +34,7 @@ func initialConfigTOML() *Config { }, Get: ConfigGet{ CreateSkeletonPlugconf: &trueValue, + FallbackGitCmd: &trueValue, }, } } @@ -63,6 +65,9 @@ func merge(cfg, initCfg *Config) { if cfg.Get.CreateSkeletonPlugconf == nil { cfg.Get.CreateSkeletonPlugconf = initCfg.Get.CreateSkeletonPlugconf } + if cfg.Get.FallbackGitCmd == nil { + cfg.Get.FallbackGitCmd = initCfg.Get.FallbackGitCmd + } } func validate(cfg *Config) error { From e1965cd7b1d0dd90d90c03c38a7e29a4f330a729 Mon Sep 17 00:00:00 2001 From: tyru Date: Sun, 18 Feb 2018 18:36:37 +0900 Subject: [PATCH 10/11] fix: repos is removed if an error occurred while upgrading (fix #195) --- cmd/get.go | 38 ++++++++++++++++---------------------- 1 file changed, 16 insertions(+), 22 deletions(-) diff --git a/cmd/get.go b/cmd/get.go index 1903039d..b923ef82 100644 --- a/cmd/get.go +++ b/cmd/get.go @@ -339,11 +339,6 @@ func (cmd *getCmd) installPlugin(reposPath pathutil.ReposPath, repos *lockjson.R fromHash, err = gitutil.GetHEAD(reposPath) if err != nil { result := errors.New("failed to get HEAD commit hash: " + err.Error()) - logger.Debug("Rollbacking " + fullReposPath + " ...") - err = cmd.rollbackRepos(fullReposPath) - if err != nil { - result = multierror.Append(result, err) - } done <- getParallelResult{ reposPath: reposPath, status: fmt.Sprintf(fmtInstallFailed, reposPath), @@ -372,11 +367,6 @@ func (cmd *getCmd) installPlugin(reposPath pathutil.ReposPath, repos *lockjson.R err := cmd.upgradePlugin(reposPath, cfg) if err != git.NoErrAlreadyUpToDate && err != nil { result := errors.New("failed to upgrade plugin: " + err.Error()) - logger.Debug("Rollbacking " + fullReposPath + " ...") - err = cmd.rollbackRepos(fullReposPath) - if err != nil { - result = multierror.Append(result, err) - } done <- getParallelResult{ reposPath: reposPath, status: fmt.Sprintf(fmtUpgradeFailed, reposPath), @@ -396,7 +386,7 @@ func (cmd *getCmd) installPlugin(reposPath pathutil.ReposPath, repos *lockjson.R if err != nil { result := errors.New("failed to install plugin: " + err.Error()) logger.Debug("Rollbacking " + fullReposPath + " ...") - err = cmd.rollbackRepos(fullReposPath) + err = cmd.removeDir(fullReposPath) if err != nil { result = multierror.Append(result, err) } @@ -420,10 +410,12 @@ func (cmd *getCmd) installPlugin(reposPath pathutil.ReposPath, repos *lockjson.R toHash, err = gitutil.GetHEAD(reposPath) if err != nil { result := errors.New("failed to get HEAD commit hash: " + err.Error()) - logger.Debug("Rollbacking " + fullReposPath + " ...") - err = cmd.rollbackRepos(fullReposPath) - if err != nil { - result = multierror.Append(result, err) + if doInstall { + logger.Debug("Rollbacking " + fullReposPath + " ...") + err = cmd.removeDir(fullReposPath) + if err != nil { + result = multierror.Append(result, err) + } } done <- getParallelResult{ reposPath: reposPath, @@ -460,12 +452,14 @@ func (cmd *getCmd) installPlugconf(reposPath pathutil.ReposPath, pluginResult *g err := cmd.fetchPlugconf(reposPath) if err != nil { result := errors.New("failed to install plugconf: " + err.Error()) - fullReposPath := pathutil.FullReposPath(reposPath) - logger.Debug("Rollbacking " + fullReposPath + " ...") - err = cmd.rollbackRepos(fullReposPath) - if err != nil { - result = multierror.Append(result, err) - } + // TODO: Call cmd.removeDir() only when the repos *did not* exist previously + // and was installed newly. + // fullReposPath := pathutil.FullReposPath(reposPath) + // logger.Debug("Rollbacking " + fullReposPath + " ...") + // err = cmd.removeDir(fullReposPath) + // if err != nil { + // result = multierror.Append(result, err) + // } done <- getParallelResult{ reposPath: reposPath, status: fmt.Sprintf(fmtInstallFailed, reposPath), @@ -486,7 +480,7 @@ func (*getCmd) detectReposType(fullpath string) (lockjson.ReposType, error) { return lockjson.ReposStaticType, nil } -func (*getCmd) rollbackRepos(fullReposPath string) error { +func (*getCmd) removeDir(fullReposPath string) error { if pathutil.Exists(fullReposPath) { err := os.RemoveAll(fullReposPath) if err != nil { From fa167c40c06aadbf505c25e189cb7c53fca3e754 Mon Sep 17 00:00:00 2001 From: tyru Date: Sun, 18 Feb 2018 20:32:32 +0900 Subject: [PATCH 11/11] Bump version: v0.3.2-beta -> v0.3.2 --- cmd/version.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/version.go b/cmd/version.go index 02b44aca..2bc5f184 100644 --- a/cmd/version.go +++ b/cmd/version.go @@ -9,7 +9,7 @@ import ( "strconv" ) -var voltVersion string = "v0.3.2-beta" +var voltVersion string = "v0.3.2" func init() { cmdMap["version"] = &versionCmd{}

    I5SS1n1J9++n`<`JM&vJfhQNtbD5P4^} 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 literal 0 HcmV?d00001 diff --git a/vendor/github.com/golang/dep/docs/assets/four-states.png b/vendor/github.com/golang/dep/docs/assets/four-states.png new file mode 100644 index 0000000000000000000000000000000000000000..a1aa5a566e59e21451e044e241e5fe0d586911f9 GIT binary patch literal 32855 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 Q`~vtB6OtAz70~hiU*ZW{V*mgE literal 0 HcmV?d00001 diff --git a/vendor/github.com/golang/dep/docs/assets/in-sync.png b/vendor/github.com/golang/dep/docs/assets/in-sync.png new file mode 100644 index 0000000000000000000000000000000000000000..094148a5c04c92d363c4cf3fcf86ab70f9a9f495 GIT binary patch literal 34774 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 Nw1k3qshFYv{{aD-p_c#v literal 0 HcmV?d00001 diff --git a/vendor/github.com/golang/dep/docs/assets/required-arrows.png b/vendor/github.com/golang/dep/docs/assets/required-arrows.png new file mode 100644 index 0000000000000000000000000000000000000000..791076f991fb7a82b408ce99932718ce32fc1616 GIT binary patch literal 46651 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 IkWs+@10a)xk^lez literal 0 HcmV?d00001 diff --git a/vendor/github.com/golang/dep/docs/daily-dep.md b/vendor/github.com/golang/dep/docs/daily-dep.md new file mode 100644 index 00000000..faf22617 --- /dev/null +++ b/vendor/github.com/golang/dep/docs/daily-dep.md @@ -0,0 +1,127 @@ +--- +title: Daily Dep +--- + +This guide is an introduction to the day-to-day use of dep. If you haven't set up a Go project at all yet, though, run through [Creating a New Project](new-project.md) first. + +Dep is a tool you'll use regularly in the course of normal Go development. Regularly, but briefly - dependency management is never the place we want to be spending our time or energy! In keeping with Go's philosophy of minimizing knobs, dep has a sparse interface; there are only two commands you're likely to run regularly: + +* `dep ensure` is the primary workhorse command, and is the only command that changes disk state. +* `dep status` reports on the state of your project, and the visible universe of Go software projects. + +This guide primarily centers on `dep ensure`, as that's the command you run to effect changes on your project. The [Models and Mechanisms](ensure-mechanics.md) reference document details how the things work under the hood, and is worth reading if you're encountering a confusing `dep ensure` behavior (or just curious!). + +## Basics + +Let's start with words! + +Dep's main command is `dep ensure`. The verb is "ensure" to imply that the action is not just some single, discrete action (like adding a dependency), but enforcing some kind of broader guarantee. If we wanted to express the `dep ensure` guarantee as a sentence, it would go something like this: + +> Hey dep, please make sure that [my project](glossary.md#current-project) is [in sync](glossary.md#sync): that [`Gopkg.lock`](Gopkg.lock.md) satisfies all the imports in my project, and all the rules in[ `Gopkg.toml`](Gopkg.toml.md), and that `vendor/` contains exactly what `Gopkg.lock` says it should." + +As the narrative indicates, `dep ensure` is a holistic operation; rather than offering a series of commands that you run in succession to incrementally achieve a some final state, each run of `dep ensure` delivers a safe, complete, and reproducible set of dependencies with respect to the current state of your project. You might imagine repeated runs of `dep ensure` as being a bit like a frog, hopping from one lilypad to the next. + + `dep ensure` also guarantees that, barring `kill -9`, power failure, or a critical bug, its disk writes are all-or-nothing: on any given run, either nothing changes (and you get an error), or you're on the nearest safe lilypad. This makes `dep ensure` fine to run at most any time. + + +## Using `dep ensure` + +There are four times when you'll run `dep ensure`: + +- To add a new dependency +- To update an existing dependency +- To catch up after importing a package for the first time in your project, or removing the last import of a package in your project +- To catch up to a change to a rule in `Gopkg.toml` + +There's also an implicit fifth time: when you're not sure if one of the above has happened. Running `dep ensure` without any additional flags will get your project back in sync - a known good state. As such, it's generally safe to defensively run `dep ensure` as a way of simply making sure that your project is in that state. + +Let's explore each of moments. To play along, you'll need to `cd` into a project that's already been set up by `dep init`. If you haven't done that yet, check out the guides for [new projects](new-project.md) and [migrations](migrating.md). + +### Adding a new dependency + +Let's say that we want to introduce a new dependency on `github.com/pkg/errors`. This can be accomplished with one command: + +```bash +$ dep ensure -add github.com/pkg/errors +``` + +> Much like git, `dep status` and `dep ensure` can also be run from any subdirectory of your project root, which is determined by the presence of a `Gopkg.toml` file. + +This should succeed, resulting in an updated `Gopkg.lock` and `vendor/` directory, as well as injecting a best-guess version constraint for `github.com/pkg/errors` into our `Gopkg.toml`. But, it will also report a warning: + +```bash +"github.com/pkg/errors" is not imported by your project, and has been temporarily added to Gopkg.lock and vendor/. +If you run "dep ensure" again before actually importing it, it will disappear from Gopkg.lock and vendor/. +``` + +As the warning suggests, you should introduce an `import "github.com/pkg/errors"` in your code, the sooner the better. If you don't, a later `dep ensure` run will interpret your newly-added dependency as unused, and automatically remove it from `Gopkg.lock` and `vendor/`. This also means that if you want to add multiple dependencies at once, you'll need to do it in a single command, rather than one after the other: + +```bash +$ dep ensure -add github.com/pkg/errors github.com/foo/bar +``` + +Dep works this way because it considers the import statements it discovers through static analysis of your project's code to be the canonical indicator of what dependencies must be present. That choice does add some pain at this moment, but it reduces friction and automates cleanup elsewhere. Tradeoffs! + +Of course, given this model, you don't _have to_ use `dep ensure -add` to add new dependencies - you can also just add an appropriate `import` statement in your code, then run `dep ensure`. However, this approach doesn't always play nicely with [`goimports`](https://godoc.org/golang.org/x/tools/cmd/goimports), and also won't append a `[[constraint]]` into `Gopkg.toml`. Still, it can be useful at times, often for rapid iteration and off-the-cuff experimenting. + +The [ensure mechanics section on `-add`](ensure-mechanics.md#add) has a more thorough exploration, including some ways that `dep ensure -add`'s behavior subtly varies depending on the state of your project. + +### Updating dependencies + +Ideally, updating a dependency project to a newer version is a single command: + +```bash +$ dep ensure -update github.com/foo/bar +``` + +This also works without arguments to try to update all dependencies, though it's generally not recommended: + +```bash +$ dep ensure -update +``` + +`dep ensure -update` searches for versions that work with the `branch`, `version`, or `revision` constraint defined in `Gopkg.toml`. These constraint types have different semantics, some of which allow `dep ensure -update` to effectively find a "newer" version, while others will necessitate hand-updating the `Gopkg.toml`. The [ensure mechanics](ensure-mechanics.md#update-and-constraint-types) guide explains this in greater detail, but if you want to know what effect a `dep ensure -update` is likely to have for a particular project, the `LATEST` field in `dep status` output will tell you. + +### Adding and removing `import` statements + +As noted in [the section on adding dependencies](#adding-a-new-dependency), dep relies on the import statements in your code to figure out which dependencies your project actually needs. Thus, when you add or remove import statements, dep might need to care about it. + +It's only "might," though, because most of the time, adding or removing imports doesn't matter to dep. Only if one of the following has occurred will a `dep ensure` be necessary to bring the project back in sync: + +1. You've added the first `import` of a package, but already `import` other packages from that project. +2. You've removed the last `import` of a package, but still `import` other packages from that project. +3. You've added the first `import` of any package within a particular project. (Note: this is the [alternate adding approach](#adding-a-new-dependency)) +4. You've removed the last `import` of a package from within a particular project. + +In short, dep is concerned with the set of unique import paths across your entire project, and only cares when you make a change that adds or removes an import path from that set. + +Of course, especially on large projects, it can be tough to keep track of whether adding or removing (especially removing) a particular import statement actually does change the overall set. Fortunately, you needn't keep close track, as you can run `dep ensure` and it will automatically pick up any additions or removals, and bring your project back in sync. + +Only if it is the first/last import of a project being added/removed - cases 3 and 4 - are additional steps needed: `Gopkg.toml` should be updated to add/remove the corresponding project's `[[constraint]]`. + +### Rule changes in `Gopkg.toml` + +`Gopkg.toml` files contain five basic types of rules. The [`Gopkg.toml` docs](#gopkg.toml.md) explain them in detail, but here's an overview: + +* `required`, which are mostly equivalent to `import` statements in `.go` files, except that it's OK to list a `main` package here +* `ignored`, which causes dep to black hole an import path (and any imports it uniquely introduces) +* `[[constraint]]`, stanzas that express version constraints and some other rules on a per-project dependency basis +* `[[override]]`, stanzas identical to `[[constraint]]` except that only the current project can express them and they supersede `[[constraint]]` in both the current project and dependencies +* `[prune]`, global and per-project rules that govern what kinds of files should be removed from `vendor/` + +Changes to any one of these rules will likely necessitate changes in `Gopkg.lock` and `vendor/`; a single successful `dep ensure` run will incorporate all such changes at once, bringing your project back in sync. + +## Key Takeaways + +Here are the key takeaways from this guide: + +- `dep ensure -update` is the preferred way to update dependencies, though it's less effective for projects that don't publish semver releases. +- `dep ensure -add` is usually the easiest way to introduce new dependencies, though it's not the only one. To add more than one at a time, you'll need to use multiple arguments, not multiple invocations - and make sure to add real `import` statements for the projects after the command completes! +- If you ever make a manual change in `Gopkg.toml`, it's best to run `dep ensure` to make sure everything's in sync. +- `dep ensure` is almost never the wrong thing to run; if you're not sure what's going on, running it will bring you back to safety ("the nearest lilypad"), or fail informatively. + +Also, a couple other miscellaneous tidbits: + +- As in the Go toolchain generally, avoid symlinks within your own project. dep tolerates a bit of this, but like the Go toolchain itself, is generally not terribly supportive of symlinks. +- Never directly edit anything in `vendor/`; dep will unconditionally overwrite such changes. If you need to modify a dependency, fork it and do it properly. + diff --git a/vendor/github.com/golang/dep/docs/deduction.md b/vendor/github.com/golang/dep/docs/deduction.md new file mode 100644 index 00000000..3675c194 --- /dev/null +++ b/vendor/github.com/golang/dep/docs/deduction.md @@ -0,0 +1,26 @@ +--- +title: Import Path Deduction +--- + +Deduction is dep's algorithm for looking at an import path and determining the portion of the path that corresponds to the source root. The algorithm has a static component, by which a small set of known, popular hosts like GitHub and Bitbucket have their roots deduced: + +- `github.com/golang/dep/gps` -> `github.com/golang/dep` +- `bitbucket.org/foo/bar/baz` -> `bitbucket.org/foo/bar` + +The set of hosts supported by static deduction are the same as [those supported by `go get`](https://golang.org/cmd/go/#hdr-Remote_import_paths): + +* GitHub +* Bitbucket +* Launchpad +* IBM DevOps Services + +In addition, dep also handles [gopkg.in](http://gopkg.in) directly with static deduction because, owing to internal implementation details, it is the easiest way of also attaching filters to adapt the versioning semantics of gopkg.in import paths into dep's versioning model. This turns out fine, as gopkg.in's rules mapping rules are themselves entirely static. + +If the static logic cannot identify the root for a given import path, the algorithm continues to a dynamic component: dep makes an HTTP(S) request to the import path, and a server is expected to send back the root import path embedded within the HTML response. Again, this directly emulates the behavior of `go get`. + +Import path deduction is applied to all of the following: + +* `import` statements found in all `.go` files +* Import paths in the [`required`](gopkg.toml.md#required) list in `Gopkg.toml` +* `name` properties in both [`[[constraint]]`](Gopkg.toml.md#constraint) and [`[[override]]`](Gopkg.toml.md#override) stanzas in `Gopkg.toml`. This is solely for validation purposes, enforcing that these names correspond only to project/source roots. + diff --git a/vendor/github.com/golang/dep/docs/ensure-mechanics.md b/vendor/github.com/golang/dep/docs/ensure-mechanics.md new file mode 100644 index 00000000..e7173425 --- /dev/null +++ b/vendor/github.com/golang/dep/docs/ensure-mechanics.md @@ -0,0 +1,203 @@ +--- +title: Models and Mechanisms +--- + +While dep has many discrete components and moving parts, all of these parts revolve around a central model. This document explains that model, then explores the dep's primary mechanisms in the context of that model. + +## States and flows + +Dep is centered around the idea of the "four state system" - a model for classifying and organizing the on-disk state with which a package manager interacts. This was first articulated as a coherent, general model in [this (long) article](https://medium.com/@sdboyer/so-you-want-to-write-a-package-manager-4ae9c17d9527), though many of the principles in the four state model were derived from existing package managers. + +Briefly, the four states are: + +1. The [current project's](glossary.md#current-project) source code. +2. A [manifest](glossary.md#manifest) - a file describing the current project's dependency requirements. In dep, this is the [`Gopkg.toml`](Gopkg.toml.md) file. +3. A [lock](glossary.md#lock) - a file containing a transitively-complete, reproducible description of the dependency graph. In dep, this is the [`Gopkg.lock`](Gopkg.lock.md) file. +4. The source code of the dependences themselves. In dep's current design, this is the `vendor/` directory. + +We can visually represent these four states as follows: + +![dep's four states](assets/four-states.png) + +### Functional flow + +It's useful to think of dep as a system that imposes a unidirectional, functional flow on the relationships between these states. These functions treat the above states as inputs and outputs, moving them from left to right. Specifically, there are two functions: + +* A _solving function_, that takes as its input the set of imports in the current project and the rules in `Gopkg.toml`, and returns as its output a transitively-complete, immutable dependency graph - the information in a `Gopkg.lock`. +* A _vendoring function_, that takes the information in a `Gopkg.lock` as its input and ensures an on-disk arrangement of source files such that the compiler will use the versions designated in the lock. + +We can represent these two functions visually: + +![dep's two main functions](assets/annotated-func-arrows.png) + +This is `dep ensure` - the typical flow, used when a `Gopkg.toml` already exists. When a project does not yet have a `Gopkg.toml`, `dep init` can generate one. The essential flow remains the same, but with changed inputs: instead of reading from an existing `Gopkg.toml` file, `dep init` constructs one out of data inferred from the user's GOPATH, and/or [a metadata file from another tool](). (In other words, `dep init` automatically migrates a project from other approaches to organizing dependencies.) + +This diagram directly corresponds directly to code, as well. The solving function is actually split into a constructor and a method - we first create a [`Solver`](https://godoc.org/github.com/golang/dep/gps#Solver) type, then call its `Solve()` method. The inputs to the constructor are wrapped up in a [`SolveParameters`](https://godoc.org/github.com/golang/dep/gps#SolveParameters), which should look familiar: + +```go +type SolveParameters struct { + RootPackageTree pkgtree.PackageTree // Parsed project src; contains lists of imports + Manifest gps.RootManifest // Gopkg.toml + ... +} +``` + +The vendoring function is [`gps.WriteDepTree()`](https://godoc.org/github.com/golang/dep/gps#WriteDepTree). While it takes a handful of arguments, the relevant one is a [`gps.Lock`](https://godoc.org/github.com/golang/dep/gps#Lock) - an interface representing an abstracted form of the data held in a `Gopkg.lock`. + +The four state system, and these functional flows through it, are the foundation on which all of dep's behavior is built. If you want to understand dep's mechanics, keep this model at the forefront of your mind. + +### Staying in sync + +One of dep's design goals is that both of its "functions" minimize both the work they do, and the change they induce in their respective results. (Note: "minimize" is not currently formally defined with respect to a cost function.) Consequently, both functions peek ahead at the pre-existing result to understand what work actually needs to be done: + +* The solving function checks the existing `Gopkg.lock` to determine if all of its inputs (project import statements + `Gopkg.toml` rules) are satisfied. If they are, the solving function can be bypassed entirely. If not, the solving function proceeds, but attempts to change as few of the selections in `Gopkg.lock` as possible. + * WIP: The current implementation's check relies on a coarse heuristic check that can be wrong in some cases. There is a [plan to fix this](https://github.com/golang/dep/issues/1496). +* The vendoring function hashes each discrete project already in `vendor/` to see if the code present on disk is what `Gopkg.lock` indicates it should be. Only projects that deviate from expectations are written out. + * WIP: the hashing check is generally referred to as "vendor verification," and [is not yet complete](https://github.com/golang/dep/issues/121). Without this verification, dep is blind to whether code in `vendor/` is correct or not; as such, dep must defensively re-write all projects to ensure the state of `vendor/` is correct. + +Of course, it's possible that, in peeking ahead, either function might discover that the pre-existing result is already correct - so no work need be done at all. Either way, when each function completes, we can be sure that the output, changed or not, is correct with respect to the inputs. In other words, the inputs and outputs are "in sync." Indeed, being in sync is the "known good state" of dep; `dep ensure` (without flags) guarantees that if it exits 0, all four states in the project are in sync. + +## `dep ensure` flags and behavior variations + +Each of `dep ensure`'s various flags affects the behavior of the solving and vendoring functions - or even whether they run at all. Some flags can also marginally push the project out of sync, temporarily. Thinking about these effects in the context of dep's basic model is the fastest path to understanding. + +### `-no-vendor` and `-vendor-only` + +These two flags are mutually exclusive, and determine which of `dep ensure`'s two functions are actually performed. Passing `-no-vendor` will cause only the solving function to be run, resulting in the creation of a new `Gopkg.lock`; `-vendor-only` will skip solving and run only the vendoring function, causing `vendor/` to be repopulated from the pre-existing `Gopkg.lock`. + +![Flags to run only one or the other of dep's functions](assets/func-toggles.png) + +Passing `-no-vendor` has the additional effect of causing the solving function to run unconditionally, bypassing the pre-check ordinarily made against `Gopkg.lock` to see if it already satisfies all inputs. + +### `-add` + +The general purpose of `dep ensure -add` is to facilitate the introduction of new dependencies into the depgraph. Whereas `-update` is restricted to [source roots](glossary.md#source-root), (e.g. `github.com/foo/bar`), `-add` can take any package import path as an argument (e.g. `github.com/foo/bar` OR `github.com/foo/bar/baz`). + +Conceptually, there are two possible things that `-add` might be introducing. Any `dep ensure -add` run will do at least one of these: + +1. Running the solving function in order to generate a new `Gopkg.lock` with the new dependenc(ies) +2. Appending a version constraint into `Gopkg.toml` + +This implies two preconditions for `dep ensure -add`, at least one of which must be met: + +1. The named import path is not currently in the project's import statements, or in `Gopkg.toml`'s `required` list +2. There is no `[[constraint]]` stanza in `Gopkg.toml` for the project root corresponding to the named import path + + +It is also possible to explicitly specify a version constraint: + +```bash +$ dep ensure -add github.com/foo/bar@v1.0.0 +``` + +When no version constraint is included in the argument, the solving function will select the latest version that works (generally, the newest semver release, or the default branch if there are no semver releases). If solving succeeds, then either the argument-specified version, or if none then the version selected by the solver, will be appended into `Gopkg.toml`. + +The behavioral variations that arise from the assorted differences in input and current project state are best expressed as a matrix: + +| Argument to `dep ensure -add` | Has `[[constraint]]` stanza in `Gopkg.toml` | In imports or `required` | Result | +| ----------------------------- | ---------------------------------------- | ------------------------ | ---------------------------------------- | +| `github.com/foo/bar` | N | N | Added temporarily to `Gopkg.lock` & `vendor/`; inferred version constraint appended to `Gopkg.toml` | +| `github.com/foo/bar@v1.0.0` | N | N | Added temporarily to `Gopkg.lock` & `vendor/`; specified version constraint appended to `Gopkg.toml` | +| `github.com/foo/bar` | Y | N | Added temporarily to `Gopkg.lock` & `vendor/` | +| `github.com/foo/bar@v1.0.0` | Y | - | **Immediate error**: constraint already present in `Gopkg.toml` | +| `github.com/foo/bar` | N | Y | Infer version constraint from `Gopkg.lock` and add to `Gopkg.toml` | +| `github.com/foo/bar` | Y | Y | **Immediate error:** nothing to do | + +For any of the paths where `dep ensure -add` needs to run the solving function in order to generate an updated `Gopkg.lock`, the relevant information from CLI arguments is applied to the in-memory representation of `Gopkg.toml`: + +![Model modifications made by -add](assets/required-arrows.png) + +Import path arguments that need to be added are injected via the `required` list, and if an explicit version requirement was specified, the equivalent of a `[[constraint]]` is created. + +Though these rules may ultimately be persisted if solving succeeds, they are ephemeral at least until solving succeeds. And, from the solver's perspective, the ephemeral rules are indistinguishable from rules sourced directly from disk. Thus, to the solver, `dep ensure -add foo@v1.0.0` is identical to modifying `Gopkg.toml` by adding `"foo"` to the `required` list, plus a `[[constraint]]` stanza with `version = "v1.0.0"`, then running `dep ensure`. + +However, because these modifications are ephemeral, a successful `dep ensure -add` may actually push the project out of sync. Constraint modifications generally do not, but if the `required` list is modified, then the project will desync. The user is warned accordingly: + +```bash +$ dep ensure -add github.com/foo/bar +"github.com/foo/bar" is not imported by your project, and has been temporarily added to Gopkg.lock and vendor/. +If you run "dep ensure" again before actually importing it, it will disappear from Gopkg.lock and vendor/. +``` + +### `-update` + +The behavior of `dep ensure -update` is intimately linked to the behavior of the solver itself. Full detail on that is a topic for the [solver reference material](the-solver.md), but for the purposes of understanding `-update`, we can simplify a bit. + +First, to solidify an implication in the discussion of [functional optimizations](#staying-in-sync), the solving function actually takes into account the pre-existing `Gopkg.lock` when it runs: + +![Pre-existing lock feeds back into solving function](assets/lock-back.png) + +Injecting `Gopkg.lock` into the solver is a necessity. If we want the solver to preserve previously-selected versions by default, then the solver has to learn about the existing `Gopkg.lock` from somewhere. Otherwise, it wouldn't know what to preserve! + +As such, the lock is another one of the properties encoded onto the [previously-discussed]() `SolveParameters` struct. That, plus two other properties, are the salient ones for `-update`: + +```go +type SolveParameters struct { + ... + Lock gps.Lock // Gopkg.lock + ToChange []gps.ProjectRoot // args to -update + ChangeAll bool // true if no -update args passed + ... +} +``` + +Ordinarily, when the solver encounters a project name for which there's an entry in `Gopkg.lock`, it pulls that version out and puts it at the head of the queue of possible versions for that project. When a specific dependency is passed to `dep ensure -update`, however, it is added to the `ToChange` list; when the solver encounters a project listed in `ToChange`, it simply skips pulling the version from the lock. + +"Skips pulling the version from the lock" would imply that `dep ensure -update github.com/foo/bar` is equivalent to removing the `[[project]]` stanza for `github.com/foo/bar` from your `Gopkg.lock`, then running `dep ensure`. And indeed it is - however, that approach is not recommended, and subtle changes may be introduced in the future that complicate the equivalency. + +If `-update` is passed with no arguments, then `ChangeAll` is set to `true`, resulting in the solver ignoring `Gopkg.lock` for all newly-encountered project names. This is equivalent to explicitly passing all of your dependences as arguments to `dep ensure -update`, as well as `rm Gopkg.lock && dep ensure`. Again, however, neither of these approaches are recommended, and future changes may introduce subtle differences. + +When a version hint from `Gopkg.lock` is not placed at the head of the version queue, it means that dep will explore the set of possible versions for a particular dependency. This exploration is performed according to a [fixed sort order](https://godoc.org/github.com/golang/dep/gps#SortForUpgrade), where newer versions are tried first, resulting in an update. + +For example, say there is a project, `github.com/foo/bar`, with the following versions: + +```bash +v1.2.0, v1.1.1, v1.1.0, v1.0.0, master +``` + +If we depend on that project with `^1.1.0`, and have `v1.1.0` in our `Gopkg.lock` , then it means there are three versions that match our constraint, and two of them are newer than the one currently selected. (There's also an older version, `v1.0.0`, and a `master` branch, but these aren't allowed by a `^1.1.0` constraint.) An ordinary `dep ensure` run will duplicate and push `v1.1.0` ahead of all the others in the queue: + +```bash +[v1.1.0, v1.2.0, v1.1.1, v1.1.0, v1.0.0, master] +``` + +And `v1.1.0` will be selected again, unless some other condition is presented that forces the solver to discard it. When running `dep ensure -update github.com/foo/bar`, however, the locked version is not prepended: + +```bash +[v1.2.0, v1.1.1, v1.1.0, v1.0.0, master] +``` + +So, barring some other conflict, `v1.2.0` is selected, resulting in the desired update. + +#### `-update` and constraint types + +Continuing with our example, it's important to note that updates with `-update` are achieved incidentally - the solver never explicitly targets a newer version. It just skips adding a hint from the lock, then selects the first version in the queue that satisfies constraints. Consequently, `-update` is only effective with certain types of constraints. + +It does work with branch constraints, which we can observe by including the underlying revision. If the user has constrained on `branch = "master"`, and `Gopkg.lock` points at a topologically older revision (say, `aabbccd`) than the tip of the canonical source's `master` branch (say, `bbccdde`), then `dep ensure` will end up contructing a queue that looks like this: + +```bash +[master@aabbccd, v1.1.0, v1.2.0, v1.1.1, v1.1.0, v1.0.0, master@bbccdde] +``` + +With `-update`, the hint at the head will be omitted; `branch = "master"` will cause the solver to reject all of the semantic versions, and finally settle on `master@bbccdde`. + +All versions in the version queue keep track of an underlying revision, which means the same is true if, for example, some upstream project force-pushes a git tag: + +```bash +[v1.1.0@aabbccd, v1.1.0, v1.2.0, v1.1.1, v1.1.0@bbccdde, v1.0.0, master] +``` + +Thus, even if an upstream tag is force-pushed in one of your project's dependences, dep will retain the original revision until you explicitly allow it to change via a `dep ensure -update`. + +The key takeaway here is that `-update`'s behavior is governed by the type of constraints specified: + +| `Gopkg.toml` version constraint type | Constraint example | `dep ensure -update` behavior | +| ------------------------------------ | ------------------ | ---------------------------------------- | +| `version` (semver range) | `"^1.0.0"` | Tries to get the latest version allowed by the range | +| `branch` | `"master"` | Tries to move to the current tip of the named branch | +| `version` (non-range semver) | `"=1.0.0"` | Change can only occur if the upstream release was moved (e.g. `git push --force `) | +| `version` (non-semver) | `"foo"` | Change can only occur if the upstream release was moved | +| `revision` | `aabbccd...` | No change is possible | +| (none) | (none) | The first version that works, according to [the sort order](https://godoc.org/github.com/golang/dep/gps#SortForUpgrade) (not recommended) | + + diff --git a/vendor/github.com/golang/dep/docs/failure-modes.md b/vendor/github.com/golang/dep/docs/failure-modes.md new file mode 100644 index 00000000..f06acca0 --- /dev/null +++ b/vendor/github.com/golang/dep/docs/failure-modes.md @@ -0,0 +1,204 @@ +--- +title: Failure Modes +--- + +Like all complex, network-oriented software, dep has known failure modes. These generally fall into two categories: I/O and logical. I/O errors arise from unexpected responses to system calls that interact with the network or local disk. Logical failures occur when dep encounters issues within the package management problem domain. + +## I/O errors + +dep reads from the network, and reads and writes to disk, and is thus subject to all the typical errors that are possible with such activities: full disks, failed disks, lack of permissions, network partitions, firewalls, etc. However, there are three classes of I/O errors that are worth addressing specifically: + +* Network failures +* Bad local cache state +* `vendor` write errors + +In general, these problems aren't things we can reasonably program around in dep. Therefore, they can't be considered bugs for us to fix. Fortunately, most of these problems have straightforward remediations. + +### Network failures + +> **Remediation tl;dr:** most network issues are ephemeral, even if they may last for a few minutes, and can be addressed simply by re-running the same command. Always try this before attempting more invasive solutions. + +dep talks to the network at several different points. These vary somewhat depending on source (VCS) type and local disk state, but this list of operations is generally instructive: + +* When dep cannot [statically deduce](deduction.md#static-deduction) the source root of an import path, it issues a `go-get` HTTP metadata request to a URL constructed from the import path. +* Retrieving the list of available versions for a source (think `git ls-remote`) necessarily requires network activity. +* Initially downloading (in git terms, `git clone`) an upstream source into the local cache also necessarily requires network activity. +* Updating a local cache (in git terms, `git fetch`) with the latest changes from an upstream source. +* Writing out code trees under `vendor` is typically done from the local cache, but under some circumstances a tarball may be fetched on-the-fly from a remote source. + + +Network failures that you actually may observe are biased towards the earlier items in the list, simply because those operations tend to happen first: you generally don't see update failures as much as version-listing failures, because they usually have the same underlying cause (source host is down, network partition, etc.), but the version-list request happens first on most paths. + +#### Persistent network failures + +Although most network failures are ephemeral, there are three well-defined cases where they're more permanent: + +* **The network on which the source resides is permanently unreachable from the user's location:** in practice, this generally means one of two things: you've forgotten to log into your company VPN, or you're behind [the GFW](https://en.wikipedia.org/wiki/Great_Firewall). In the latter case, setting the *de facto* standard HTTP proxy environment variables that [`http.ProxyFromEnvironment()`](https://golang.org/pkg/net/http/#ProxyFromEnvironment) respects will cause dep's `go-get` HTTP metadata requests, as well as git, bzr, and hg subcommands, to utilize the proxy. + + * Remediation is also exactly the same when the custom `go-get` HTTP metadata service for a source is similarly unreachable. The failure messages, however, will look like [deduction failures](#deduction-failures). + +* **The source has been permanently deleted or moved:** these are [left-pad](https://www.theregister.co.uk/2016/03/23/npm_left_pad_chaos/) events, though note that [GitHub automatically redirects traffic after renames](https://help.github.com/articles/renaming-a-repository/), mitigating the rename problem. But, if an upstream source is removed, dep will be unable to proceed until a new upstream source is established for the import path. To that end: + + * If you still have a copy of the source repository in your local cache or GOPATH, consider uploading it to a new location (e.g. forking it) and using a [`source`](Gopkg.toml.md#source) rule to point to the fork. + * If you don't have a whole repository locally, then extracting the code currently in your `vendor` directory into a new repository and pushing it to a . (Note: this may have licensing implications.) + * If you have no instances of the code locally, then there's little that can be done - that code is simply gone, and you'll need to refactor your project. + + Future versions of dep will be able to better handle an interim period before a new upstream/forked source is created, or simply living in a world where a given code tree exists solely in your project's `vendor` directory. + +* **The user lacks the necessary credentials to interact with a source:** see the [FAQ on configuring credentials](FAQ.md#how-do-i-get-dep-to-authenticate-to-a-git-repo). + +The exact error text will vary depending on which of the operations is running, what type of source dep is trying to communicate with, and what actual network problem has occurred. The error text may not always make it immediately clear which combination of these you're dealing with, but for persistent problems, it should at least reduce the search space. + +#### Hangs + +> **Remediation tl;dr:** hangs are almost always network congestion, or sheer amount of network data to fetch. Wait, or cancel and try again with `-v` to try to get more context. + +Almost any case where a dep command, run with `-v`, hangs for more than ten minutes will ultimately be a bug. However, the most common explanation for an apparent dep hangs is actually normal behavior: because dep's operation requires that it keep its own copies of upstream sources hidden away in the [local cache](glossary.md#local-cache), the first run of dep against a project, especially large projects, can take a long time while it populates the cache. + +The only known case where dep may hang indefinitely is if one of the underlying VCS binaries it calls is prompting for some kind of input. Typically this means credentials (though not always - make sure to accept remote hosts' SSH keys into your known hosts!), and dep's normal assumption is that necessary credentials have been provided via environmental mechanisms - [configuration files or daemons](FAQ.md#how-do-i-get-dep-to-authenticate-to-a-git-repo), SSH agents, etc. This assumption is necessary for dep's concurrent network activity to work. If your use case absolutely cannot support the use of any such environmental caching mechanism, [please weigh in on this issue](). + +Unfortunately, until dep [improves the observability of its ongoing I/O operations](), it cannot accurately report to the user which operations are actually underway at any given moment. This can make it difficult to differentiate from other hangs - credentials prompts, long network timeouts induced by firewalls, sluggish TCP when faced with packet loss, etc. + +### Bad local cache state + +> **Remediation tl;dr:** Remove the local cache dir: `rm -rf $GOPATH/pkg/dep/sources`. + +It is possible for parts of the [local cache](glossary.md#local-cache) maintained by dep to get into a bad state. This primarily happens when dep processes are forcibly terminated (e.g. Ctrl-C). This can, for example, terminate a `git` command partway through, leaving bad state on disk. By dep's definition, a [dirty git working copy]() is bad state. + +The error messages arising from bad local cache state often do not include full paths, so it may not be immediately obvious that problems are originating in the local cache. If full paths aren't included, then the best hint tends to be that the errors look like local VCS errors, but they're not on files from your own project. + +However, for the most part, **dep automatically discovers and recovers from bad local cache state problems**, rebounding back into a good state as it bootstraps each command execution. If you do encounter what appears to be a local cache problem from which dep does not automatically recover, then the fix is typically to just throw out the cache, `rm -rf $GOPATH/pkg/dep/sources`; dep will repopulate it automatically on the next run. However, if you have time, please preserve the local cache dir and report it as a bug! + +There are no known cases where, in the course of normal operations, dep can irreparably corrupt its own local cache. Any such case would be considered a critical bug in dep, and you should report it! If you think you've encountered such a case, it should have the following characteristics: + +* The error message you're seeing is consistent with some sort of disk state error in a downloaded source within `$GOPATH/pkg/dep/sources` +* You can identify a bad state (generally: a vcs "status"-type command will either fail outright, or report a modified working tree) in a subdirectory of `$GOPATH/pkg/dep/sources` suggested by the above error +* The exact same error recurs after removing the local cache dir and running the same command, **without** prematurely terminating the project (e.g. via Ctrl-C) + +### `vendor` write errors + +Dep may encounter errors while attempting to write out the `vendor` directory itself (any such errors will result in a full rollback; causing no changes to be made to disk). To help pinpoint where the problem may be, know that this is the flow for populating `vendor`: + +1. Allocate a new temporary directory within the system temporary directory. +2. Rename the existing `vendor` directory to `vendor.orig`. Do this within the current project's root directory if possible; if not, rename and move it to the tempdir. +3. Create a new `vendor` directory within the tempdir and concurrently populate it with all the projects named in `Gopkg.lock`. +4. Move the new `vendor` directory into place in the current project's root directory. +5. Delete the old `vendor` directory. + +Note: this flow will become more targeted after [vendor verification]() allows dep to identify and target the subset of projects currently in `vendor` that need to be changed. + +Known problems in this category include: + +* Insufficient space in the temporary directory will cause an error, triggering a rollback. However, because the rollback process cleans up files written so-far, the temporary partition won't actually be full after dep exits, which can be misleading. +* Attempting to [re]move the original `vendor` directory can fail with permissions errors if any of the files therein are "open", in some editors/on some OSes (particularly Windows). [There's an issue for this](). + +## Logical failures + +Logical failures encompass everything that can happen within dep's logical problem-solving domain - after + +Some of these failures can be as straightforward as typos, and are just as easily resolved. Others, unfortunately, may necessitate forking and modifying an upstream project - although such cases are very rare. + +### Deduction failures + +Import path deduction, as detailed in the [deduction reference](deduction.md), has both static and dynamic phases. When neither of these phases is able to determine the source root for a given import path, it is considered to be a deduction failure. Deduction failures all contain this key error text: + +```bash +...unable to deduce repository and source type for ""... +``` + +_Note: there are [more varied error messages for the small subset of cases](#malformed-import-paths) where an import path appears to be deducible, but is somehow malformed._ + +When a deduction failure occurs on a given import path, the proximal cause will have been one of following five scenarios (arranged from most to least likely): + +* The import path was never deducible. +* **Dynamic deduction failures:** + * The import path was, at one time, dynamically deducible, and the metadata service for it is up, but it is unreachable by dep. + * The import path was, at one time, dynamically deducible, but the metadata service for it is down. +* **Static rule changes:** + * The import path cannot be statically deduced by the running version of dep, but a newer version of dep has added rules that can statically deduce it. + * The import path was once statically deducible, but the running version of dep has discontinued support for it. + +In all of these cases, your last recourse will be to add a [`source`](Gopkg.toml.md#source) directive to fix the problem. However, these directives are brittle, and should only be used when other options have been exhausted; also, until [this problem is solved](https://github.com/golang/dep/issues/860), even `source` may not be able to help. + +#### Undeducible paths + +> **Remediation tl;dr:** You made a typo; fix it. If not, you may need a `source`, but be sparing with those. + +The most likely cause of deduction failure is minor user error. Specifically, the user is the _current_ user (you), and the error is there is a mistyped import path somewhere in the current (your) project. The problem may be in your `Gopkg.toml`, or one of your imports, but the error message should point you directly at the problem, and the solution is usually obvious - e.g., "gihtub". + +Validation of the inputs from the current project are made fast and up front in dep, so these errors will tend to present themselves immediately. Between this fast validation, and the fact that projects are typically uncompilable, or at least not `go get`-able, with these kinds of errors, they tend to be caught early. This is why truly undeducible paths pop up primarily as temporary accidents while hacking on your own projects - you have to fix them to move on. + +That undeducibility is an immediate and hard blocker, however, has led to this being a sticking point for migration to dep. In particular, there are two issues: + +* Several other Go dependency management tools do allow specifying arbitrary VCS/source URLs, and [but support for that via `source` in dep is still pending](https://github.com/golang/dep/issues/860). +* GitHub Enterprise only implements `go-get` HTTP metadata correctly for the root package of a repository. In practice, this makes all import paths pointing to GHE undeducible, and `source` can't help either without the aforementioned improvement. + +If the problem import path is in your current project, but the problem isn't an obvious typo, then you're likely experiencing a dynamic failure, or may need to check the [deduction reference](deduction.md) to understand what what a deducible import path looks like. + +#### Dynamic deduction failures + +Most dynamic deduction failures are either ephemeral network or service availability issues, and will go away by re-running the previous command. Always try that first. + +If the issue persists, and you're certain the import path should be deducible, network issues are the first culprit to check. The typical causes (VPN, firewalls) and remediation for when a metadata service is unreachable are the same as [when a source itself is unreachable](#persistent-network-failures). + +The next possibility is a metadata service that's permanently gone away. Whereas network errors are still reasonably common, it is rare to encounter an import path pointing to a defunct public metadata service. Consider: that one import path can render the entire project unfetchable and/or uncompilable, and neither of those are states that popular projects can afford to be in for long. So, being that most (public Go ecosystem) dependencies are on the more popular projects, as long as you're also depending on the more popular projects, you're unlikely to encounter this. + +Of course, defunct _private_ metadata services may be much more common, as they are subject to entirely different incentives. + +If you think you've encountered a defunct metadata service, try probing the domain portion of the import path directly to see if there is an HTTP(S) server there at all. If not, you can only force with `source` - assuming you know what source URL you should use. If not, you may need to refactor your code (if the problem is in your project), pick a different version of the problem dependency, or drop the problem dependency entirely; sometimes, you just have to get rid of dead code. + +#### Static rule changes + +> **Remediation tl;dr:** make sure you have the latest released version of dep. + +Static rule changes are very unlikely to be the cause of your deduction failures. + +It is plausible that dep will add new static deduction rules in the future. And it is possible that, if you have an older version of dep, and you collaborate with or pull in code from someone using a newer version of dep, then their code may take advantage of new import path patterns that your dep doesn't know about yet. But very, very few static rules additions are likely to ever be made to dep over its lifetime - and getting access to them is just a question of updating once. + +The final scenario - dep discontinuing support for a static deduction pattern - is included for clarity and completeness, but simply should never happen. Even if a hosting service covered by static rules today were to shut down, dep would retain the existing static rules; if hosted code had been migrated elsewhere, then dep would attempt to perform a remapping automatically. If no such remapping were possible, then dep would still recognize the basic host pattern, but may fall back on using malformed import path errors - the next topic - to informatively reject new imports from the host. + +#### Malformed import paths + +For the most part, static ("is it one of the handful of hosts we know?") and dynamic ("just do whatever the metadata service tells us to do") deduction are single-pass checks. However, both cases can perform some minor additional validation: + +* In static deduction, the rules are necessarily specific to each host, but most enforce allowable characters and schemes in URLs that are known to be required by the underlying host. +* In dynamic deduction, responses from the metadata service are minimally validated to ensure that the source type and scheme are all supported, and that the URL contains valid characters. + +### Solving failures + +When `dep ensure` or `dep init` exit with an error message looking something like this: + +```bash +$ dep init +init failed: unable to solve the dependency graph: Solving failure: No versions of github.com/foo/bar met constraints: + v1.0.1: Could not introduce github.com/foo/bar@v1.13.1, as its subpackage github.com/foo/bar/foo is missing. (Package is required by (root).) + v1.0.0: Could not introduce github.com/foo/bar@v1.13.0, as... + v0.1.0: (another error) + master: (another error) +``` + +_Note: all three of the other hard failure types can sometimes be reported as the errors for individual versions in a list like this. This primarily happens because dep is in need of a [thorough refactor of its error handling](https://github.com/golang/dep/issues/288)._ + +It means that the solver was unable to find a combination of versions for all dependencies that satisfy all the rules enforced by the solver. It is crucial to note that, just because dep provides a big list of reasons why each version failed _doesn't mean_ you have to address each one! That's just dep telling you why it ultimately couldn't use each of those versions in a solution. + +These rules, and specific remediations for failing to meet them, are described in detail in the section on [solver invariants](the-solver.md#solving-invariants). This section is about the steps to take when solving failures occur in general. But, to set context, here's a summary: + +* **`[[constraint]]` conflicts:** when projects in the dependency graph disagree on what [versions](gopkg.toml.md#version-rules) are acceptable for a project, or where to [source](gopkg.toml.md#source) it from. + * Remediation will usually be either changing a `[[constraint]]` or adding an `[[override]]`, but genuine conflicts may require forking and hacking code. +* **Package validity failure:** when an imported package is quite obviously not capable of being built. + * There usually isn't much remediation here beyond "stop importing that," as it indicates something broken at a particular version. +* **Import comment failure:** when the import path used to address a package differs from the [import comment](https://golang.org/cmd/go/#hdr-Import_path_checking) the package uses to specify how it should be imported. + * Remediation is to use the specified import path, instead of whichever one you used. +* **Case-only import variation failure:** when two equal-except-for-case imports exist in the same build. + * Remediation is to pick one case variation to use throughout your project, then manually update all projects in your depgraph to use the new casing. + + +Let's break down the process of addressing a solving failure into a series of steps: + +1. First, look through the failed versions list for a version of the dependency that works for you (or a failure that seems fixable), then try to work that one out. Often enough, you'll see a single failure repeated across the entire version list, which makes it pretty clear what problem you need to solve. +2. Take the remediation steps specific to that failure. +3. Re-run the same command you ran that produced the failure. There are three possible outcomes: + 1. Success! + 2. Your fix was ineffective - the same failure re-occurs. Either re-examine your fix (step 2), or look for a new failure to fix (step 1). + 3. Your fix was effective, but some new failure arose. Return to step 1 with the new failure list. + diff --git a/vendor/github.com/golang/dep/docs/glossary.md b/vendor/github.com/golang/dep/docs/glossary.md new file mode 100644 index 00000000..0cb3aab9 --- /dev/null +++ b/vendor/github.com/golang/dep/docs/glossary.md @@ -0,0 +1,139 @@ +--- +id: glossary +title: Glossary +--- + +dep uses some specialized terminology. Learn about it here! + +* [Atom](#atom) +* [Cache lock](#cache-lock) +* [Constraint](#constraint) +* [Current Project](#current-project) +* [Deducible](#deducible) +* [Deduction](#deduction) +* [Direct Dependency](#direct-dependency) +* [External Import](#external-import) +* [GPS](#gps) +* [Local cache](#local-cache) +* [Lock](#lock) +* [Manifest](#manifest) +* [Metadata Service](#metadata-service) +* [Override](#override) +* [Project](#project) +* [Project Root](#project-root) +* [Solver](#solver) +* [Source](#source) +* [Source Root](#source-root) +* [Sync](#sync) +* [Transitive Dependency](#transitive-dependency) + +--- + +### Atom + +Atoms are a source at a particular version. In practice, this means a two-tuple of [project root](#project-root) and version, e.g. `github.com/foo/bar@master`. Atoms are primarily internal to the [solver](#solver), and the term is rarely used elsewhere. + +### Cache lock + +Also "cache lock file." A file, named `sm.lock`, used to ensure only a single dep process operates on the [local cache](#local-cache) at a time, as it is unsafe in dep's current design for multiple processes to access the local cache. + +### Constraint + +Constraints have both a narrow and a looser meaning. The narrow sense refers to a [`[[constraint]]`](Gopkg.toml.md#constraint) stanza in `Gopkg.toml`. However, in some contexts, the word may be used more loosely to refer to the idea of applying rules and requirements to dependency management in general. + +### Current Project + +The project on which dep is operating - writing its `Gopkg.lock` and populating its `vendor` directory. + +Also called the "root project." + +### Deducible + +A shorthand way of referring to whether or not import path [deduction](#deduction) will return successfully for a given import path. "Undeducible" is also often used, to refer to an import path for which deduction fails. + +### Deduction + +Deduction is the process of determining the subset of an import path that corresponds to a source root. Some patterns are known a priori (static); others must be discovered via network requests (dynamic). See the reference on [import path deduction](deduction.md) for specifics. + +### Direct Dependency + +A project's direct dependencies are those that it _imports_ from one or more of its packages, or includes in its [`required`](Gopkg.toml.md#required) list in `Gopkg.toml`. + + If each letter in `A -> B -> C -> D` represents a distinct project containing only a single package, and `->` indicates an import statement, then `B` is `A`'s direct dependency, whereas `C` and `D` are [transitive dependencies](#transitive-dependency) of `A`. + +Dep only incorporates the `required` rules from the [current project's](#current-project) `Gopkg.toml`. Therefore, if `=>` represents `required` rather than a standard import, and `A -> B => C`, then `C` is a direct dependency of `B` _only_ when `B` is the current project. Because the `B`-to-`C` link does not exist when `A` is the current project, then `C` won't actually be in the graph at all. + +### External Import + +An `import` statement that points to a package in a project other than the one in which it originates. For example, an `import` in package `github.com/foo/bar` will be considered an external import if it points to anything _other_ than stdlib or `github.com/foo/bar/*`. + +### GPS + +Stands for "Go packaging solver", it is [a subtree of library-style packages within dep](https://godoc.org/github.com/golang/dep/gps), and is the engine around which dep is built. Most commonly referred to as "gps." + +### Local cache + +dep maintains its own, pristine set of upstream sources (so, generally, git repository clones). This is kept separate from `$GOPATH/src` so that there is no obligation to maintain disk state within `$GOPATH`, as dep frequently needs to change disk state in order to do its work. + +By default, the local cache lives at `$GOPATH/pkg/dep`. If you have multiple `$GOPATH` entries, dep will use whichever is the logical parent of the process' working directory. Alternatively, the location can be forced via the `DEPCACHEDIR` environment variable. + +### Lock + +A generic term, used across many language package managers, for the kind of information dep keeps in a `Gopkg.lock` file. + +### Manifest + +A generic term, used across many language package managers, for the kind of information dep keeps in a `Gopkg.toml` file. + +### Metadata Service + +An HTTP service that, when it receives an HTTP request containing a `go-get=1` in the query string, treats interprets the path portion of the request as an import path, and responds by embedding data in HTML `` tags that indicate the type and URL of of the underlying source root. This is the server-side component of dynamic [deduction](#deduction). + +The behavior of metadata services is defined in the [Go documentation on remote import paths](https://golang.org/cmd/go/#hdr-Remote_import_paths). + +Variously referenced as "HTTP metadata service", "`go-get` HTTP metadata service", "`go-get` service", etc. + +### Override + +An override is a [`[[override]]`](Gopkg.toml.md#override) stanza in `Gopkg.toml`. + +### Project + +A project is a tree of Go packages. Projects cannot be nested. See [Project Root](#project-root) for more information about how the root of the tree is determined. + +### Project Root + +The root import path for a project. A project root is defined as: + +* For the current project, the location of the `Gopkg.toml` file defines the project root +* For dependencies, the root of the network [source](#source) (VCS repository) is treated as the project root + +These are generally one and the same, though not always. When using dep inside a monorepo, multiple `Gopkg.toml` files may exist at subpaths for discrete projects, designating each of those import paths as Project Roots. This works fine when working directly on those projects. If, however, any project not in the repository seeks to import the monorepo, dep will treat the monorepo's as one big Project, with the root directory being the Project Root; it will disregard any and all `Gopkg.toml` files in subdirectories. + +This may also be referred to as the "import root" or "root import path." + +### Solver + +"The solver" is a reference to the domain-specific SAT solver contained in [gps](#gps). More detail can be found on its [reference page](the-solver.md). + +### Source + +The remote entities that hold versioned code. Sources are specifically the entity containing the code, not any particular version of thecode itself. + +"Source" is used in lieu of "VCS" because Go package management tools will soon learn to use more than just VCS systems. + +### Source Root + +The portion of an import path that corresponds to the network location of a source. This is similar to [Project Root](#project-root), but refers strictly to the second, network-oriented definition. + +### Sync + +Dep's interaction model is based around the idea of maintaining a well-defined relationship between your project's import statements and `Gopkg.toml`, and your project's `Gopkg.lock` - keeping them "in sync". When the `Gopkg.lock` has more or fewer entries than are necessary, or entries that are incompatible with constraint rules established in `Gopkg.toml`, your project is "out of sync". + +This concept is explored in detail on [the ensure mechanics reference page](ensure-mechanics.md#staying-in-sync). + +### Transitive Dependency + +A project's transitive dependencies are those dependencies that it does not import itself, but are imported by one of its dependencies. + +If each letter in `A -> B -> C -> D` represents a distinct project containing only a single package, and `->` indicates an import statement, then `C` and `D` are `A`'s transitive dependencies, whereas `B` is a [direct dependency](#transitive-dependency) of `A`. \ No newline at end of file diff --git a/vendor/github.com/golang/dep/docs/installation.md b/vendor/github.com/golang/dep/docs/installation.md new file mode 100644 index 00000000..75171815 --- /dev/null +++ b/vendor/github.com/golang/dep/docs/installation.md @@ -0,0 +1,19 @@ +--- +title: Installation +--- + +It is strongly recommended that you use a released version of dep. While tip is never purposefully broken, its stability is not guaranteed. + +Pre-compiled binaries are available on the [releases](https://github.com/golang/dep/releases) page. On MacOS, you can also install or upgrade to the latest released version with Homebrew: + +```sh +$ brew install dep +$ brew upgrade dep +``` + +If you want to hack on dep, you can install via `go get`: + +```sh +go get -u github.com/golang/dep/cmd/dep +``` +Note that dep requires a functioning Go workspace and GOPATH. If you're unfamiliar with Go workspaces and GOPATH, have a look at [the language documentation](https://golang.org/doc/code.html#Organization) and get your local workspace set up. Dep's model could lead to being able to work without GOPATH, but we're not there yet. \ No newline at end of file diff --git a/vendor/github.com/golang/dep/docs/introduction.md b/vendor/github.com/golang/dep/docs/introduction.md new file mode 100644 index 00000000..0367ebd5 --- /dev/null +++ b/vendor/github.com/golang/dep/docs/introduction.md @@ -0,0 +1,11 @@ +--- +id: introduction +title: Getting Started +--- + + +Welcome! This is documentation for dep, the "official experiment" dependency management tool for the Go language. Dep is a tool intended primarily for use by developers, to support the work of actually writing and shipping code. It is _not_ intended for end users who are installing Go software - that's what `go get` does. + +This site has both guides and reference documents. The guides are practical explanations of how to actually do things with dep, whereas the reference material provides deeper dives on specific topics. Of particular note is the [glossary](glossary.md) - if you're unfamiliar with terminology used in this documentation, make sure to check there! + +After [installing dep](installation.md), if you're using it for the first time, check out [Creating a New Project](new-project.md). Or, if you have an existing Go project that you want to convert to dep, [Migrating to Dep](migrating.md) is probably the place to start. \ No newline at end of file diff --git a/vendor/github.com/golang/dep/docs/migrating.md b/vendor/github.com/golang/dep/docs/migrating.md new file mode 100644 index 00000000..c48843b7 --- /dev/null +++ b/vendor/github.com/golang/dep/docs/migrating.md @@ -0,0 +1,103 @@ +--- +title: Migrating to Dep +--- + +Ideally, migrating an existing Go project to dep is straightforward: + +```bash +$ cd $GOPATH/src/path/to/project/root +$ dep init +``` + +For many projects, this will just work. `dep init` will make educated guesses about what versions to use for your dependencies, generate sane `Gopkg.toml`, `Gopkg.lock`, and `vendor/`, and if your tests pass and builds work, then you're probably done. (If so, congratulations! You should check out [Daily Dep](daily-dep.md) next.) + +The migration process is still difficult for some projects. If you're trying dep for the first time, this can be particularly frustrating, as you're trying to simultaneously learn how to use dep, and how your project *should* be managed in dep. The good news is, `dep init` is usually the big difficulty hump; once you're over it, things get much easier. + +The goal of this guide is to provide enough information for you to reason about what's happening during `dep init`, so that you can at least understand what class of problems you're encountering, and what steps you might take to address them. To that end, we'll start with an overview of what `dep init` is doing. + +> Note: the first run of `dep init` can take quite a long time, as dep is creating fresh clones of all your dependencies into a special location, `$GOPATH/pkg/dep/sources/`. This is necessary for dep's normal operations, and is largely a one-time cost. + +## `dep init` mechanics + +When migrating existing projects, the primary goal of `dep init` is to automate as much of the work of creating a `Gopkg.toml` as possible. This is necessarily a heuristic goal, as dep may not have a 1:1 correspondence for everything you may have done before. As such, it's important to only expect that `dep init`'s automated migrations are operating on a best-effort basis. + +The behavior of `dep init` varies depending on what's in your existing codebase, and the flags that are passed to it. However, it always proceeds in two phases: + +1. *Inference phase:* Infer, from various sources, rules and hints about which versions of dependencies to use. +2. *Solving phase:* Work out a solution that is acceptable under dep's model, while incorporating the above inferences as much as possible. + +### The Inference Phase + +The inference phase is where `dep init`'s behavior varies. By default, `dep init` will look in your codebase for metadata files from [other Go package management tools that it understands](https://github.com/golang/dep/tree/master/internal/importers), and attempt to automatically migrate the data in these files into concepts that make sense in a dep. Depending on the tool and the particular values dep finds, metadata from the tool may be treated as either: + +* A hint: information that dep will try to honor in the solving phase, but will discard if it cannot find a solution that respects the hint. +* A rule: information that must obeyed in the solving phase, and will ultimately appear in `Gopkg.toml` as a `[[constraint]]`. If the solving phase cannot find a solution that satisfies the rules, it will fail with an informative message. + +There are three circumstances that can lead dep not to make any tool-based inferences: + +- Your project doesn't use a package management tool +- dep doesn't yet support the tool you use yet +- You tell it not to, by running `dep init -skip-tools` + +After tool-based inference is complete, dep will normally proceed to the solving phase. However, if the user passes the `-gopath` flag, dep will first try to fill in any holes in the inferences drawn from tool metadata by checking the current project's containing GOPATH. Only hints are gleaned from GOPATH, and they will never supersede inferences from tool metadata. If you want to put GOPATH fully in charge, pass both flags: `dep init -skip-tools -gopath`. + +Once dep has compiled its set of inferences, it proceeds to solving. + +### The Solving Phase + +Once the inference phase is completed, the set of rules and hints dep has assembled will be passed to its [solver](solver.md) to work out a transitively complete depgraph, which will ultimately be recorded as the `Gopkg.lock`. This is the same solving process used by `dep ensure`, and completing it successfully means that dep has found a combination of dependency versions that respects all inferred rules, and as many inferred hints as possible. If solving succeeds, then the hard work is done; most of what remains is writing out `Gopkg.toml`, `Gopkg.lock`, and `vendor/`. + +The solver returns a solution, which itself is just [a representation](https://godoc.org/github.com/golang/dep/gps#Solution) of [the data stored in a `Gopkg.lock`](https://godoc.org/github.com/golang/dep#Lock): a transitively-complete, reproducible snapshot of the entire dependency graph. Writing out the `Gopkg.lock` from a solution is little more than a copy-and-encode operation, and writing `vendor/` is a matter of placing each project listed in the solution into its appropriate place, at the designated revision. This is exactly the same as `dep ensure`'s behavior. + +`Gopkg.toml` is a little different. There's no guarantee that rules were inferred for all (or even any) of your project's dependencies, but we still want to populate `Gopkg.toml` with sane values. So, for any dependency for which a rule was not inferred, dep inspects the solution to see what version was ultimately selected, and creates a constraint based on that: + +* If a branch, like `master`, was picked in the solution, then `branch: "master"` will appear in `Gopkg.toml`. +* If a semantic version-compliant version was selected, like `v1.2.0`, then that will be specified as a minimum version: `version: "v1.2.0"`. +* If only a raw revision was selected, nothing will be put in `Gopkg.toml`. While dep does allow `revision: "…"` constraints in `Gopkg.toml`, use of them is considered an antipattern, so dep does not create them automatically in order to avoid implicitly encouraging their use. + +## Dealing with failures + +First and foremost, make sure that you're running `dep init` with the `-v` flag. That will provide a lot more information. + +`dep init`, like dep in general, has both hard and soft failure modes. Hard failures result in the process hanging or aborting entirely, without anything being written to disk. Soft failures may or may not include warnings, but do ultimately write out a `Gopkg.toml`, `Gopkg.lock`, and `vendor/` - just, not the ones you wanted. Before we dig into those, though, let's set some context. + +While dep contributors have invested enormous effort into creating automated migration paths into dep, these paths will always best-effort and imprecise. It's simply not always possible to convert from other tools or GOPATH with full fidelity. dep is an opinionated tool, with a correspondingly opinionated model, and that model does sometimes fundamentally differ from that of other tools. Sometimes these model mismatches result in hard failures, sometimes soft, and sometimes there's no harm at all. + +Because these are deep assumptions, their symptoms can be varied and surprising. Keeping these assumptions in mind could save you some hair-pulling later on. + +- dep does not allow nested `vendor/` directories; it flattens all dependencies to the topmost `vendor/` directory, at the root of your project. This is foundational to dep's model, and cannot be disabled. +- dep wholly controls `vendor`, and will blow away any manual changes or additions made to it that deviate from the version of an upstream source dep selects. +- dep requires that all packages from a given project/repository be at the same version. +- dep generally does not care about what's on your GOPATH; it deals exclusively with projects sourced from remote network locations. (Hint inference is the only exception to this; once solving begins, GOPATH - and any custom changes you've made to code therein - is ignored.) +- dep generally prefers semantic versioning-tagged releases to branches (when not given any additional rules). This is a significant shift from the "default branch" model of `go get` and some other tools. It can result in dep making surprising choices for dependencies for which it could not infer a rule. +- dep assumes that all generated code exists, and has been committed to the source. + +A small number of projects that have reported being unable, thus far, to find a reasonable way of adapting to these requirements. If you can't figure out how to make your project fit, please file an issue - while dep necessarily cannot accommodate every single existing approach, it is dep's goal is define rules to which all Go projects can reasonably adapt. + +### Hard failures + +All of the hard failure modes are covered extensively in the reference on [failure modes](failure-modes.md). + +Because the solver, and all its possible failures, are the same for `dep init` as for `dep ensure`, there's a separate section for understanding and dealing with them: [dealing with solving failures](failure-modes.md#solving-failures). It can be trickier with `dep init`, however, as many remediations require tweaking `Gopkg.toml`. + +Unfortunately, `dep init` does not write out a partial `Gopkg.toml` when it fails. This is a known, critical problem, and [we have an open issue (help wanted!)](https://github.com/golang/dep/issues/909). + +In the meantime, if the particular errors you are encountering do entail `Gopkg.toml` tweaks, you unfortunately may have to do without the automation of `dep init`: create an empty [`Gopkg.toml`](Gopkg.toml.md), and populate it with rules by hand. Before resorting to that, make sure you've run `dep init` with various combinations of the inferencing flags (`-skip-tools` and `-gopath`) to see if they can at least give you something to start from. + +### Soft failures + +Soft failures are cases where `dep init` appears to exit cleanly, but a subsequent `go build` or `go test` fails. Dep's soft failures are usually more drastically than subtly wrong - e.g., an explosion of type errors when you try to build, because a wildly incorrect version for some dependency got selected. + +If you do encounter problems like this, `dep status` is your first diagnostic step; it will report what versions were selected for all your dependencies. It may be clear which dependencies are a problem simply from your building or testing error messages. If not, compare the `dep status` list against the versions recorded by your previous tool to find the differences. + +Once you've identified the problematic dependenc(ies), the next step is exerting appropriate controls over them via `Gopkg.toml`. + +For each of the following items, assume that you should run `dep ensure` after making the suggested change. If that fails, consult [dealing with solving failures](). + +* If the wrong `[[constraint]]` was inferred for one of your direct dependencies, change it. Then, file an issue against dep (please!) - while `dep init` may choose to omit a constraint, converting one incorrectly is considered a bug. +* If one of your transitive dependencies is at the wrong version, define an `[[override]]` on it to force it to the version you need. + * If the version you need is a specific git commit, it's preferable to instead manually change the `revision` to the desired hash in `Gopkg.lock` for that project, then drop the `version` or `branch` fields (if any). +* If one of your direct dependencies is at the wrong version and there's no `[[constraint]]` on it in `Gopkg.toml` already, then define an appropriate one. + * As with the transitive dependencies, if the version you need is a specific git commit, prefer doing that manually in `Gopkg.lock`. + +Hopefully this information is enough to get you through your project's migration to dep. If not, please feel free to file an issue, or join us in [#vendor on the Gopher's slack](https://gophers.slack.com/messages/C0M5YP9LN) for help! \ No newline at end of file diff --git a/vendor/github.com/golang/dep/docs/new-project.md b/vendor/github.com/golang/dep/docs/new-project.md new file mode 100644 index 00000000..63beb68b --- /dev/null +++ b/vendor/github.com/golang/dep/docs/new-project.md @@ -0,0 +1,37 @@ +--- +title: Creating a New Project +--- + +Once you have [dep installed](installation.md), we need to pick a root directory for our project. This is primarily about picking the right root import path, and corresponding directory beneath `$GOPATH/src`, at which to situate your project. There are four basic possibilities: + +1. A project that is now or eventually may be shared with or imported by other projects/people. In this case, pick the import path corresponding to the VCS root of its intended network location, e.g., `$GOPATH/src/github.com/golang/dep`. +2. An entirely local project - one that you have no intention of pushing to a central server (like GitHub). In this case, any subdirectory beneath `$GOPATH/src` will do. +3. A project that needs to live within a large repository, such as a company monorepo. This may be possible, but gets more complicated. (Unfortunately, no docs on this yet - coming soon!) +4. Treat the entire GOPATH as a single project, where `$GOPATH/src` is the root. dep [does not currently support this](https://github.com/golang/dep/issues/417) - it needs a non-empty import path to treat as the root of your project's import namespace. + +We'll assume the first case, as it's the most common. Create and move into the directory: + +```bash +$ mkdir -p $GOPATH/src/github.com/me/example +$ cd $GOPATH/src/github.com/me/example +``` + +Now, we'll initialize the project: + +```bash +$ dep init +$ ls +Gopkg.toml Gopkg.lock vendor/ +``` + +In a new project like this one, both files and the `vendor` directory will be effectively empty. + +This would also be a good time to set up a version control, such as [git](https://git-scm.com/). While dep in no way requires version control for your project, it can make inspecting the changes made by normal dep operations easier. Plus, it's basically best practice #1 of modern software development! + +At this point, our project is initialized, and we're ready to start writing code. You can open up a `.go` file in an editor and start hacking away. Or, if you already know some projects you'll need, you can pre-populate your `vendor` directory with them: + +```bash +$ dep ensure -add github.com/foo/bar github.com/baz/quux +``` + +Now you're ready to move on to [Daily Dep](daily-dep.md)! \ No newline at end of file diff --git a/vendor/github.com/golang/dep/docs/the-solver.md b/vendor/github.com/golang/dep/docs/the-solver.md new file mode 100644 index 00000000..25854dbd --- /dev/null +++ b/vendor/github.com/golang/dep/docs/the-solver.md @@ -0,0 +1,84 @@ +--- +title: The Solver +--- + +At the heart of dep is a constraint solving engine - a [CDCL]()-style [SMT]() solver, tailored specifically to the domain of Go package management. It lives in the `github.com/golang/dep/gps` package, and is where the work of determining a valid, transitively complete dependency graph (aka, the contents of `Gopkg.lock`) is performed. + +This page will eventually detail the solver's mechanics, but in the meantime, there are [docs for an older version of the solver](https://github.com/sdboyer/gps/wiki/gps-for-Contributors) that are still accurate enough to provide a rough picture of its behavior. + +## Solving invariants + +The solver guarantees certain invariants in every complete solution it returns. Each invariant is explored in detail later, but they can be summarized as follows: + +* All rules specified in activated `[[constraint]]` stanzas in both the current project and dependency projects will be satisfied, unless superseded by a `[[override]]` stanza in the current project. +* For all import paths pointing into a given project, the version of the project selected will contain "valid" Go packages in the corresponding directory. +* If an [import comment](https://golang.org/cmd/go/#hdr-Import_path_checking) is specified by a package, any import paths addressing that package will be of the form specified in the comment. +* For any given import path, all instances of that import path will use the exact same casing. + +The solver is an iterative algorithm, working its way project-by-project through possible dependency graphs. In order to select a project, it must first prove that, to the best of its current knowledge, all of the above conditions are met. When the solver cannot find a solution, failure is defined in terms of a project's version's inability to meet one of the above criteria. + +### `[[constraint]]` rules + +As described in the `Gopkg.toml` docs, each [`[[constraint]]`](gopkg.toml.md#constraint) stanza is associated with a single project, and each stanza can contain both [a version rule](Gopkg.toml.md#version-rules) and a [source rule](Gopkg.toml.md#source). For any given project `P`, all dependers on `P` whose constraint rules are "activated" must express mutually compatible rules. That means: + +* For version rules, all activated constraints on `P` must [intersect](https://en.wikipedia.org/wiki/Intersection_(set_theory)), and and there must be at least one published version must exist in the intersecting space. Intersection varies depending on version rule type: + * For `revision` and `branch`, it must be a string-literal match. + * For `version`, if the string is not a valid semantic version, then it must be a string-literal match. + * For `version` that are valid semantic version ranges, intersection is standard set-theoretic intersection of the possible values in each range range. Semantic versions without ranges are treated as a single element set (e.g., `version = "=v1.0.0"`) for intersection purposes. +* For `source` rules, all projects with a particular dependency must either express a string-equal `source` value, or have no `source` value at all. This allows one dependency to specify an alternate `source`, and other dependencies to play along if they have no opinion. (NB: this play-along behavior may be removed in a future version.) + +If the current project's `Gopkg.toml` has an [`[[override]]`](gopkg.toml.md#override) on `P`, then all `[[constraint]]` declarations (including any in the current project) are ignored, obviating the possibility of conflict. + +#### Activated constraints + +Just because a `[[constraint]]` on `P` appears in `D`'s `Gopkg.toml` doesn't necessarily mean the constraint on `P` is considered active. A package in `P` must be imported by a package in `D` - and, if `D` is not the current project, then one of its packages importing `P` must also be imported. + +Given the following dependency graph, where `C` is the current project: + +``` +C -> D +C -> P +D/subpkg -> P +``` + +Even though `C` imports `D`, because `D/subpkg` is not reachable through `C`'s imports, any `[[constraint]]` declared in `D`'s `Gopkg.toml`' on `P` will not be active. + +The reasoning behind this behavior is explained further [in this gist](https://gist.github.com/sdboyer/b0813bf2b9dba58a335a85092085472f). + +### Package validity + +dep does only superficial validaton of code in packages, but it does do some. For a package to be considered valid, three things must be true: + +* There must be at least one `.go` file. +* No errors are reported from [`parser.ParseFile()`](https://golang.org/pkg/go/parser/#ParseFile) when called with [`parser.ImportsOnly|parser.ParseComments`](https://golang.org/pkg/go/parser/#Mode) on any file in the package directory. + +- The package must not contain any [local imports](https://golang.org/pkg/go/build/#IsLocalImport). Note: this disallows something the standard toolchain compiler does allow, which is normally means dep must support it. However, local imports are already strongly discouraged in the toolchain, and skipping them allows dep to avoid [dot-dot hell](https://9p.io/sys/doc/lexnames.html). + +If any of the above are untrue, the code in a package is considered malformed, and cannot be used in a solution. + +It is not immediately disqualifying for a project to merely contain some invalid packages; they must be imported for the invariant to be broken. So, if `P/invalid` is a subpackage with invalid code in it, then it is still acceptable if `C -> P`. However, internal imports within `P` are also considered, so this import chain: + +``` +C -> P +P -> invalid +``` + +will result in an error, as `C` imports a package that will necessarily result in the import of an invalid package. + +### Import comments + +Go 1.4 introduced [import comments](https://golang.org/cmd/go/#hdr-Import_path_checking), which allow a package to specify the import path that must be used when addressing it. For example, `import "github.com/golang/net/dict"` would point to a valid package, but because [it uses an import comment](https://github.com/golang/net/blob/42fe2e1c20de1054d3d30f82cc9fb5b41e2e3767/dict/dict.go#L7) to enforce that it must be imported as `golang.org/x/net/dict`, dep would reject any project attempting to import it directly through its github address. + +Because most projects are consistent about their import comment use over time, this issue typically only occurs when adding a new dependency or attempting to revive an older project. + +> Note: dep does not currently enforce this rule, but [it needs to](https://github.com/golang/dep/issues/902). + +**Remediation:** change the code by fixing the offending import paths. If the offending import paths are not in the current project and you don't directly control the dependency, you'll have to fork and fix it yourself, then use `source` to point to your fork. + +### Import path casing + +The standard Go toolchain compiler [does not](https://github.com/golang/go/issues/4773) [allow](https://github.com/golang/go/issues/20264) import paths that vary only in case to exist in the same build. For example, either of `github.com/sirupsen/logrus` or `github.com/Sirupsen/logrus` are fine (GitHub treats usernames as case-insensitive) individually, but they cannot exist in the same project. + +The solver keeps track of the accepted case variant for each import path it's processed. Any subsequent projects it sees that introduces a case-only variation for a known import path will be rejected. + +**Remediation:** Pick a casing variation (all lowercase is usually the right answer), and enforce it universally across the depgraph. As it has to be respected in all dependencies, as well, this may necessitate pull requests and possibly forking of dependencies, if you don't control them directly. \ No newline at end of file diff --git a/vendor/github.com/golang/dep/gps/_testdata/badrepo/README.md b/vendor/github.com/golang/dep/gps/_testdata/badrepo/README.md new file mode 100644 index 00000000..14232159 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/badrepo/README.md @@ -0,0 +1,5 @@ +### Test Data + +This directory contains artifacts that represent malformed repo archives. Its purpose is to ensure `dep` can recover from such corrupted repositories in specific test scenarios. + +- `corrupt_dot_git_directory.tar`: is a repo with a corrupt `.git` directory. Dep can put a directory in such malformed state when a user hits `Ctrl+C` in the middle of a `dep init` process or others. `TestNewCtxRepoRecovery` uses this file to ensure recovery. diff --git a/vendor/github.com/golang/dep/gps/_testdata/badrepo/corrupt_dot_git_directory.tar b/vendor/github.com/golang/dep/gps/_testdata/badrepo/corrupt_dot_git_directory.tar new file mode 100644 index 0000000000000000000000000000000000000000..7a847318395c721a0bee0e7f189c00792e05caef GIT binary patch literal 459 zcmV;+0W|&}iwFSt=OtMH1MQd1YTPgofPKzW4D2Co=-RR++feAK&{N+aBRem$=rG3Gx`uPvH0P34;#au;eO}#XO9G}L8Fs=X6&+;C>%m0MD=n(H*)LrmQ|Ev+L zsVg4*i@GYwe+u%#j2h!6fffEaC;v&v3%vcNc0OhXc)9O75fWf)(dq(EXo=#lM$_cu8P||ElHWKLro>f4uL&75>|%BL69P@PCxMyMM>O zp!+`w%m1JHzU!yGiZe!7k4A_;`{&J5|4d}S;!Ni;Z`}U|4#q?8w%YW{!FG$jQ+9q> zw!~Ij96seC>d{WQ*uYmah8Dh)9_BUla5BDw%grT7t6+!2phoZV5cvfyNH|)YGYt&r ze18vSgwG#Ba|Igv9#3XGzzL^*54S2r9}xH8ln2zIhhyWrVql0gQ%w zoFFI+6$q14=lb^_L*uLb8s*LW@Z;jO*P9>+f*=TjAP9mW2!bF|@)IDBK#%|^002q9 B>=^(6 literal 0 HcmV?d00001 diff --git a/vendor/github.com/golang/dep/gps/_testdata/cmd/echosleep/echosleep.go b/vendor/github.com/golang/dep/gps/_testdata/cmd/echosleep/echosleep.go new file mode 100644 index 00000000..70de0e50 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/cmd/echosleep/echosleep.go @@ -0,0 +1,21 @@ +// Copyright 2017 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 main + +import ( + "flag" + "fmt" + "time" +) + +func main() { + n := flag.Int("n", 1, "number of iterations before stopping") + flag.Parse() + + for i := 0; i < *n; i++ { + fmt.Println("foo") + time.Sleep(time.Duration(i) * 250 * time.Millisecond) + } +} diff --git a/vendor/github.com/golang/dep/gps/_testdata/cmd/stdout_stderr/stdout_stderr.go b/vendor/github.com/golang/dep/gps/_testdata/cmd/stdout_stderr/stdout_stderr.go new file mode 100644 index 00000000..806d1891 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/cmd/stdout_stderr/stdout_stderr.go @@ -0,0 +1,14 @@ +// Copyright 2017 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 main + +import ( + "os" +) + +func main() { + os.Stdout.WriteString("stdout") + os.Stderr.WriteString("stderr") +} diff --git a/vendor/github.com/golang/dep/gps/_testdata/digest/github.com/alice/match/match.go b/vendor/github.com/golang/dep/gps/_testdata/digest/github.com/alice/match/match.go new file mode 100644 index 00000000..ab5f8752 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/digest/github.com/alice/match/match.go @@ -0,0 +1,5 @@ +// Copyright 2017 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 match diff --git a/vendor/github.com/golang/dep/gps/_testdata/digest/github.com/alice/mismatch/mismatch.go b/vendor/github.com/golang/dep/gps/_testdata/digest/github.com/alice/mismatch/mismatch.go new file mode 100644 index 00000000..1ace4e76 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/digest/github.com/alice/mismatch/mismatch.go @@ -0,0 +1,5 @@ +// Copyright 2017 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 mismatch diff --git a/vendor/github.com/golang/dep/gps/_testdata/digest/github.com/alice/notInLock/notInLock.go b/vendor/github.com/golang/dep/gps/_testdata/digest/github.com/alice/notInLock/notInLock.go new file mode 100644 index 00000000..5b2914de --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/digest/github.com/alice/notInLock/notInLock.go @@ -0,0 +1,5 @@ +// Copyright 2017 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 notInLock diff --git a/vendor/github.com/golang/dep/gps/_testdata/digest/github.com/bob/emptyDigest/emptyDigest.go b/vendor/github.com/golang/dep/gps/_testdata/digest/github.com/bob/emptyDigest/emptyDigest.go new file mode 100644 index 00000000..2d6067bc --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/digest/github.com/bob/emptyDigest/emptyDigest.go @@ -0,0 +1,5 @@ +// Copyright 2017 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 emptyDigest diff --git a/vendor/github.com/golang/dep/gps/_testdata/digest/github.com/bob/match/match.go b/vendor/github.com/golang/dep/gps/_testdata/digest/github.com/bob/match/match.go new file mode 100644 index 00000000..ab5f8752 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/digest/github.com/bob/match/match.go @@ -0,0 +1,5 @@ +// Copyright 2017 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 match diff --git a/vendor/github.com/golang/dep/gps/_testdata/digest/launchpad.net/match/match.go b/vendor/github.com/golang/dep/gps/_testdata/digest/launchpad.net/match/match.go new file mode 100644 index 00000000..ab5f8752 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/digest/launchpad.net/match/match.go @@ -0,0 +1,5 @@ +// Copyright 2017 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 match diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/bad/bad.go b/vendor/github.com/golang/dep/gps/_testdata/src/bad/bad.go new file mode 100644 index 00000000..dfc89bee --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/bad/bad.go @@ -0,0 +1,6 @@ +// Copyright 2017 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. + +// This ill-formed Go source file is here to ensure the tool is robust +// against bad packages in the workspace. diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/buildtag/invalid.go b/vendor/github.com/golang/dep/gps/_testdata/src/buildtag/invalid.go new file mode 100644 index 00000000..20c43146 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/buildtag/invalid.go @@ -0,0 +1,17 @@ +// Copyright 2017 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. + +// Hello +// Not a valid +build ignore +// No Really + +package buildtag + +import ( + "sort" +) + +var ( + _ = sort.Strings +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/canon_confl/a.go b/vendor/github.com/golang/dep/gps/_testdata/src/canon_confl/a.go new file mode 100644 index 00000000..98153451 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/canon_confl/a.go @@ -0,0 +1,9 @@ +// Copyright 2017 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 canonical // import "vanity1" + +var ( + A = "A" +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/canon_confl/b.go b/vendor/github.com/golang/dep/gps/_testdata/src/canon_confl/b.go new file mode 100644 index 00000000..b8b706bb --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/canon_confl/b.go @@ -0,0 +1,9 @@ +// Copyright 2017 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 canonical // import "vanity2" + +var ( + B = "B" +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/canonical/main.go b/vendor/github.com/golang/dep/gps/_testdata/src/canonical/main.go new file mode 100644 index 00000000..4fe31ce3 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/canonical/main.go @@ -0,0 +1,9 @@ +// Copyright 2017 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 pkg // import "canonical" + +var ( + A = "A" +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/canonical/sub/sub.go b/vendor/github.com/golang/dep/gps/_testdata/src/canonical/sub/sub.go new file mode 100644 index 00000000..783186df --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/canonical/sub/sub.go @@ -0,0 +1,5 @@ +// Copyright 2017 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 sub // import "canonical/subpackage" diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/cycle/a.go b/vendor/github.com/golang/dep/gps/_testdata/src/cycle/a.go new file mode 100644 index 00000000..443db779 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/cycle/a.go @@ -0,0 +1,16 @@ +// Copyright 2017 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 cycle + +import ( + "cycle/one" + + "github.com/golang/dep/gps" +) + +var ( + A = gps.Solve + B = one.A +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/cycle/one/a.go b/vendor/github.com/golang/dep/gps/_testdata/src/cycle/one/a.go new file mode 100644 index 00000000..055d98db --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/cycle/one/a.go @@ -0,0 +1,16 @@ +// Copyright 2017 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 one + +import ( + "cycle/two" + + "github.com/golang/dep/gps" +) + +var ( + A = gps.Solve + B = two.A +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/cycle/two/a.go b/vendor/github.com/golang/dep/gps/_testdata/src/cycle/two/a.go new file mode 100644 index 00000000..a44003ad --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/cycle/two/a.go @@ -0,0 +1,16 @@ +// Copyright 2017 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 two + +import ( + "cycle" + + "github.com/golang/dep/gps" +) + +var ( + A = gps.Solve + B = cycle.A +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/disallow/a.go b/vendor/github.com/golang/dep/gps/_testdata/src/disallow/a.go new file mode 100644 index 00000000..99dd6f35 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/disallow/a.go @@ -0,0 +1,18 @@ +// Copyright 2017 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 disallow + +import ( + "disallow/testdata" + "sort" + + "github.com/golang/dep/gps" +) + +var ( + _ = sort.Strings + _ = gps.Solve + _ = testdata.H +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/disallow/testdata/another.go b/vendor/github.com/golang/dep/gps/_testdata/src/disallow/testdata/another.go new file mode 100644 index 00000000..f2d60b88 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/disallow/testdata/another.go @@ -0,0 +1,11 @@ +// Copyright 2017 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 testdata + +import "hash" + +var ( + H = hash.Hash +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/dotgodir/.go/.gitkeep b/vendor/github.com/golang/dep/gps/_testdata/src/dotgodir/.go/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/dotgodir/.go/dot.go b/vendor/github.com/golang/dep/gps/_testdata/src/dotgodir/.go/dot.go new file mode 100644 index 00000000..bb51d69f --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/dotgodir/.go/dot.go @@ -0,0 +1,7 @@ +// Copyright 2017 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 dot + +// nothing to see here diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/dotgodir/.m1p/a.go b/vendor/github.com/golang/dep/gps/_testdata/src/dotgodir/.m1p/a.go new file mode 100644 index 00000000..6a88c120 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/dotgodir/.m1p/a.go @@ -0,0 +1,16 @@ +// Copyright 2017 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 m1p + +import ( + "sort" + + "github.com/golang/dep/gps" +) + +var ( + _ = sort.Strings + S = gps.Solve +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/dotgodir/.m1p/b.go b/vendor/github.com/golang/dep/gps/_testdata/src/dotgodir/.m1p/b.go new file mode 100644 index 00000000..de4eb0b5 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/dotgodir/.m1p/b.go @@ -0,0 +1,15 @@ +// Copyright 2017 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 m1p + +import ( + "os" + "sort" +) + +var ( + _ = sort.Strings + _ = os.PathSeparator +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/dotgodir/foo.go/.gitkeep b/vendor/github.com/golang/dep/gps/_testdata/src/dotgodir/foo.go/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/dotgodir/foo.go/foo.go b/vendor/github.com/golang/dep/gps/_testdata/src/dotgodir/foo.go/foo.go new file mode 100644 index 00000000..1de8b0ab --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/dotgodir/foo.go/foo.go @@ -0,0 +1,12 @@ +// Copyright 2017 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 foo + +import "sort" + +var _ = sort.Strings + +// yes, this is dumb, don't use ".go" in your directory names +// See https://github.com/golang/dep/issues/550 for more information diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/doublenest/a.go b/vendor/github.com/golang/dep/gps/_testdata/src/doublenest/a.go new file mode 100644 index 00000000..fca9b43a --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/doublenest/a.go @@ -0,0 +1,16 @@ +// Copyright 2017 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 base + +import ( + "go/parser" + + "github.com/golang/dep/gps" +) + +var ( + _ = parser.ParseFile + _ = gps.Solve +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/doublenest/namemismatch/m1p/a.go b/vendor/github.com/golang/dep/gps/_testdata/src/doublenest/namemismatch/m1p/a.go new file mode 100644 index 00000000..78f859bb --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/doublenest/namemismatch/m1p/a.go @@ -0,0 +1,16 @@ +// Copyright 2017 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 m1p + +import ( + "sort" + + "github.com/golang/dep/gps" +) + +var ( + _ = sort.Strings + _ = gps.Solve +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/doublenest/namemismatch/m1p/b.go b/vendor/github.com/golang/dep/gps/_testdata/src/doublenest/namemismatch/m1p/b.go new file mode 100644 index 00000000..de4eb0b5 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/doublenest/namemismatch/m1p/b.go @@ -0,0 +1,15 @@ +// Copyright 2017 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 m1p + +import ( + "os" + "sort" +) + +var ( + _ = sort.Strings + _ = os.PathSeparator +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/doublenest/namemismatch/nm.go b/vendor/github.com/golang/dep/gps/_testdata/src/doublenest/namemismatch/nm.go new file mode 100644 index 00000000..6c4a42fc --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/doublenest/namemismatch/nm.go @@ -0,0 +1,16 @@ +// Copyright 2017 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 nm + +import ( + "os" + + "github.com/Masterminds/semver" +) + +var ( + V = os.FileInfo + _ = semver.Constraint +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/empty/.gitkeep b/vendor/github.com/golang/dep/gps/_testdata/src/empty/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/github.com/example/varied/locals.go b/vendor/github.com/golang/dep/gps/_testdata/src/github.com/example/varied/locals.go new file mode 100644 index 00000000..38dbe7aa --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/github.com/example/varied/locals.go @@ -0,0 +1,17 @@ +// Copyright 2017 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 main + +import ( + "github.com/example/varied/namemismatch" + "github.com/example/varied/otherpath" + "github.com/example/varied/simple" +) + +var ( + _ = simple.S + _ = nm.V + _ = otherpath.O +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/github.com/example/varied/m1p/a.go b/vendor/github.com/golang/dep/gps/_testdata/src/github.com/example/varied/m1p/a.go new file mode 100644 index 00000000..9fae843c --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/github.com/example/varied/m1p/a.go @@ -0,0 +1,16 @@ +// Copyright 2017 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 m1p + +import ( + "sort" + + "github.com/golang/dep/gps" +) + +var ( + M = sort.Strings + _ = gps.Solve +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/github.com/example/varied/m1p/b.go b/vendor/github.com/golang/dep/gps/_testdata/src/github.com/example/varied/m1p/b.go new file mode 100644 index 00000000..de4eb0b5 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/github.com/example/varied/m1p/b.go @@ -0,0 +1,15 @@ +// Copyright 2017 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 m1p + +import ( + "os" + "sort" +) + +var ( + _ = sort.Strings + _ = os.PathSeparator +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/github.com/example/varied/main.go b/vendor/github.com/golang/dep/gps/_testdata/src/github.com/example/varied/main.go new file mode 100644 index 00000000..0812e3ca --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/github.com/example/varied/main.go @@ -0,0 +1,13 @@ +// Copyright 2017 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 main + +import ( + "net/http" +) + +var ( + _ = http.Client +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/github.com/example/varied/namemismatch/nm.go b/vendor/github.com/golang/dep/gps/_testdata/src/github.com/example/varied/namemismatch/nm.go new file mode 100644 index 00000000..6c4a42fc --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/github.com/example/varied/namemismatch/nm.go @@ -0,0 +1,16 @@ +// Copyright 2017 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 nm + +import ( + "os" + + "github.com/Masterminds/semver" +) + +var ( + V = os.FileInfo + _ = semver.Constraint +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/github.com/example/varied/otherpath/otherpath_test.go b/vendor/github.com/golang/dep/gps/_testdata/src/github.com/example/varied/otherpath/otherpath_test.go new file mode 100644 index 00000000..734c91ad --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/github.com/example/varied/otherpath/otherpath_test.go @@ -0,0 +1,9 @@ +// Copyright 2017 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 otherpath + +import "github.com/example/varied/m1p" + +var O = m1p.M diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/github.com/example/varied/simple/another/another.go b/vendor/github.com/golang/dep/gps/_testdata/src/github.com/example/varied/simple/another/another.go new file mode 100644 index 00000000..c453a8ea --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/github.com/example/varied/simple/another/another.go @@ -0,0 +1,11 @@ +// Copyright 2017 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 another + +import "hash" + +var ( + H = hash.Hash +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/github.com/example/varied/simple/another/another_test.go b/vendor/github.com/golang/dep/gps/_testdata/src/github.com/example/varied/simple/another/another_test.go new file mode 100644 index 00000000..e8713913 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/github.com/example/varied/simple/another/another_test.go @@ -0,0 +1,11 @@ +// Copyright 2017 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 another + +import "encoding/binary" + +var ( + _ = binary.PutVarint +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/github.com/example/varied/simple/another/locals.go b/vendor/github.com/golang/dep/gps/_testdata/src/github.com/example/varied/simple/another/locals.go new file mode 100644 index 00000000..6995b925 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/github.com/example/varied/simple/another/locals.go @@ -0,0 +1,9 @@ +// Copyright 2017 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 another + +import "github.com/example/varied/m1p" + +var _ = m1p.M diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/github.com/example/varied/simple/locals.go b/vendor/github.com/golang/dep/gps/_testdata/src/github.com/example/varied/simple/locals.go new file mode 100644 index 00000000..c5a0ae3a --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/github.com/example/varied/simple/locals.go @@ -0,0 +1,11 @@ +// Copyright 2017 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 simple + +import "github.com/example/varied/simple/another" + +var ( + _ = another.H +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/github.com/example/varied/simple/simple.go b/vendor/github.com/golang/dep/gps/_testdata/src/github.com/example/varied/simple/simple.go new file mode 100644 index 00000000..6dfd0494 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/github.com/example/varied/simple/simple.go @@ -0,0 +1,16 @@ +// Copyright 2017 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 simple + +import ( + "go/parser" + + "github.com/golang/dep/gps" +) + +var ( + _ = parser.ParseFile + S = gps.Prepare +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/igmain/a.go b/vendor/github.com/golang/dep/gps/_testdata/src/igmain/a.go new file mode 100644 index 00000000..f772b57e --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/igmain/a.go @@ -0,0 +1,16 @@ +// Copyright 2017 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 simple + +import ( + "sort" + + "github.com/golang/dep/gps" +) + +var ( + _ = sort.Strings + _ = gps.Solve +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/igmain/igmain.go b/vendor/github.com/golang/dep/gps/_testdata/src/igmain/igmain.go new file mode 100644 index 00000000..eaab15bd --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/igmain/igmain.go @@ -0,0 +1,11 @@ +// Copyright 2017 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. + +// +build ignore + +package main + +import "unicode" + +var _ = unicode.In diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/igmainfirst/igmain.go b/vendor/github.com/golang/dep/gps/_testdata/src/igmainfirst/igmain.go new file mode 100644 index 00000000..eaab15bd --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/igmainfirst/igmain.go @@ -0,0 +1,11 @@ +// Copyright 2017 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. + +// +build ignore + +package main + +import "unicode" + +var _ = unicode.In diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/igmainfirst/z.go b/vendor/github.com/golang/dep/gps/_testdata/src/igmainfirst/z.go new file mode 100644 index 00000000..f772b57e --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/igmainfirst/z.go @@ -0,0 +1,16 @@ +// Copyright 2017 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 simple + +import ( + "sort" + + "github.com/golang/dep/gps" +) + +var ( + _ = sort.Strings + _ = gps.Solve +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/igmainlong/a.go b/vendor/github.com/golang/dep/gps/_testdata/src/igmainlong/a.go new file mode 100644 index 00000000..f772b57e --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/igmainlong/a.go @@ -0,0 +1,16 @@ +// Copyright 2017 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 simple + +import ( + "sort" + + "github.com/golang/dep/gps" +) + +var ( + _ = sort.Strings + _ = gps.Solve +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/igmainlong/igmain.go b/vendor/github.com/golang/dep/gps/_testdata/src/igmainlong/igmain.go new file mode 100644 index 00000000..849ceab4 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/igmainlong/igmain.go @@ -0,0 +1,13 @@ +// Copyright 2017 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. + +// Another comment, which the parser should ignore and still see builds tags + +// +build ignore + +package main + +import "unicode" + +var _ = unicode.In diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/igmaint/a.go b/vendor/github.com/golang/dep/gps/_testdata/src/igmaint/a.go new file mode 100644 index 00000000..f772b57e --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/igmaint/a.go @@ -0,0 +1,16 @@ +// Copyright 2017 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 simple + +import ( + "sort" + + "github.com/golang/dep/gps" +) + +var ( + _ = sort.Strings + _ = gps.Solve +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/igmaint/igmain.go b/vendor/github.com/golang/dep/gps/_testdata/src/igmaint/igmain.go new file mode 100644 index 00000000..eaab15bd --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/igmaint/igmain.go @@ -0,0 +1,11 @@ +// Copyright 2017 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. + +// +build ignore + +package main + +import "unicode" + +var _ = unicode.In diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/igmaint/t_test.go b/vendor/github.com/golang/dep/gps/_testdata/src/igmaint/t_test.go new file mode 100644 index 00000000..f29d3313 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/igmaint/t_test.go @@ -0,0 +1,15 @@ +// Copyright 2017 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 simple + +import ( + "math/rand" + "strconv" +) + +var ( + _ = rand.Int() + _ = strconv.Unquote +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/m1p/a.go b/vendor/github.com/golang/dep/gps/_testdata/src/m1p/a.go new file mode 100644 index 00000000..78f859bb --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/m1p/a.go @@ -0,0 +1,16 @@ +// Copyright 2017 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 m1p + +import ( + "sort" + + "github.com/golang/dep/gps" +) + +var ( + _ = sort.Strings + _ = gps.Solve +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/m1p/b.go b/vendor/github.com/golang/dep/gps/_testdata/src/m1p/b.go new file mode 100644 index 00000000..de4eb0b5 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/m1p/b.go @@ -0,0 +1,15 @@ +// Copyright 2017 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 m1p + +import ( + "os" + "sort" +) + +var ( + _ = sort.Strings + _ = os.PathSeparator +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/missing/a.go b/vendor/github.com/golang/dep/gps/_testdata/src/missing/a.go new file mode 100644 index 00000000..619b1bc5 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/missing/a.go @@ -0,0 +1,19 @@ +// Copyright 2017 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 simple + +import ( + "sort" + + "missing/missing" + + "github.com/golang/dep/gps" +) + +var ( + _ = sort.Strings + _ = gps.Solve + _ = missing.Foo +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/missing/m1p/a.go b/vendor/github.com/golang/dep/gps/_testdata/src/missing/m1p/a.go new file mode 100644 index 00000000..78f859bb --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/missing/m1p/a.go @@ -0,0 +1,16 @@ +// Copyright 2017 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 m1p + +import ( + "sort" + + "github.com/golang/dep/gps" +) + +var ( + _ = sort.Strings + _ = gps.Solve +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/missing/m1p/b.go b/vendor/github.com/golang/dep/gps/_testdata/src/missing/m1p/b.go new file mode 100644 index 00000000..de4eb0b5 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/missing/m1p/b.go @@ -0,0 +1,15 @@ +// Copyright 2017 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 m1p + +import ( + "os" + "sort" +) + +var ( + _ = sort.Strings + _ = os.PathSeparator +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/nest/a.go b/vendor/github.com/golang/dep/gps/_testdata/src/nest/a.go new file mode 100644 index 00000000..f772b57e --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/nest/a.go @@ -0,0 +1,16 @@ +// Copyright 2017 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 simple + +import ( + "sort" + + "github.com/golang/dep/gps" +) + +var ( + _ = sort.Strings + _ = gps.Solve +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/nest/m1p/a.go b/vendor/github.com/golang/dep/gps/_testdata/src/nest/m1p/a.go new file mode 100644 index 00000000..78f859bb --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/nest/m1p/a.go @@ -0,0 +1,16 @@ +// Copyright 2017 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 m1p + +import ( + "sort" + + "github.com/golang/dep/gps" +) + +var ( + _ = sort.Strings + _ = gps.Solve +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/nest/m1p/b.go b/vendor/github.com/golang/dep/gps/_testdata/src/nest/m1p/b.go new file mode 100644 index 00000000..de4eb0b5 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/nest/m1p/b.go @@ -0,0 +1,15 @@ +// Copyright 2017 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 m1p + +import ( + "os" + "sort" +) + +var ( + _ = sort.Strings + _ = os.PathSeparator +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/relimport/a.go b/vendor/github.com/golang/dep/gps/_testdata/src/relimport/a.go new file mode 100644 index 00000000..ccfa73a9 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/relimport/a.go @@ -0,0 +1,13 @@ +// Copyright 2017 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 relimport + +import ( + "sort" +) + +var ( + A = sort.Strings +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/relimport/dot/a.go b/vendor/github.com/golang/dep/gps/_testdata/src/relimport/dot/a.go new file mode 100644 index 00000000..a1dd2853 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/relimport/dot/a.go @@ -0,0 +1,14 @@ +// Copyright 2017 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 dot + +import ( + "." + "sort" +) + +var ( + A = sort.Strings +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/relimport/dotdot/a.go b/vendor/github.com/golang/dep/gps/_testdata/src/relimport/dotdot/a.go new file mode 100644 index 00000000..6cfc99f2 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/relimport/dotdot/a.go @@ -0,0 +1,13 @@ +// Copyright 2017 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 dotdot + +import ( + relimport ".." +) + +var ( + A = relimport.A +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/relimport/dotdotslash/a.go b/vendor/github.com/golang/dep/gps/_testdata/src/relimport/dotdotslash/a.go new file mode 100644 index 00000000..b4caf2fa --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/relimport/dotdotslash/a.go @@ -0,0 +1,13 @@ +// Copyright 2017 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 dotslash + +import ( + "../github.com/golang/dep/gps" +) + +var ( + A = gps.Solver +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/relimport/dotslash/a.go b/vendor/github.com/golang/dep/gps/_testdata/src/relimport/dotslash/a.go new file mode 100644 index 00000000..b904565d --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/relimport/dotslash/a.go @@ -0,0 +1,13 @@ +// Copyright 2017 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 dotslash + +import ( + "./simple" +) + +var ( + A = simple.A +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/ren/m1p/a.go b/vendor/github.com/golang/dep/gps/_testdata/src/ren/m1p/a.go new file mode 100644 index 00000000..78f859bb --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/ren/m1p/a.go @@ -0,0 +1,16 @@ +// Copyright 2017 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 m1p + +import ( + "sort" + + "github.com/golang/dep/gps" +) + +var ( + _ = sort.Strings + _ = gps.Solve +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/ren/m1p/b.go b/vendor/github.com/golang/dep/gps/_testdata/src/ren/m1p/b.go new file mode 100644 index 00000000..de4eb0b5 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/ren/m1p/b.go @@ -0,0 +1,15 @@ +// Copyright 2017 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 m1p + +import ( + "os" + "sort" +) + +var ( + _ = sort.Strings + _ = os.PathSeparator +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/ren/simple/a.go b/vendor/github.com/golang/dep/gps/_testdata/src/ren/simple/a.go new file mode 100644 index 00000000..f772b57e --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/ren/simple/a.go @@ -0,0 +1,16 @@ +// Copyright 2017 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 simple + +import ( + "sort" + + "github.com/golang/dep/gps" +) + +var ( + _ = sort.Strings + _ = gps.Solve +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/simple/a.go b/vendor/github.com/golang/dep/gps/_testdata/src/simple/a.go new file mode 100644 index 00000000..f772b57e --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/simple/a.go @@ -0,0 +1,16 @@ +// Copyright 2017 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 simple + +import ( + "sort" + + "github.com/golang/dep/gps" +) + +var ( + _ = sort.Strings + _ = gps.Solve +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/simpleallt/a.go b/vendor/github.com/golang/dep/gps/_testdata/src/simpleallt/a.go new file mode 100644 index 00000000..f772b57e --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/simpleallt/a.go @@ -0,0 +1,16 @@ +// Copyright 2017 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 simple + +import ( + "sort" + + "github.com/golang/dep/gps" +) + +var ( + _ = sort.Strings + _ = gps.Solve +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/simpleallt/a_test.go b/vendor/github.com/golang/dep/gps/_testdata/src/simpleallt/a_test.go new file mode 100644 index 00000000..b8a754a7 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/simpleallt/a_test.go @@ -0,0 +1,15 @@ +// Copyright 2017 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 simple_test + +import ( + "sort" + "strconv" +) + +var ( + _ = sort.Strings + _ = strconv.Unquote +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/simpleallt/t_test.go b/vendor/github.com/golang/dep/gps/_testdata/src/simpleallt/t_test.go new file mode 100644 index 00000000..f29d3313 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/simpleallt/t_test.go @@ -0,0 +1,15 @@ +// Copyright 2017 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 simple + +import ( + "math/rand" + "strconv" +) + +var ( + _ = rand.Int() + _ = strconv.Unquote +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/simplet/a.go b/vendor/github.com/golang/dep/gps/_testdata/src/simplet/a.go new file mode 100644 index 00000000..f772b57e --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/simplet/a.go @@ -0,0 +1,16 @@ +// Copyright 2017 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 simple + +import ( + "sort" + + "github.com/golang/dep/gps" +) + +var ( + _ = sort.Strings + _ = gps.Solve +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/simplet/t_test.go b/vendor/github.com/golang/dep/gps/_testdata/src/simplet/t_test.go new file mode 100644 index 00000000..f29d3313 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/simplet/t_test.go @@ -0,0 +1,15 @@ +// Copyright 2017 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 simple + +import ( + "math/rand" + "strconv" +) + +var ( + _ = rand.Int() + _ = strconv.Unquote +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/simplext/a.go b/vendor/github.com/golang/dep/gps/_testdata/src/simplext/a.go new file mode 100644 index 00000000..f772b57e --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/simplext/a.go @@ -0,0 +1,16 @@ +// Copyright 2017 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 simple + +import ( + "sort" + + "github.com/golang/dep/gps" +) + +var ( + _ = sort.Strings + _ = gps.Solve +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/simplext/a_test.go b/vendor/github.com/golang/dep/gps/_testdata/src/simplext/a_test.go new file mode 100644 index 00000000..b8a754a7 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/simplext/a_test.go @@ -0,0 +1,15 @@ +// Copyright 2017 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 simple_test + +import ( + "sort" + "strconv" +) + +var ( + _ = sort.Strings + _ = strconv.Unquote +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/skip_/_a.go b/vendor/github.com/golang/dep/gps/_testdata/src/skip_/_a.go new file mode 100644 index 00000000..b53a03b5 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/skip_/_a.go @@ -0,0 +1,15 @@ +// Copyright 2017 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 skip + +import ( + "bytes" + "sort" +) + +var ( + _ = sort.Strings + _ = bytes.Buffer +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/skip_/a.go b/vendor/github.com/golang/dep/gps/_testdata/src/skip_/a.go new file mode 100644 index 00000000..fc99a11d --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/skip_/a.go @@ -0,0 +1,16 @@ +// Copyright 2017 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 skip + +import ( + "sort" + + "github.com/golang/dep/gps" +) + +var ( + _ = sort.Strings + _ = gps.Solve +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/t/t_test.go b/vendor/github.com/golang/dep/gps/_testdata/src/t/t_test.go new file mode 100644 index 00000000..f29d3313 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/t/t_test.go @@ -0,0 +1,15 @@ +// Copyright 2017 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 simple + +import ( + "math/rand" + "strconv" +) + +var ( + _ = rand.Int() + _ = strconv.Unquote +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/twopkgs/a.go b/vendor/github.com/golang/dep/gps/_testdata/src/twopkgs/a.go new file mode 100644 index 00000000..f772b57e --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/twopkgs/a.go @@ -0,0 +1,16 @@ +// Copyright 2017 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 simple + +import ( + "sort" + + "github.com/golang/dep/gps" +) + +var ( + _ = sort.Strings + _ = gps.Solve +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/twopkgs/b.go b/vendor/github.com/golang/dep/gps/_testdata/src/twopkgs/b.go new file mode 100644 index 00000000..de4eb0b5 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/twopkgs/b.go @@ -0,0 +1,15 @@ +// Copyright 2017 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 m1p + +import ( + "os" + "sort" +) + +var ( + _ = sort.Strings + _ = os.PathSeparator +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/varied/locals.go b/vendor/github.com/golang/dep/gps/_testdata/src/varied/locals.go new file mode 100644 index 00000000..d9dcdec1 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/varied/locals.go @@ -0,0 +1,17 @@ +// Copyright 2017 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 main + +import ( + "varied/namemismatch" + "varied/otherpath" + "varied/simple" +) + +var ( + _ = simple.S + _ = nm.V + _ = otherpath.O +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/varied/m1p/a.go b/vendor/github.com/golang/dep/gps/_testdata/src/varied/m1p/a.go new file mode 100644 index 00000000..9fae843c --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/varied/m1p/a.go @@ -0,0 +1,16 @@ +// Copyright 2017 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 m1p + +import ( + "sort" + + "github.com/golang/dep/gps" +) + +var ( + M = sort.Strings + _ = gps.Solve +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/varied/m1p/b.go b/vendor/github.com/golang/dep/gps/_testdata/src/varied/m1p/b.go new file mode 100644 index 00000000..de4eb0b5 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/varied/m1p/b.go @@ -0,0 +1,15 @@ +// Copyright 2017 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 m1p + +import ( + "os" + "sort" +) + +var ( + _ = sort.Strings + _ = os.PathSeparator +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/varied/main.go b/vendor/github.com/golang/dep/gps/_testdata/src/varied/main.go new file mode 100644 index 00000000..0812e3ca --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/varied/main.go @@ -0,0 +1,13 @@ +// Copyright 2017 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 main + +import ( + "net/http" +) + +var ( + _ = http.Client +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/varied/namemismatch/nm.go b/vendor/github.com/golang/dep/gps/_testdata/src/varied/namemismatch/nm.go new file mode 100644 index 00000000..6c4a42fc --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/varied/namemismatch/nm.go @@ -0,0 +1,16 @@ +// Copyright 2017 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 nm + +import ( + "os" + + "github.com/Masterminds/semver" +) + +var ( + V = os.FileInfo + _ = semver.Constraint +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/varied/otherpath/otherpath_test.go b/vendor/github.com/golang/dep/gps/_testdata/src/varied/otherpath/otherpath_test.go new file mode 100644 index 00000000..0ccf3d03 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/varied/otherpath/otherpath_test.go @@ -0,0 +1,9 @@ +// Copyright 2017 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 otherpath + +import "varied/m1p" + +var O = m1p.M diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/varied/simple/another/another.go b/vendor/github.com/golang/dep/gps/_testdata/src/varied/simple/another/another.go new file mode 100644 index 00000000..c453a8ea --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/varied/simple/another/another.go @@ -0,0 +1,11 @@ +// Copyright 2017 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 another + +import "hash" + +var ( + H = hash.Hash +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/varied/simple/another/another_test.go b/vendor/github.com/golang/dep/gps/_testdata/src/varied/simple/another/another_test.go new file mode 100644 index 00000000..e8713913 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/varied/simple/another/another_test.go @@ -0,0 +1,11 @@ +// Copyright 2017 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 another + +import "encoding/binary" + +var ( + _ = binary.PutVarint +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/varied/simple/another/locals.go b/vendor/github.com/golang/dep/gps/_testdata/src/varied/simple/another/locals.go new file mode 100644 index 00000000..befa5c68 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/varied/simple/another/locals.go @@ -0,0 +1,9 @@ +// Copyright 2017 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 another + +import "varied/m1p" + +var _ = m1p.M diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/varied/simple/locals.go b/vendor/github.com/golang/dep/gps/_testdata/src/varied/simple/locals.go new file mode 100644 index 00000000..3f592af7 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/varied/simple/locals.go @@ -0,0 +1,11 @@ +// Copyright 2017 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 simple + +import "varied/simple/another" + +var ( + _ = another.H +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/varied/simple/simple.go b/vendor/github.com/golang/dep/gps/_testdata/src/varied/simple/simple.go new file mode 100644 index 00000000..6dfd0494 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/varied/simple/simple.go @@ -0,0 +1,16 @@ +// Copyright 2017 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 simple + +import ( + "go/parser" + + "github.com/golang/dep/gps" +) + +var ( + _ = parser.ParseFile + S = gps.Prepare +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/varied_hidden/.onlyfromtests/a.go b/vendor/github.com/golang/dep/gps/_testdata/src/varied_hidden/.onlyfromtests/a.go new file mode 100644 index 00000000..676dbae1 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/varied_hidden/.onlyfromtests/a.go @@ -0,0 +1,18 @@ +// Copyright 2017 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 onlyfromtests + +import ( + "sort" + + _ "varied/_secondorder" + + "github.com/golang/dep/gps" +) + +var ( + M = sort.Strings + _ = gps.Solve +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/varied_hidden/.onlyfromtests/b.go b/vendor/github.com/golang/dep/gps/_testdata/src/varied_hidden/.onlyfromtests/b.go new file mode 100644 index 00000000..fa353864 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/varied_hidden/.onlyfromtests/b.go @@ -0,0 +1,15 @@ +// Copyright 2017 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 onlyfromtests + +import ( + "os" + "sort" +) + +var ( + _ = sort.Strings + _ = os.PathSeparator +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/varied_hidden/_frommain/a.go b/vendor/github.com/golang/dep/gps/_testdata/src/varied_hidden/_frommain/a.go new file mode 100644 index 00000000..67634a85 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/varied_hidden/_frommain/a.go @@ -0,0 +1,16 @@ +// Copyright 2017 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 frommain + +import ( + "sort" + + "github.com/golang/dep/gps" +) + +var ( + M = sort.Strings + _ = gps.Solve +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/varied_hidden/_never/a.go b/vendor/github.com/golang/dep/gps/_testdata/src/varied_hidden/_never/a.go new file mode 100644 index 00000000..f2bdd5b0 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/varied_hidden/_never/a.go @@ -0,0 +1,16 @@ +// Copyright 2017 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 never + +import ( + "sort" + + "github.com/golang/dep/gps" +) + +var ( + M = sort.Strings + _ = gps.Solve +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/varied_hidden/_secondorder/secondorder.go b/vendor/github.com/golang/dep/gps/_testdata/src/varied_hidden/_secondorder/secondorder.go new file mode 100644 index 00000000..4224b81e --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/varied_hidden/_secondorder/secondorder.go @@ -0,0 +1,11 @@ +// Copyright 2017 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 secondorder + +import "hash" + +var ( + H = hash.Hash +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/varied_hidden/always/always_test.go b/vendor/github.com/golang/dep/gps/_testdata/src/varied_hidden/always/always_test.go new file mode 100644 index 00000000..043805b4 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/varied_hidden/always/always_test.go @@ -0,0 +1,7 @@ +// Copyright 2017 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 always + +import _ "varied/.onlyfromtests" diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/varied_hidden/dotdotslash/a.go b/vendor/github.com/golang/dep/gps/_testdata/src/varied_hidden/dotdotslash/a.go new file mode 100644 index 00000000..b4caf2fa --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/varied_hidden/dotdotslash/a.go @@ -0,0 +1,13 @@ +// Copyright 2017 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 dotslash + +import ( + "../github.com/golang/dep/gps" +) + +var ( + A = gps.Solver +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/varied_hidden/locals.go b/vendor/github.com/golang/dep/gps/_testdata/src/varied_hidden/locals.go new file mode 100644 index 00000000..4afaa8bf --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/varied_hidden/locals.go @@ -0,0 +1,14 @@ +// Copyright 2017 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 main + +import ( + _ "varied/_frommain" + "varied/simple" +) + +var ( + _ = simple.S +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/varied_hidden/main.go b/vendor/github.com/golang/dep/gps/_testdata/src/varied_hidden/main.go new file mode 100644 index 00000000..0812e3ca --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/varied_hidden/main.go @@ -0,0 +1,13 @@ +// Copyright 2017 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 main + +import ( + "net/http" +) + +var ( + _ = http.Client +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/varied_hidden/simple/locals.go b/vendor/github.com/golang/dep/gps/_testdata/src/varied_hidden/simple/locals.go new file mode 100644 index 00000000..7d682c4e --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/varied_hidden/simple/locals.go @@ -0,0 +1,11 @@ +// Copyright 2017 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 simple + +import "varied/simple/testdata" + +var ( + _ = testdata.H +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/varied_hidden/simple/simple.go b/vendor/github.com/golang/dep/gps/_testdata/src/varied_hidden/simple/simple.go new file mode 100644 index 00000000..6dfd0494 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/varied_hidden/simple/simple.go @@ -0,0 +1,16 @@ +// Copyright 2017 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 simple + +import ( + "go/parser" + + "github.com/golang/dep/gps" +) + +var ( + _ = parser.ParseFile + S = gps.Prepare +) diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/varied_hidden/simple/testdata/another.go b/vendor/github.com/golang/dep/gps/_testdata/src/varied_hidden/simple/testdata/another.go new file mode 100644 index 00000000..02eab2a2 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/varied_hidden/simple/testdata/another.go @@ -0,0 +1,7 @@ +// Copyright 2017 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 testdata + +import _ "varied/dotdotslash" diff --git a/vendor/github.com/golang/dep/gps/_testdata/src/xt/a_test.go b/vendor/github.com/golang/dep/gps/_testdata/src/xt/a_test.go new file mode 100644 index 00000000..b8a754a7 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/_testdata/src/xt/a_test.go @@ -0,0 +1,15 @@ +// Copyright 2017 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 simple_test + +import ( + "sort" + "strconv" +) + +var ( + _ = sort.Strings + _ = strconv.Unquote +) diff --git a/vendor/github.com/golang/dep/gps/bridge.go b/vendor/github.com/golang/dep/gps/bridge.go new file mode 100644 index 00000000..819d0ae5 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/bridge.go @@ -0,0 +1,223 @@ +// Copyright 2017 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 gps + +import ( + "fmt" + "os" + "path/filepath" + "sync/atomic" + + "github.com/golang/dep/gps/pkgtree" +) + +// sourceBridge is an adapter to SourceManagers that tailor operations for a +// single solve run. +type sourceBridge interface { + // sourceBridge includes all the methods in the SourceManager interface except + // for Release(). + SourceExists(ProjectIdentifier) (bool, error) + SyncSourceFor(ProjectIdentifier) error + RevisionPresentIn(ProjectIdentifier, Revision) (bool, error) + ListPackages(ProjectIdentifier, Version) (pkgtree.PackageTree, error) + GetManifestAndLock(ProjectIdentifier, Version, ProjectAnalyzer) (Manifest, Lock, error) + ExportProject(ProjectIdentifier, Version, string) error + DeduceProjectRoot(ip string) (ProjectRoot, error) + + //sourceExists(ProjectIdentifier) (bool, error) + //syncSourceFor(ProjectIdentifier) error + listVersions(ProjectIdentifier) ([]Version, error) + //revisionPresentIn(ProjectIdentifier, Revision) (bool, error) + //listPackages(ProjectIdentifier, Version) (pkgtree.PackageTree, error) + //getManifestAndLock(ProjectIdentifier, Version, ProjectAnalyzer) (Manifest, Lock, error) + //exportProject(ProjectIdentifier, Version, string) error + //deduceProjectRoot(ip string) (ProjectRoot, error) + verifyRootDir(path string) error + vendorCodeExists(ProjectIdentifier) (bool, error) + breakLock() +} + +// bridge is an adapter around a proper SourceManager. It provides localized +// caching that's tailored to the requirements of a particular solve run. +// +// Finally, it provides authoritative version/constraint operations, ensuring +// that any possible approach to a match - even those not literally encoded in +// the inputs - is achieved. +type bridge struct { + // The underlying, adapted-to SourceManager + sm SourceManager + + // The solver which we're assisting. + // + // The link between solver and bridge is circular, which is typically a bit + // awkward, but the bridge needs access to so many of the input arguments + // held by the solver that it ends up being easier and saner to do this. + s *solver + + // Map of project root name to their available version list. This cache is + // layered on top of the proper SourceManager's cache; the only difference + // is that this keeps the versions sorted in the direction required by the + // current solve run. + vlists map[ProjectIdentifier][]Version + + // Indicates whether lock breaking has already been run + lockbroken int32 + + // Whether to sort version lists for downgrade. + down bool + + // The cancellation context provided to the solver. Threading it through the + // various solver methods is needlessly verbose so long as we maintain the + // lifetime guarantees that a solver can only be run once. + // TODO(sdboyer) uncomment this and thread it through SourceManager methods + //ctx context.Context +} + +// mkBridge creates a bridge +func mkBridge(s *solver, sm SourceManager, down bool) *bridge { + return &bridge{ + sm: sm, + s: s, + down: down, + vlists: make(map[ProjectIdentifier][]Version), + } +} + +func (b *bridge) GetManifestAndLock(id ProjectIdentifier, v Version, an ProjectAnalyzer) (Manifest, Lock, error) { + if b.s.rd.isRoot(id.ProjectRoot) { + return b.s.rd.rm, b.s.rd.rl, nil + } + + b.s.mtr.push("b-gmal") + m, l, e := b.sm.GetManifestAndLock(id, v, an) + b.s.mtr.pop() + return m, l, e +} + +func (b *bridge) listVersions(id ProjectIdentifier) ([]Version, error) { + if vl, exists := b.vlists[id]; exists { + return vl, nil + } + + b.s.mtr.push("b-list-versions") + pvl, err := b.sm.ListVersions(id) + if err != nil { + b.s.mtr.pop() + return nil, err + } + + vl := hidePair(pvl) + if b.down { + SortForDowngrade(vl) + } else { + SortForUpgrade(vl) + } + + b.vlists[id] = vl + b.s.mtr.pop() + return vl, nil +} + +func (b *bridge) RevisionPresentIn(id ProjectIdentifier, r Revision) (bool, error) { + b.s.mtr.push("b-rev-present-in") + i, e := b.sm.RevisionPresentIn(id, r) + b.s.mtr.pop() + return i, e +} + +func (b *bridge) SourceExists(id ProjectIdentifier) (bool, error) { + b.s.mtr.push("b-source-exists") + i, e := b.sm.SourceExists(id) + b.s.mtr.pop() + return i, e +} + +func (b *bridge) vendorCodeExists(id ProjectIdentifier) (bool, error) { + fi, err := os.Stat(filepath.Join(b.s.rd.dir, "vendor", string(id.ProjectRoot))) + if err != nil { + return false, err + } else if fi.IsDir() { + return true, nil + } + + return false, nil +} + +// listPackages lists all the packages contained within the given project at a +// particular version. +// +// The root project is handled separately, as the source manager isn't +// responsible for that code. +func (b *bridge) ListPackages(id ProjectIdentifier, v Version) (pkgtree.PackageTree, error) { + if b.s.rd.isRoot(id.ProjectRoot) { + return b.s.rd.rpt, nil + } + + b.s.mtr.push("b-list-pkgs") + pt, err := b.sm.ListPackages(id, v) + b.s.mtr.pop() + return pt, err +} + +func (b *bridge) ExportProject(id ProjectIdentifier, v Version, path string) error { + panic("bridge should never be used to ExportProject") +} + +// verifyRoot ensures that the provided path to the project root is in good +// working condition. This check is made only once, at the beginning of a solve +// run. +func (b *bridge) verifyRootDir(path string) error { + if fi, err := os.Stat(path); err != nil { + return badOptsFailure(fmt.Sprintf("could not read project root (%s): %s", path, err)) + } else if !fi.IsDir() { + return badOptsFailure(fmt.Sprintf("project root (%s) is a file, not a directory", path)) + } + + return nil +} + +func (b *bridge) DeduceProjectRoot(ip string) (ProjectRoot, error) { + b.s.mtr.push("b-deduce-proj-root") + pr, e := b.sm.DeduceProjectRoot(ip) + b.s.mtr.pop() + return pr, e +} + +// breakLock is called when the solver has to break a version recorded in the +// lock file. It prefetches all the projects in the solver's lock, so that the +// information is already on hand if/when the solver needs it. +// +// Projects that have already been selected are skipped, as it's generally unlikely that the +// solver will have to backtrack through and fully populate their version queues. +func (b *bridge) breakLock() { + // No real conceivable circumstance in which multiple calls are made to + // this, but being that this is the entrance point to a bunch of async work, + // protect it with an atomic CAS in case things change in the future. + // + // We avoid using a sync.Once here, as there's no reason for other callers + // to block until completion. + if !atomic.CompareAndSwapInt32(&b.lockbroken, 0, 1) { + return + } + + for _, lp := range b.s.rd.rl.Projects() { + if _, is := b.s.sel.selected(lp.pi); !is { + pi, v := lp.pi, lp.Version() + go func() { + // Sync first + b.sm.SyncSourceFor(pi) + // Preload the package info for the locked version, too, as + // we're more likely to need that + b.sm.ListPackages(pi, v) + }() + } + } +} + +func (b *bridge) SyncSourceFor(id ProjectIdentifier) error { + // we don't track metrics here b/c this is often called in its own goroutine + // by the solver, and the metrics design is for wall time on a single thread + return b.sm.SyncSourceFor(id) +} diff --git a/vendor/github.com/golang/dep/gps/cmd.go b/vendor/github.com/golang/dep/gps/cmd.go new file mode 100644 index 00000000..1166cb9c --- /dev/null +++ b/vendor/github.com/golang/dep/gps/cmd.go @@ -0,0 +1,17 @@ +// Copyright 2017 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 gps + +func (c cmd) Args() []string { + return c.Cmd.Args +} + +func (c cmd) SetDir(dir string) { + c.Cmd.Dir = dir +} + +func (c cmd) SetEnv(env []string) { + c.Cmd.Env = env +} diff --git a/vendor/github.com/golang/dep/gps/cmd_unix.go b/vendor/github.com/golang/dep/gps/cmd_unix.go new file mode 100644 index 00000000..413f6b39 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/cmd_unix.go @@ -0,0 +1,82 @@ +// Copyright 2017 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. + +// +build !windows + +package gps + +import ( + "bytes" + "context" + "os" + "os/exec" + "syscall" + "time" + + "github.com/pkg/errors" +) + +type cmd struct { + // ctx is provided by the caller; SIGINT is sent when it is cancelled. + ctx context.Context + Cmd *exec.Cmd +} + +func commandContext(ctx context.Context, name string, arg ...string) cmd { + c := exec.Command(name, arg...) + + // Force subprocesses into their own process group, rather than being in the + // same process group as the dep process. Because Ctrl-C sent from a + // terminal will send the signal to the entire currently running process + // group, this allows us to directly manage the issuance of signals to + // subprocesses. + c.SysProcAttr = &syscall.SysProcAttr{ + Setpgid: true, + Pgid: 0, + } + + return cmd{ctx: ctx, Cmd: c} +} + +// CombinedOutput is like (*os/exec.Cmd).CombinedOutput except that it +// terminates subprocesses gently (via os.Interrupt), but resorts to Kill if +// the subprocess fails to exit after 1 minute. +func (c cmd) CombinedOutput() ([]byte, error) { + // Adapted from (*os/exec.Cmd).CombinedOutput + if c.Cmd.Stdout != nil { + return nil, errors.New("exec: Stdout already set") + } + if c.Cmd.Stderr != nil { + return nil, errors.New("exec: Stderr already set") + } + var b bytes.Buffer + c.Cmd.Stdout = &b + c.Cmd.Stderr = &b + if err := c.Cmd.Start(); err != nil { + return nil, err + } + + // Adapted from (*os/exec.Cmd).Start + waitDone := make(chan struct{}) + defer close(waitDone) + go func() { + select { + case <-c.ctx.Done(): + if err := c.Cmd.Process.Signal(os.Interrupt); err != nil { + // If an error comes back from attempting to signal, proceed + // immediately to hard kill. + _ = c.Cmd.Process.Kill() + } else { + defer time.AfterFunc(time.Minute, func() { + _ = c.Cmd.Process.Kill() + }).Stop() + <-waitDone + } + case <-waitDone: + } + }() + + err := c.Cmd.Wait() + return b.Bytes(), err +} diff --git a/vendor/github.com/golang/dep/gps/cmd_windows.go b/vendor/github.com/golang/dep/gps/cmd_windows.go new file mode 100644 index 00000000..ce1a0347 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/cmd_windows.go @@ -0,0 +1,18 @@ +// Copyright 2017 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 gps + +import ( + "context" + "os/exec" +) + +type cmd struct { + *exec.Cmd +} + +func commandContext(ctx context.Context, name string, arg ...string) cmd { + return cmd{Cmd: exec.CommandContext(ctx, name, arg...)} +} diff --git a/vendor/github.com/golang/dep/gps/constraint_test.go b/vendor/github.com/golang/dep/gps/constraint_test.go new file mode 100644 index 00000000..160feaac --- /dev/null +++ b/vendor/github.com/golang/dep/gps/constraint_test.go @@ -0,0 +1,1007 @@ +// Copyright 2017 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 gps + +import ( + "fmt" + "testing" + + "github.com/golang/dep/gps/internal/pb" + "github.com/golang/protobuf/proto" + "github.com/pkg/errors" +) + +// gu - helper func for stringifying what we assume is a VersionPair (otherwise +// will panic), but is given as a Constraint +func gu(v Constraint) string { + return fmt.Sprintf("%q at rev %q", v, v.(PairedVersion).Revision()) +} + +func TestBranchConstraintOps(t *testing.T) { + v1 := NewBranch("master").(branchVersion) + v2 := NewBranch("test").(branchVersion) + + if !v1.MatchesAny(any) { + t.Errorf("Branches should always match the any constraint") + } + if v1.Intersect(any) != v1 { + t.Errorf("Branches should always return self when intersecting the any constraint, but got %s", v1.Intersect(any)) + } + + if v1.MatchesAny(none) { + t.Errorf("Branches should never match the none constraint") + } + if v1.Intersect(none) != none { + t.Errorf("Branches should always return none when intersecting the none constraint, but got %s", v1.Intersect(none)) + } + + if v1.Matches(v2) { + t.Errorf("%s should not match %s", v1, v2) + } + + if v1.MatchesAny(v2) { + t.Errorf("%s should not allow any matches when combined with %s", v1, v2) + } + + if v1.Intersect(v2) != none { + t.Errorf("Intersection of %s with %s should result in empty set", v1, v2) + } + + // Add rev to one + snuffster := Revision("snuffleupagus") + v3 := v1.Pair(snuffster).(versionPair) + if v2.Matches(v3) { + t.Errorf("%s should not match %s", v2, gu(v3)) + } + if v3.Matches(v2) { + t.Errorf("%s should not match %s", gu(v3), v2) + } + + if v2.MatchesAny(v3) { + t.Errorf("%s should not allow any matches when combined with %s", v2, gu(v3)) + } + if v3.MatchesAny(v2) { + t.Errorf("%s should not allow any matches when combined with %s", v2, gu(v3)) + } + + if v2.Intersect(v3) != none { + t.Errorf("Intersection of %s with %s should result in empty set", v2, gu(v3)) + } + if v3.Intersect(v2) != none { + t.Errorf("Intersection of %s with %s should result in empty set", gu(v3), v2) + } + + // Add different rev to the other + v4 := v2.Pair(Revision("cookie monster")).(versionPair) + if v4.Matches(v3) { + t.Errorf("%s should not match %s", gu(v4), gu(v3)) + } + if v3.Matches(v4) { + t.Errorf("%s should not match %s", gu(v3), gu(v4)) + } + + if v4.MatchesAny(v3) { + t.Errorf("%s should not allow any matches when combined with %s", gu(v4), gu(v3)) + } + if v3.MatchesAny(v4) { + t.Errorf("%s should not allow any matches when combined with %s", gu(v4), gu(v3)) + } + + if v4.Intersect(v3) != none { + t.Errorf("Intersection of %s with %s should result in empty set", gu(v4), gu(v3)) + } + if v3.Intersect(v4) != none { + t.Errorf("Intersection of %s with %s should result in empty set", gu(v3), gu(v4)) + } + + // Now add same rev to different branches + v5 := v2.Pair(Revision("snuffleupagus")).(versionPair) + if !v5.Matches(v3) { + t.Errorf("%s should match %s", gu(v5), gu(v3)) + } + if !v3.Matches(v5) { + t.Errorf("%s should match %s", gu(v3), gu(v5)) + } + + if !v5.MatchesAny(v3) { + t.Errorf("%s should allow some matches when combined with %s", gu(v5), gu(v3)) + } + if !v3.MatchesAny(v5) { + t.Errorf("%s should allow some matches when combined with %s", gu(v5), gu(v3)) + } + + if v5.Intersect(v3) != snuffster { + t.Errorf("Intersection of %s with %s should return underlying rev", gu(v5), gu(v3)) + } + if v3.Intersect(v5) != snuffster { + t.Errorf("Intersection of %s with %s should return underlying rev", gu(v3), gu(v5)) + } + + // Set up for cross-type constraint ops + cookie := Revision("cookie monster") + o1 := NewVersion("master").(plainVersion) + o2 := NewVersion("1.0.0").(semVersion) + o3 := o1.Pair(cookie).(versionPair) + o4 := o2.Pair(cookie).(versionPair) + v6 := v1.Pair(cookie).(versionPair) + + if v1.Matches(o1) { + t.Errorf("%s (branch) should not match %s (version) across types", v1, o1) + } + + if v1.MatchesAny(o1) { + t.Errorf("%s (branch) should not allow any matches when combined with %s (version)", v1, o1) + } + + if v1.Intersect(o1) != none { + t.Errorf("Intersection of %s (branch) with %s (version) should result in empty set", v1, o1) + } + + if v1.Matches(o2) { + t.Errorf("%s (branch) should not match %s (semver) across types", v1, o2) + } + + if v1.MatchesAny(o2) { + t.Errorf("%s (branch) should not allow any matches when combined with %s (semver)", v1, o2) + } + + if v1.Intersect(o2) != none { + t.Errorf("Intersection of %s (branch) with %s (semver) should result in empty set", v1, o2) + } + + if v1.Matches(o3) { + t.Errorf("%s (branch) should not match %s (version) across types", v1, gu(o3)) + } + + if v1.MatchesAny(o3) { + t.Errorf("%s (branch) should not allow any matches when combined with %s (version)", v1, gu(o3)) + } + + if v1.Intersect(o3) != none { + t.Errorf("Intersection of %s (branch) with %s (version) should result in empty set", v1, gu(o3)) + } + + if v1.Matches(o4) { + t.Errorf("%s (branch) should not match %s (semver) across types", v1, gu(o4)) + } + + if v1.MatchesAny(o4) { + t.Errorf("%s (branch) should not allow any matches when combined with %s (semver)", v1, gu(o4)) + } + + if v1.Intersect(o4) != none { + t.Errorf("Intersection of %s (branch) with %s (semver) should result in empty set", v1, gu(o4)) + } + + if !v6.Matches(o3) { + t.Errorf("%s (branch) should match %s (version) across types due to shared rev", gu(v6), gu(o3)) + } + + if !v6.MatchesAny(o3) { + t.Errorf("%s (branch) should allow some matches when combined with %s (version) across types due to shared rev", gu(v6), gu(o3)) + } + + if v6.Intersect(o3) != cookie { + t.Errorf("Intersection of %s (branch) with %s (version) should return shared underlying rev", gu(v6), gu(o3)) + } + + if !v6.Matches(o4) { + t.Errorf("%s (branch) should match %s (version) across types due to shared rev", gu(v6), gu(o4)) + } + + if !v6.MatchesAny(o4) { + t.Errorf("%s (branch) should allow some matches when combined with %s (version) across types due to shared rev", gu(v6), gu(o4)) + } + + if v6.Intersect(o4) != cookie { + t.Errorf("Intersection of %s (branch) with %s (version) should return shared underlying rev", gu(v6), gu(o4)) + } +} + +func TestVersionConstraintOps(t *testing.T) { + v1 := NewVersion("ab123").(plainVersion) + v2 := NewVersion("b2a13").(plainVersion) + + if !v1.MatchesAny(any) { + t.Errorf("Versions should always match the any constraint") + } + if v1.Intersect(any) != v1 { + t.Errorf("Versions should always return self when intersecting the any constraint, but got %s", v1.Intersect(any)) + } + + if v1.MatchesAny(none) { + t.Errorf("Versions should never match the none constraint") + } + if v1.Intersect(none) != none { + t.Errorf("Versions should always return none when intersecting the none constraint, but got %s", v1.Intersect(none)) + } + + if v1.Matches(v2) { + t.Errorf("%s should not match %s", v1, v2) + } + + if v1.MatchesAny(v2) { + t.Errorf("%s should not allow any matches when combined with %s", v1, v2) + } + + if v1.Intersect(v2) != none { + t.Errorf("Intersection of %s with %s should result in empty set", v1, v2) + } + + // Add rev to one + snuffster := Revision("snuffleupagus") + v3 := v1.Pair(snuffster).(versionPair) + if v2.Matches(v3) { + t.Errorf("%s should not match %s", v2, gu(v3)) + } + if v3.Matches(v2) { + t.Errorf("%s should not match %s", gu(v3), v2) + } + + if v2.MatchesAny(v3) { + t.Errorf("%s should not allow any matches when combined with %s", v2, gu(v3)) + } + if v3.MatchesAny(v2) { + t.Errorf("%s should not allow any matches when combined with %s", v2, gu(v3)) + } + + if v2.Intersect(v3) != none { + t.Errorf("Intersection of %s with %s should result in empty set", v2, gu(v3)) + } + if v3.Intersect(v2) != none { + t.Errorf("Intersection of %s with %s should result in empty set", gu(v3), v2) + } + + // Add different rev to the other + v4 := v2.Pair(Revision("cookie monster")).(versionPair) + if v4.Matches(v3) { + t.Errorf("%s should not match %s", gu(v4), gu(v3)) + } + if v3.Matches(v4) { + t.Errorf("%s should not match %s", gu(v3), gu(v4)) + } + + if v4.MatchesAny(v3) { + t.Errorf("%s should not allow any matches when combined with %s", gu(v4), gu(v3)) + } + if v3.MatchesAny(v4) { + t.Errorf("%s should not allow any matches when combined with %s", gu(v4), gu(v3)) + } + + if v4.Intersect(v3) != none { + t.Errorf("Intersection of %s with %s should result in empty set", gu(v4), gu(v3)) + } + if v3.Intersect(v4) != none { + t.Errorf("Intersection of %s with %s should result in empty set", gu(v3), gu(v4)) + } + + // Now add same rev to different versions, and things should line up + v5 := v2.Pair(Revision("snuffleupagus")).(versionPair) + if !v5.Matches(v3) { + t.Errorf("%s should match %s", gu(v5), gu(v3)) + } + if !v3.Matches(v5) { + t.Errorf("%s should match %s", gu(v3), gu(v5)) + } + + if !v5.MatchesAny(v3) { + t.Errorf("%s should allow some matches when combined with %s", gu(v5), gu(v3)) + } + if !v3.MatchesAny(v5) { + t.Errorf("%s should allow some matches when combined with %s", gu(v5), gu(v3)) + } + + if v5.Intersect(v3) != snuffster { + t.Errorf("Intersection of %s with %s should return underlying rev", gu(v5), gu(v3)) + } + if v3.Intersect(v5) != snuffster { + t.Errorf("Intersection of %s with %s should return underlying rev", gu(v3), gu(v5)) + } + + // Set up for cross-type constraint ops + cookie := Revision("cookie monster") + o1 := NewBranch("master").(branchVersion) + o2 := NewVersion("1.0.0").(semVersion) + o3 := o1.Pair(cookie).(versionPair) + o4 := o2.Pair(cookie).(versionPair) + v6 := v1.Pair(cookie).(versionPair) + + if v1.Matches(o1) { + t.Errorf("%s (version) should not match %s (branch) across types", v1, o1) + } + + if v1.MatchesAny(o1) { + t.Errorf("%s (version) should not allow any matches when combined with %s (branch)", v1, o1) + } + + if v1.Intersect(o1) != none { + t.Errorf("Intersection of %s (version) with %s (branch) should result in empty set", v1, o1) + } + + if v1.Matches(o2) { + t.Errorf("%s (version) should not match %s (semver) across types", v1, o2) + } + + if v1.MatchesAny(o2) { + t.Errorf("%s (version) should not allow any matches when combined with %s (semver)", v1, o2) + } + + if v1.Intersect(o2) != none { + t.Errorf("Intersection of %s (version) with %s (semver) should result in empty set", v1, o2) + } + + if v1.Matches(o3) { + t.Errorf("%s (version) should not match %s (branch) across types", v1, gu(o3)) + } + + if v1.MatchesAny(o3) { + t.Errorf("%s (version) should not allow any matches when combined with %s (branch)", v1, gu(o3)) + } + + if v1.Intersect(o3) != none { + t.Errorf("Intersection of %s (version) with %s (branch) should result in empty set", v1, gu(o3)) + } + + if v1.Matches(o4) { + t.Errorf("%s (version) should not match %s (semver) across types", v1, gu(o4)) + } + + if v1.MatchesAny(o4) { + t.Errorf("%s (version) should not allow any matches when combined with %s (semver)", v1, gu(o4)) + } + + if v1.Intersect(o4) != none { + t.Errorf("Intersection of %s (version) with %s (semver) should result in empty set", v1, gu(o4)) + } + + if !v6.Matches(o3) { + t.Errorf("%s (version) should match %s (branch) across types due to shared rev", gu(v6), gu(o3)) + } + + if !v6.MatchesAny(o3) { + t.Errorf("%s (version) should allow some matches when combined with %s (branch) across types due to shared rev", gu(v6), gu(o3)) + } + + if v6.Intersect(o3) != cookie { + t.Errorf("Intersection of %s (version) with %s (branch) should return shared underlying rev", gu(v6), gu(o3)) + } + + if !v6.Matches(o4) { + t.Errorf("%s (version) should match %s (branch) across types due to shared rev", gu(v6), gu(o4)) + } + + if !v6.MatchesAny(o4) { + t.Errorf("%s (version) should allow some matches when combined with %s (branch) across types due to shared rev", gu(v6), gu(o4)) + } + + if v6.Intersect(o4) != cookie { + t.Errorf("Intersection of %s (version) with %s (branch) should return shared underlying rev", gu(v6), gu(o4)) + } +} + +func TestSemverVersionConstraintOps(t *testing.T) { + v1 := NewVersion("1.0.0").(semVersion) + v2 := NewVersion("2.0.0").(semVersion) + + if !v1.MatchesAny(any) { + t.Errorf("Semvers should always match the any constraint") + } + if v1.Intersect(any) != v1 { + t.Errorf("Semvers should always return self when intersecting the any constraint, but got %s", v1.Intersect(any)) + } + + if v1.MatchesAny(none) { + t.Errorf("Semvers should never match the none constraint") + } + if v1.Intersect(none) != none { + t.Errorf("Semvers should always return none when intersecting the none constraint, but got %s", v1.Intersect(none)) + } + + if v1.Matches(v2) { + t.Errorf("%s should not match %s", v1, v2) + } + + if v1.MatchesAny(v2) { + t.Errorf("%s should not allow any matches when combined with %s", v1, v2) + } + + if v1.Intersect(v2) != none { + t.Errorf("Intersection of %s with %s should result in empty set", v1, v2) + } + + // Add rev to one + snuffster := Revision("snuffleupagus") + v3 := v1.Pair(snuffster).(versionPair) + if v2.Matches(v3) { + t.Errorf("%s should not match %s", v2, gu(v3)) + } + if v3.Matches(v2) { + t.Errorf("%s should not match %s", gu(v3), v2) + } + + if v2.MatchesAny(v3) { + t.Errorf("%s should not allow any matches when combined with %s", v2, gu(v3)) + } + if v3.MatchesAny(v2) { + t.Errorf("%s should not allow any matches when combined with %s", v2, gu(v3)) + } + + if v2.Intersect(v3) != none { + t.Errorf("Intersection of %s with %s should result in empty set", v2, gu(v3)) + } + if v3.Intersect(v2) != none { + t.Errorf("Intersection of %s with %s should result in empty set", gu(v3), v2) + } + + // Add different rev to the other + v4 := v2.Pair(Revision("cookie monster")).(versionPair) + if v4.Matches(v3) { + t.Errorf("%s should not match %s", gu(v4), gu(v3)) + } + if v3.Matches(v4) { + t.Errorf("%s should not match %s", gu(v3), gu(v4)) + } + + if v4.MatchesAny(v3) { + t.Errorf("%s should not allow any matches when combined with %s", gu(v4), gu(v3)) + } + if v3.MatchesAny(v4) { + t.Errorf("%s should not allow any matches when combined with %s", gu(v4), gu(v3)) + } + + if v4.Intersect(v3) != none { + t.Errorf("Intersection of %s with %s should result in empty set", gu(v4), gu(v3)) + } + if v3.Intersect(v4) != none { + t.Errorf("Intersection of %s with %s should result in empty set", gu(v3), gu(v4)) + } + + // Now add same rev to different versions, and things should line up + v5 := v2.Pair(Revision("snuffleupagus")).(versionPair) + if !v5.Matches(v3) { + t.Errorf("%s should match %s", gu(v5), gu(v3)) + } + if !v3.Matches(v5) { + t.Errorf("%s should match %s", gu(v3), gu(v5)) + } + + if !v5.MatchesAny(v3) { + t.Errorf("%s should allow some matches when combined with %s", gu(v5), gu(v3)) + } + if !v3.MatchesAny(v5) { + t.Errorf("%s should allow some matches when combined with %s", gu(v5), gu(v3)) + } + + if v5.Intersect(v3) != snuffster { + t.Errorf("Intersection of %s with %s should return underlying rev", gu(v5), gu(v3)) + } + if v3.Intersect(v5) != snuffster { + t.Errorf("Intersection of %s with %s should return underlying rev", gu(v3), gu(v5)) + } + + // Set up for cross-type constraint ops + cookie := Revision("cookie monster") + o1 := NewBranch("master").(branchVersion) + o2 := NewVersion("ab123").(plainVersion) + o3 := o1.Pair(cookie).(versionPair) + o4 := o2.Pair(cookie).(versionPair) + v6 := v1.Pair(cookie).(versionPair) + + if v1.Matches(o1) { + t.Errorf("%s (semver) should not match %s (branch) across types", v1, o1) + } + + if v1.MatchesAny(o1) { + t.Errorf("%s (semver) should not allow any matches when combined with %s (branch)", v1, o1) + } + + if v1.Intersect(o1) != none { + t.Errorf("Intersection of %s (semver) with %s (branch) should result in empty set", v1, o1) + } + + if v1.Matches(o2) { + t.Errorf("%s (semver) should not match %s (version) across types", v1, o2) + } + + if v1.MatchesAny(o2) { + t.Errorf("%s (semver) should not allow any matches when combined with %s (version)", v1, o2) + } + + if v1.Intersect(o2) != none { + t.Errorf("Intersection of %s (semver) with %s (version) should result in empty set", v1, o2) + } + + if v1.Matches(o3) { + t.Errorf("%s (semver) should not match %s (branch) across types", v1, gu(o3)) + } + + if v1.MatchesAny(o3) { + t.Errorf("%s (semver) should not allow any matches when combined with %s (branch)", v1, gu(o3)) + } + + if v1.Intersect(o3) != none { + t.Errorf("Intersection of %s (semver) with %s (branch) should result in empty set", v1, gu(o3)) + } + + if v1.Matches(o4) { + t.Errorf("%s (semver) should not match %s (version) across types", v1, gu(o4)) + } + + if v1.MatchesAny(o4) { + t.Errorf("%s (semver) should not allow any matches when combined with %s (version)", v1, gu(o4)) + } + + if v1.Intersect(o4) != none { + t.Errorf("Intersection of %s (semver) with %s (version) should result in empty set", v1, gu(o4)) + } + + if !v6.Matches(o3) { + t.Errorf("%s (semver) should match %s (branch) across types due to shared rev", gu(v6), gu(o3)) + } + + if !v6.MatchesAny(o3) { + t.Errorf("%s (semver) should allow some matches when combined with %s (branch) across types due to shared rev", gu(v6), gu(o3)) + } + + if v6.Intersect(o3) != cookie { + t.Errorf("Intersection of %s (semver) with %s (branch) should return shared underlying rev", gu(v6), gu(o3)) + } + + if !v6.Matches(o4) { + t.Errorf("%s (semver) should match %s (branch) across types due to shared rev", gu(v6), gu(o4)) + } + + if !v6.MatchesAny(o4) { + t.Errorf("%s (semver) should allow some matches when combined with %s (branch) across types due to shared rev", gu(v6), gu(o4)) + } + + if v6.Intersect(o4) != cookie { + t.Errorf("Intersection of %s (semver) with %s (branch) should return shared underlying rev", gu(v6), gu(o4)) + } + + // Regression check - make sure that semVersion -> semverConstraint works + // the same as verified in the other test + c1, _ := NewSemverConstraint("=1.0.0") + if !v1.MatchesAny(c1) { + t.Errorf("%s (semver) should allow some matches - itself - when combined with an equivalent semverConstraint", gu(v1)) + } + if v1.Intersect(c1) != v1 { + t.Errorf("Intersection of %s (semver) with equivalent semver constraint should return self, got %s", gu(v1), v1.Intersect(c1)) + } + + if !v6.MatchesAny(c1) { + t.Errorf("%s (semver pair) should allow some matches - itself - when combined with an equivalent semverConstraint", gu(v6)) + } + if v6.Intersect(c1) != v6 { + t.Errorf("Intersection of %s (semver pair) with equivalent semver constraint should return self, got %s", gu(v6), v6.Intersect(c1)) + } + +} + +// The other test is about the semverVersion, this is about semverConstraint +func TestSemverConstraintOps(t *testing.T) { + v1 := NewBranch("master").(branchVersion) + v2 := NewVersion("ab123").(plainVersion) + v3 := NewVersion("1.0.0").(semVersion) + + fozzie := Revision("fozzie bear") + v4 := v1.Pair(fozzie).(versionPair) + v5 := v2.Pair(fozzie).(versionPair) + v6 := v3.Pair(fozzie).(versionPair) + + // TODO(sdboyer) we can't use the same range as below b/c semver.rangeConstraint is + // still an incomparable type + c1, err := NewSemverConstraint("=1.0.0") + if err != nil { + t.Fatalf("Failed to create constraint: %s", err) + } + + if !c1.MatchesAny(any) { + t.Errorf("Semver constraints should always match the any constraint") + } + if c1.Intersect(any) != c1 { + t.Errorf("Semver constraints should always return self when intersecting the any constraint, but got %s", c1.Intersect(any)) + } + + if c1.MatchesAny(none) { + t.Errorf("Semver constraints should never match the none constraint") + } + if c1.Intersect(none) != none { + t.Errorf("Semver constraints should always return none when intersecting the none constraint, but got %s", c1.Intersect(none)) + } + + c1, err = NewSemverConstraint(">= 1.0.0") + if err != nil { + t.Fatalf("Failed to create constraint: %s", err) + } + + if c1.Matches(v1) { + t.Errorf("Semver constraint should not match simple branch") + } + if c1.Matches(v2) { + t.Errorf("Semver constraint should not match simple version") + } + if !c1.Matches(v3) { + t.Errorf("Semver constraint should match a simple semver version in its range") + } + if c1.Matches(v4) { + t.Errorf("Semver constraint should not match paired branch") + } + if c1.Matches(v5) { + t.Errorf("Semver constraint should not match paired version") + } + if !c1.Matches(v6) { + t.Errorf("Semver constraint should match a paired semver version in its range") + } + + if c1.MatchesAny(v1) { + t.Errorf("Semver constraint should not allow any when intersected with simple branch") + } + if c1.MatchesAny(v2) { + t.Errorf("Semver constraint should not allow any when intersected with simple version") + } + if !c1.MatchesAny(v3) { + t.Errorf("Semver constraint should allow some when intersected with a simple semver version in its range") + } + if c1.MatchesAny(v4) { + t.Errorf("Semver constraint should not allow any when intersected with paired branch") + } + if c1.MatchesAny(v5) { + t.Errorf("Semver constraint should not allow any when intersected with paired version") + } + if !c1.MatchesAny(v6) { + t.Errorf("Semver constraint should allow some when intersected with a paired semver version in its range") + } + + if c1.Intersect(v1) != none { + t.Errorf("Semver constraint should return none when intersected with a simple branch") + } + if c1.Intersect(v2) != none { + t.Errorf("Semver constraint should return none when intersected with a simple version") + } + if c1.Intersect(v3) != v3 { + t.Errorf("Semver constraint should return input when intersected with a simple semver version in its range") + } + if c1.Intersect(v4) != none { + t.Errorf("Semver constraint should return none when intersected with a paired branch") + } + if c1.Intersect(v5) != none { + t.Errorf("Semver constraint should return none when intersected with a paired version") + } + if c1.Intersect(v6) != v6 { + t.Errorf("Semver constraint should return input when intersected with a paired semver version in its range") + } +} + +func TestSemverConstraint_ImpliedCaret(t *testing.T) { + c, _ := NewSemverConstraintIC("1.0.0") + + wantS := "^1.0.0" + gotS := c.String() + if wantS != gotS { + t.Errorf("Expected string %s, got %s", wantS, gotS) + } + + wantI := "1.0.0" + gotI := c.ImpliedCaretString() + if wantI != gotI { + t.Errorf("Expected implied string %s, got %s", wantI, gotI) + } + + wantT := "svc-^1.0.0" + gotT := c.typedString() + if wantT != gotT { + t.Errorf("Expected type string %s, got %s", wantT, gotT) + } +} + +// Test that certain types of cross-version comparisons work when they are +// expressed as a version union (but that others don't). +func TestVersionUnion(t *testing.T) { + rev := Revision("flooboofoobooo") + v1 := NewBranch("master") + v2 := NewBranch("test") + v3 := NewVersion("1.0.0").Pair(rev) + v4 := NewVersion("1.0.1") + v5 := NewVersion("v2.0.5").Pair(Revision("notamatch")) + + uv1 := versionTypeUnion{v1, v4, rev} + uv2 := versionTypeUnion{v2, v3} + + if uv1.MatchesAny(none) { + t.Errorf("Union can't match none") + } + if none.MatchesAny(uv1) { + t.Errorf("Union can't match none") + } + + if !uv1.MatchesAny(any) { + t.Errorf("Union must match any") + } + if !any.MatchesAny(uv1) { + t.Errorf("Union must match any") + } + + // Basic matching + if !uv1.Matches(v4) { + t.Errorf("Union should match on branch to branch") + } + if !v4.Matches(uv1) { + t.Errorf("Union should reverse-match on branch to branch") + } + + if !uv1.Matches(v3) { + t.Errorf("Union should match on rev to paired rev") + } + if !v3.Matches(uv1) { + t.Errorf("Union should reverse-match on rev to paired rev") + } + + if uv1.Matches(v2) { + t.Errorf("Union should not match on anything in disjoint unpaired") + } + if v2.Matches(uv1) { + t.Errorf("Union should not reverse-match on anything in disjoint unpaired") + } + + if uv1.Matches(v5) { + t.Errorf("Union should not match on anything in disjoint pair") + } + if v5.Matches(uv1) { + t.Errorf("Union should not reverse-match on anything in disjoint pair") + } + + if !uv1.Matches(uv2) { + t.Errorf("Union should succeed on matching comparison to other union with some overlap") + } + + // MatchesAny - repeat Matches for safety, but add more, too + if !uv1.MatchesAny(v4) { + t.Errorf("Union should match on branch to branch") + } + if !v4.MatchesAny(uv1) { + t.Errorf("Union should reverse-match on branch to branch") + } + + if !uv1.MatchesAny(v3) { + t.Errorf("Union should match on rev to paired rev") + } + if !v3.MatchesAny(uv1) { + t.Errorf("Union should reverse-match on rev to paired rev") + } + + if uv1.MatchesAny(v2) { + t.Errorf("Union should not match on anything in disjoint unpaired") + } + if v2.MatchesAny(uv1) { + t.Errorf("Union should not reverse-match on anything in disjoint unpaired") + } + + if uv1.MatchesAny(v5) { + t.Errorf("Union should not match on anything in disjoint pair") + } + if v5.MatchesAny(uv1) { + t.Errorf("Union should not reverse-match on anything in disjoint pair") + } + + c1, _ := NewSemverConstraint("~1.0.0") + c2, _ := NewSemverConstraint("~2.0.0") + if !uv1.MatchesAny(c1) { + t.Errorf("Union should have some overlap due to containing 1.0.1 version") + } + if !c1.MatchesAny(uv1) { + t.Errorf("Union should have some overlap due to containing 1.0.1 version") + } + + if uv1.MatchesAny(c2) { + t.Errorf("Union should have no overlap with ~2.0.0 semver range") + } + if c2.MatchesAny(uv1) { + t.Errorf("Union should have no overlap with ~2.0.0 semver range") + } + + if !uv1.MatchesAny(uv2) { + t.Errorf("Union should succeed on MatchAny against other union with some overlap") + } + + // Intersect - repeat all previous + if uv1.Intersect(v4) != v4 { + t.Errorf("Union intersection on contained version should return that version") + } + if v4.Intersect(uv1) != v4 { + t.Errorf("Union reverse-intersection on contained version should return that version") + } + + if uv1.Intersect(v3) != rev { + t.Errorf("Union intersection on paired version w/matching rev should return rev, got %s", uv1.Intersect(v3)) + } + if v3.Intersect(uv1) != rev { + t.Errorf("Union reverse-intersection on paired version w/matching rev should return rev, got %s", v3.Intersect(uv1)) + } + + if uv1.Intersect(v2) != none { + t.Errorf("Union should not intersect with anything in disjoint unpaired") + } + if v2.Intersect(uv1) != none { + t.Errorf("Union should not reverse-intersect with anything in disjoint unpaired") + } + + if uv1.Intersect(v5) != none { + t.Errorf("Union should not intersect with anything in disjoint pair") + } + if v5.Intersect(uv1) != none { + t.Errorf("Union should not reverse-intersect with anything in disjoint pair") + } + + if uv1.Intersect(c1) != v4 { + t.Errorf("Union intersecting with semver range should return 1.0.1 version, got %s", uv1.Intersect(c1)) + } + if c1.Intersect(uv1) != v4 { + t.Errorf("Union reverse-intersecting with semver range should return 1.0.1 version, got %s", c1.Intersect(uv1)) + } + + if uv1.Intersect(c2) != none { + t.Errorf("Union intersecting with non-overlapping semver range should return none, got %s", uv1.Intersect(c2)) + } + if c2.Intersect(uv1) != none { + t.Errorf("Union reverse-intersecting with non-overlapping semver range should return none, got %s", uv1.Intersect(c2)) + } + + if uv1.Intersect(uv2) != rev { + t.Errorf("Unions should intersect down to rev, but got %s", uv1.Intersect(uv2)) + } +} + +func TestVersionUnionPanicOnType(t *testing.T) { + // versionTypeUnions need to panic if Type() gets called + defer func() { + if err := recover(); err == nil { + t.Error("versionTypeUnion did not panic on Type() call") + } + }() + _ = versionTypeUnion{}.Type() +} + +func TestVersionUnionPanicOnString(t *testing.T) { + // versionStringUnions need to panic if String() gets called + defer func() { + if err := recover(); err == nil { + t.Error("versionStringUnion did not panic on String() call") + } + }() + _ = versionTypeUnion{}.String() +} + +func TestTypedConstraintString(t *testing.T) { + // Also tests typedVersionString(), as this nests down into that + rev := Revision("flooboofoobooo") + v1 := NewBranch("master") + v2 := NewBranch("test").Pair(rev) + v3 := NewVersion("1.0.1") + v4 := NewVersion("v2.0.5") + v5 := NewVersion("2.0.5.2") + + table := []struct { + in Constraint + out string + }{ + { + in: anyConstraint{}, + out: "any-*", + }, + { + in: noneConstraint{}, + out: "none-", + }, + { + in: mkSVC("^1.0.0"), + out: "svc-^1.0.0", + }, + { + in: v1, + out: "b-master", + }, + { + in: v2, + out: "b-test-r-" + string(rev), + }, + { + in: v3, + out: "sv-1.0.1", + }, + { + in: v4, + out: "sv-v2.0.5", + }, + { + in: v5, + out: "pv-2.0.5.2", + }, + } + + for _, fix := range table { + got := fix.in.typedString() + if got != fix.out { + t.Errorf("Typed string for %v (%T) was not expected %q; got %q", fix.in, fix.in, fix.out, got) + } + } +} + +func TestConstraintsIdentical(t *testing.T) { + for _, test := range []struct { + a, b Constraint + eq bool + }{ + {Any(), Any(), true}, + {none, noneConstraint{}, true}, + {NewVersion("test"), NewVersion("test"), true}, + {NewVersion("test"), NewVersion("test2"), false}, + {NewBranch("test"), NewBranch("test"), true}, + {NewBranch("test"), newDefaultBranch("test"), false}, + {newDefaultBranch("test"), newDefaultBranch("test"), true}, + {Revision("test"), Revision("test"), true}, + {Revision("test"), Revision("test2"), false}, + {testSemverConstraint(t, "v2.10.7"), testSemverConstraint(t, "v2.10.7"), true}, + {versionTypeUnion{NewVersion("test"), NewBranch("branch")}, + versionTypeUnion{NewBranch("branch"), NewVersion("test")}, true}, + } { + if test.eq != test.a.identical(test.b) { + want := "identical" + if !test.eq { + want = "not " + want + } + t.Errorf("expected %s:\n\t(a) %#v\n\t(b) %#v", want, test.a, test.b) + } + } +} + +func testSemverConstraint(t *testing.T, body string) Constraint { + c, err := NewSemverConstraint(body) + if err != nil { + t.Fatal(errors.Wrapf(err, "failed to create semver constraint: %s", body)) + } + return c +} + +func TestConstraintEncoding(t *testing.T) { + for _, test := range []struct { + name string + c Constraint + }{ + {"defaultBranch", newDefaultBranch("test")}, + {"branch", NewBranch("test")}, + {"ver", NewVersion("test")}, + {"semver", testSemverConstraint(t, "^1.0.0")}, + {"rev", Revision("test")}, + } { + t.Run(test.name, func(t *testing.T) { + var msg pb.Constraint + test.c.copyTo(&msg) + b, err := proto.Marshal(&msg) + if err != nil { + t.Fatal(err) + } + + if err := proto.Unmarshal(b, &msg); err != nil { + t.Fatal(err) + } + got, err := constraintFromCache(&msg) + if err != nil { + t.Error("failed to decode:", err) + } else if !got.identical(test.c) { + t.Errorf("decoded non-identical Constraint:\n\t(GOT): %#v\n\t(WNT): %#v", got, test.c) + } + + if _, ok := test.c.(UnpairedVersion); ok { + got, err := unpairedVersionFromCache(&msg) + if err != nil { + t.Error("failed to decode:", err) + } else if !got.identical(test.c) { + t.Errorf("decoded non-identical UnpairedVersion:\n\t(GOT): %#v\n\t(WNT): %#v", got, test.c) + } + } + }) + } +} diff --git a/vendor/github.com/golang/dep/gps/constraints.go b/vendor/github.com/golang/dep/gps/constraints.go new file mode 100644 index 00000000..b6550700 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/constraints.go @@ -0,0 +1,453 @@ +// Copyright 2017 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 gps + +import ( + "fmt" + "sort" + + "github.com/Masterminds/semver" + "github.com/golang/dep/gps/internal/pb" +) + +var ( + none = noneConstraint{} + any = anyConstraint{} +) + +// A Constraint provides structured limitations on the versions that are +// admissible for a given project. +// +// As with Version, it has a private method because the gps's internal +// implementation of the problem is complete, and the system relies on type +// magic to operate. +type Constraint interface { + fmt.Stringer + + // ImpliedCaretString converts the Constraint to a string in the same manner + // as String(), but treats the empty operator as equivalent to ^, rather + // than =. + // + // In the same way that String() is the inverse of NewConstraint(), this + // method is the inverse of NewSemverConstraintIC(). + ImpliedCaretString() string + + // Matches indicates if the provided Version is allowed by the Constraint. + Matches(Version) bool + + // MatchesAny indicates if the intersection of the Constraint with the + // provided Constraint would yield a Constraint that could allow *any* + // Version. + MatchesAny(Constraint) bool + + // Intersect computes the intersection of the Constraint with the provided + // Constraint. + Intersect(Constraint) Constraint + + // typedString emits the normal stringified representation of the provided + // constraint, prefixed with a string that uniquely identifies the type of + // the constraint. + // + // It also forces Constraint to be a private/sealed interface, which is a + // design goal of the system. + typedString() string + + // copyTo copies fields into a serializable representation which can be + // converted back into an identical Constraint with constraintFromCache. + copyTo(*pb.Constraint) + + // identical returns true if the constraints are identical. + // + // Identical Constraints behave identically for all methods defined by the + // interface. A Constraint is always identical to itself. + // + // Constraints serialized for caching are de-serialized into identical instances. + identical(Constraint) bool +} + +// constraintFromCache returns a Constraint identical to the one which produced m. +func constraintFromCache(m *pb.Constraint) (Constraint, error) { + switch m.Type { + case pb.Constraint_Revision: + return Revision(m.Value), nil + case pb.Constraint_Branch: + return NewBranch(m.Value), nil + case pb.Constraint_DefaultBranch: + return newDefaultBranch(m.Value), nil + case pb.Constraint_Version: + return plainVersion(m.Value), nil + case pb.Constraint_Semver: + return NewSemverConstraint(m.Value) + + default: + return nil, fmt.Errorf("unrecognized Constraint type: %#v", m) + } +} + +// unpairedVersionFromCache returns an UnpairedVersion identical to the one which produced m. +func unpairedVersionFromCache(m *pb.Constraint) (UnpairedVersion, error) { + switch m.Type { + case pb.Constraint_Branch: + return NewBranch(m.Value), nil + case pb.Constraint_DefaultBranch: + return newDefaultBranch(m.Value), nil + case pb.Constraint_Version: + return plainVersion(m.Value), nil + case pb.Constraint_Semver: + sv, err := semver.NewVersion(m.Value) + if err != nil { + return nil, err + } + return semVersion{sv: sv}, nil + + default: + return nil, fmt.Errorf("unrecognized UnpairedVersion type: %#v", m) + } +} + +// NewSemverConstraint attempts to construct a semver Constraint object from the +// input string. +// +// If the input string cannot be made into a valid semver Constraint, an error +// is returned. +func NewSemverConstraint(body string) (Constraint, error) { + c, err := semver.NewConstraint(body) + if err != nil { + return nil, err + } + // If we got a simple semver.Version, simplify by returning our + // corresponding type + if sv, ok := c.(semver.Version); ok { + return semVersion{sv: sv}, nil + } + return semverConstraint{c: c}, nil +} + +// NewSemverConstraintIC attempts to construct a semver Constraint object from the +// input string, defaulting to a caret, ^, when no operator is specified. Put +// differently, ^ is the default operator for NewSemverConstraintIC, while = +// is the default operator for NewSemverConstraint. +// +// If the input string cannot be made into a valid semver Constraint, an error +// is returned. +func NewSemverConstraintIC(body string) (Constraint, error) { + c, err := semver.NewConstraintIC(body) + if err != nil { + return nil, err + } + // If we got a simple semver.Version, simplify by returning our + // corresponding type + if sv, ok := c.(semver.Version); ok { + return semVersion{sv: sv}, nil + } + return semverConstraint{c: c}, nil +} + +type semverConstraint struct { + c semver.Constraint +} + +func (c semverConstraint) String() string { + return c.c.String() +} + +// ImpliedCaretString converts the Constraint to a string in the same manner +// as String(), but treats the empty operator as equivalent to ^, rather +// than =. +// +// In the same way that String() is the inverse of NewConstraint(), this +// method is the inverse of NewSemverConstraintIC(). +func (c semverConstraint) ImpliedCaretString() string { + return c.c.ImpliedCaretString() +} + +func (c semverConstraint) typedString() string { + return fmt.Sprintf("svc-%s", c.c.String()) +} + +func (c semverConstraint) Matches(v Version) bool { + switch tv := v.(type) { + case versionTypeUnion: + for _, elem := range tv { + if c.Matches(elem) { + return true + } + } + case semVersion: + return c.c.Matches(tv.sv) == nil + case versionPair: + if tv2, ok := tv.v.(semVersion); ok { + return c.c.Matches(tv2.sv) == nil + } + } + + return false +} + +func (c semverConstraint) MatchesAny(c2 Constraint) bool { + return c.Intersect(c2) != none +} + +func (c semverConstraint) Intersect(c2 Constraint) Constraint { + switch tc := c2.(type) { + case anyConstraint: + return c + case versionTypeUnion: + for _, elem := range tc { + if rc := c.Intersect(elem); rc != none { + return rc + } + } + case semverConstraint: + rc := c.c.Intersect(tc.c) + if !semver.IsNone(rc) { + return semverConstraint{c: rc} + } + case semVersion: + rc := c.c.Intersect(tc.sv) + if !semver.IsNone(rc) { + // If single version intersected with constraint, we know the result + // must be the single version, so just return it back out + return c2 + } + case versionPair: + if tc2, ok := tc.v.(semVersion); ok { + rc := c.c.Intersect(tc2.sv) + if !semver.IsNone(rc) { + // same reasoning as previous case + return c2 + } + } + } + + return none +} + +func (c semverConstraint) identical(c2 Constraint) bool { + sc2, ok := c2.(semverConstraint) + if !ok { + return false + } + return c.c.String() == sc2.c.String() +} + +func (c semverConstraint) copyTo(msg *pb.Constraint) { + msg.Type = pb.Constraint_Semver + msg.Value = c.String() +} + +// IsAny indicates if the provided constraint is the wildcard "Any" constraint. +func IsAny(c Constraint) bool { + _, ok := c.(anyConstraint) + return ok +} + +// Any returns a constraint that will match anything. +func Any() Constraint { + return anyConstraint{} +} + +// anyConstraint is an unbounded constraint - it matches all other types of +// constraints. It mirrors the behavior of the semver package's any type. +type anyConstraint struct{} + +func (anyConstraint) String() string { + return "*" +} + +func (anyConstraint) ImpliedCaretString() string { + return "*" +} + +func (anyConstraint) typedString() string { + return "any-*" +} + +func (anyConstraint) Matches(Version) bool { + return true +} + +func (anyConstraint) MatchesAny(Constraint) bool { + return true +} + +func (anyConstraint) Intersect(c Constraint) Constraint { + return c +} + +func (anyConstraint) identical(c Constraint) bool { + return IsAny(c) +} + +func (anyConstraint) copyTo(*pb.Constraint) { + panic("anyConstraint should never be serialized; it is solver internal-only") +} + +// noneConstraint is the empty set - it matches no versions. It mirrors the +// behavior of the semver package's none type. +type noneConstraint struct{} + +func (noneConstraint) String() string { + return "" +} + +func (noneConstraint) ImpliedCaretString() string { + return "" +} + +func (noneConstraint) typedString() string { + return "none-" +} + +func (noneConstraint) Matches(Version) bool { + return false +} + +func (noneConstraint) MatchesAny(Constraint) bool { + return false +} + +func (noneConstraint) Intersect(Constraint) Constraint { + return none +} + +func (noneConstraint) identical(c Constraint) bool { + _, ok := c.(noneConstraint) + return ok +} + +func (noneConstraint) copyTo(*pb.Constraint) { + panic("noneConstraint should never be serialized; it is solver internal-only") +} + +// A ProjectConstraint combines a ProjectIdentifier with a Constraint. It +// indicates that, if packages contained in the ProjectIdentifier enter the +// depgraph, they must do so at a version that is allowed by the Constraint. +type ProjectConstraint struct { + Ident ProjectIdentifier + Constraint Constraint +} + +// ProjectConstraints is a map of projects, as identified by their import path +// roots (ProjectRoots) to the corresponding ProjectProperties. +// +// They are the standard form in which Manifests declare their required +// dependency properties - constraints and network locations - as well as the +// form in which RootManifests declare their overrides. +type ProjectConstraints map[ProjectRoot]ProjectProperties + +type workingConstraint struct { + Ident ProjectIdentifier + Constraint Constraint + overrNet, overrConstraint bool +} + +func pcSliceToMap(l []ProjectConstraint, r ...[]ProjectConstraint) ProjectConstraints { + final := make(ProjectConstraints) + + for _, pc := range l { + final[pc.Ident.ProjectRoot] = ProjectProperties{ + Source: pc.Ident.Source, + Constraint: pc.Constraint, + } + } + + for _, pcs := range r { + for _, pc := range pcs { + if pp, exists := final[pc.Ident.ProjectRoot]; exists { + // Technically this should be done through a bridge for + // cross-version-type matching...but this is a one off for root and + // that's just ridiculous for this. + pp.Constraint = pp.Constraint.Intersect(pc.Constraint) + final[pc.Ident.ProjectRoot] = pp + } else { + final[pc.Ident.ProjectRoot] = ProjectProperties{ + Source: pc.Ident.Source, + Constraint: pc.Constraint, + } + } + } + } + + return final +} + +func (m ProjectConstraints) asSortedSlice() []ProjectConstraint { + pcs := make([]ProjectConstraint, len(m)) + + k := 0 + for pr, pp := range m { + pcs[k] = ProjectConstraint{ + Ident: ProjectIdentifier{ + ProjectRoot: pr, + Source: pp.Source, + }, + Constraint: pp.Constraint, + } + k++ + } + + sort.SliceStable(pcs, func(i, j int) bool { + return pcs[i].Ident.Less(pcs[j].Ident) + }) + return pcs +} + +// overrideAll treats the receiver ProjectConstraints map as a set of override +// instructions, and applies overridden values to the ProjectConstraints. +// +// A slice of workingConstraint is returned, allowing differentiation between +// values that were or were not overridden. +func (m ProjectConstraints) overrideAll(pcm ProjectConstraints) (out []workingConstraint) { + out = make([]workingConstraint, len(pcm)) + k := 0 + for pr, pp := range pcm { + out[k] = m.override(pr, pp) + k++ + } + + sort.SliceStable(out, func(i, j int) bool { + return out[i].Ident.Less(out[j].Ident) + }) + return +} + +// override replaces a single ProjectConstraint with a workingConstraint, +// overriding its values if a corresponding entry exists in the +// ProjectConstraints map. +func (m ProjectConstraints) override(pr ProjectRoot, pp ProjectProperties) workingConstraint { + wc := workingConstraint{ + Ident: ProjectIdentifier{ + ProjectRoot: pr, + Source: pp.Source, + }, + Constraint: pp.Constraint, + } + + if opp, has := m[pr]; has { + // The rule for overrides is that *any* non-zero value for the prop + // should be considered an override, even if it's equal to what's + // already there. + if opp.Constraint != nil { + wc.Constraint = opp.Constraint + wc.overrConstraint = true + } + + // This may appear incorrect, because the solver encodes meaning into + // the empty string for NetworkName (it means that it would use the + // import path by default, but could be coerced into using an alternate + // URL). However, that 'coercion' can only happen if there's a + // disagreement between projects on where a dependency should be sourced + // from. Such disagreement is exactly what overrides preclude, so + // there's no need to preserve the meaning of "" here - thus, we can + // treat it as a zero value and ignore it, rather than applying it. + if opp.Source != "" { + wc.Ident.Source = opp.Source + wc.overrNet = true + } + } + + return wc +} diff --git a/vendor/github.com/golang/dep/gps/deduce.go b/vendor/github.com/golang/dep/gps/deduce.go new file mode 100644 index 00000000..d29481d4 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/deduce.go @@ -0,0 +1,892 @@ +// Copyright 2017 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 gps + +import ( + "context" + "fmt" + "io" + "net/http" + "net/url" + "path" + "regexp" + "strconv" + "strings" + "sync" + + radix "github.com/armon/go-radix" + "github.com/pkg/errors" +) + +var ( + gitSchemes = []string{"https", "ssh", "git", "http"} + bzrSchemes = []string{"https", "bzr+ssh", "bzr", "http"} + hgSchemes = []string{"https", "ssh", "http"} + svnSchemes = []string{"https", "http", "svn", "svn+ssh"} + gopkginSchemes = []string{"https", "http"} +) + +const gopkgUnstableSuffix = "-unstable" + +func validateVCSScheme(scheme, typ string) bool { + // everything allows plain ssh + if scheme == "ssh" { + return true + } + + var schemes []string + switch typ { + case "git": + schemes = gitSchemes + case "bzr": + schemes = bzrSchemes + case "hg": + schemes = hgSchemes + case "svn": + schemes = svnSchemes + default: + panic(fmt.Sprint("unsupported vcs type", scheme)) + } + + for _, valid := range schemes { + if scheme == valid { + return true + } + } + return false +} + +// Regexes for the different known import path flavors +var ( + // This regex allows some usernames that github currently disallows. They + // have allowed them in the past. + ghRegex = regexp.MustCompile(`^(?Pgithub\.com(/[A-Za-z0-9][-A-Za-z0-9]*/[A-Za-z0-9_.\-]+))((?:/[A-Za-z0-9_.\-]+)*)$`) + gpinNewRegex = regexp.MustCompile(`^(?Pgopkg\.in(?:(/[a-zA-Z0-9][-a-zA-Z0-9]+)?)(/[a-zA-Z][-.a-zA-Z0-9]*)\.((?:v0|v[1-9][0-9]*)(?:\.0|\.[1-9][0-9]*){0,2}(?:-unstable)?)(?:\.git)?)((?:/[a-zA-Z0-9][-.a-zA-Z0-9]*)*)$`) + //gpinOldRegex = regexp.MustCompile(`^(?Pgopkg\.in/(?:([a-z0-9][-a-z0-9]+)/)?((?:v0|v[1-9][0-9]*)(?:\.0|\.[1-9][0-9]*){0,2}(-unstable)?)/([a-zA-Z][-a-zA-Z0-9]*)(?:\.git)?)((?:/[a-zA-Z][-a-zA-Z0-9]*)*)$`) + bbRegex = regexp.MustCompile(`^(?Pbitbucket\.org(?P/[A-Za-z0-9_.\-]+/[A-Za-z0-9_.\-]+))((?:/[A-Za-z0-9_.\-]+)*)$`) + //lpRegex = regexp.MustCompile(`^(?Plaunchpad\.net/([A-Za-z0-9-._]+)(/[A-Za-z0-9-._]+)?)(/.+)?`) + lpRegex = regexp.MustCompile(`^(?Plaunchpad\.net(/[A-Za-z0-9-._]+))((?:/[A-Za-z0-9_.\-]+)*)?$`) + //glpRegex = regexp.MustCompile(`^(?Pgit\.launchpad\.net/([A-Za-z0-9_.\-]+)|~[A-Za-z0-9_.\-]+/(\+git|[A-Za-z0-9_.\-]+)/[A-Za-z0-9_.\-]+)$`) + glpRegex = regexp.MustCompile(`^(?Pgit\.launchpad\.net(/[A-Za-z0-9_.\-]+))((?:/[A-Za-z0-9_.\-]+)*)$`) + //gcRegex = regexp.MustCompile(`^(?Pcode\.google\.com/[pr]/(?P[a-z0-9\-]+)(\.(?P[a-z0-9\-]+))?)(/[A-Za-z0-9_.\-]+)*$`) + jazzRegex = regexp.MustCompile(`^(?Phub\.jazz\.net(/git/[a-z0-9]+/[A-Za-z0-9_.\-]+))((?:/[A-Za-z0-9_.\-]+)*)$`) + apacheRegex = regexp.MustCompile(`^(?Pgit\.apache\.org(/[a-z0-9_.\-]+\.git))((?:/[A-Za-z0-9_.\-]+)*)$`) + vcsExtensionRegex = regexp.MustCompile(`^(?P([a-z0-9.\-]+\.)+[a-z0-9.\-]+(:[0-9]+)?/[A-Za-z0-9_.\-/~]*?\.(?Pbzr|git|hg|svn))((?:/[A-Za-z0-9_.\-]+)*)$`) +) + +// Other helper regexes +var ( + scpSyntaxRe = regexp.MustCompile(`^([a-zA-Z0-9_]+)@([a-zA-Z0-9._-]+):(.*)$`) + pathvld = regexp.MustCompile(`^([A-Za-z0-9-]+)(\.[A-Za-z0-9-]+)+(/[A-Za-z0-9-_.~]+)*$`) +) + +func pathDeducerTrie() *deducerTrie { + dxt := newDeducerTrie() + + dxt.Insert("github.com/", githubDeducer{regexp: ghRegex}) + dxt.Insert("gopkg.in/", gopkginDeducer{regexp: gpinNewRegex}) + dxt.Insert("bitbucket.org/", bitbucketDeducer{regexp: bbRegex}) + dxt.Insert("launchpad.net/", launchpadDeducer{regexp: lpRegex}) + dxt.Insert("git.launchpad.net/", launchpadGitDeducer{regexp: glpRegex}) + dxt.Insert("hub.jazz.net/", jazzDeducer{regexp: jazzRegex}) + dxt.Insert("git.apache.org/", apacheDeducer{regexp: apacheRegex}) + + return dxt +} + +type pathDeducer interface { + // deduceRoot takes an import path such as + // "github.com/some-user/some-package/some-subpackage" + // and returns the root folder to where the version control + // system exists. For example, the root folder where .git exists. + // So the return of the above string would be + // "github.com/some-user/some-package" + deduceRoot(string) (string, error) + deduceSource(string, *url.URL) (maybeSource, error) +} + +type githubDeducer struct { + regexp *regexp.Regexp +} + +func (m githubDeducer) deduceRoot(path string) (string, error) { + v := m.regexp.FindStringSubmatch(path) + if v == nil { + return "", fmt.Errorf("%s is not a valid path for a source on github.com", path) + } + + return "github.com" + v[2], nil +} + +func (m githubDeducer) deduceSource(path string, u *url.URL) (maybeSource, error) { + v := m.regexp.FindStringSubmatch(path) + if v == nil { + return nil, fmt.Errorf("%s is not a valid path for a source on github.com", path) + } + + u.Host = "github.com" + u.Path = v[2] + + if u.Scheme == "ssh" && u.User != nil && u.User.Username() != "git" { + return nil, fmt.Errorf("github ssh must be accessed via the 'git' user; %s was provided", u.User.Username()) + } else if u.Scheme != "" { + if !validateVCSScheme(u.Scheme, "git") { + return nil, fmt.Errorf("%s is not a valid scheme for accessing a git repository", u.Scheme) + } + if u.Scheme == "ssh" { + u.User = url.User("git") + } + return maybeGitSource{url: u}, nil + } + + mb := make(maybeSources, len(gitSchemes)) + for k, scheme := range gitSchemes { + u2 := *u + if scheme == "ssh" { + u2.User = url.User("git") + } + u2.Scheme = scheme + mb[k] = maybeGitSource{url: &u2} + } + + return mb, nil +} + +type bitbucketDeducer struct { + regexp *regexp.Regexp +} + +func (m bitbucketDeducer) deduceRoot(path string) (string, error) { + v := m.regexp.FindStringSubmatch(path) + if v == nil { + return "", fmt.Errorf("%s is not a valid path for a source on bitbucket.org", path) + } + + return "bitbucket.org" + v[2], nil +} + +func (m bitbucketDeducer) deduceSource(path string, u *url.URL) (maybeSource, error) { + v := m.regexp.FindStringSubmatch(path) + if v == nil { + return nil, fmt.Errorf("%s is not a valid path for a source on bitbucket.org", path) + } + + u.Host = "bitbucket.org" + u.Path = v[2] + + // This isn't definitive, but it'll probably catch most + isgit := strings.HasSuffix(u.Path, ".git") || (u.User != nil && u.User.Username() == "git") + ishg := strings.HasSuffix(u.Path, ".hg") || (u.User != nil && u.User.Username() == "hg") + + // TODO(sdboyer) resolve scm ambiguity if needed by querying bitbucket's REST API + if u.Scheme != "" { + validgit, validhg := validateVCSScheme(u.Scheme, "git"), validateVCSScheme(u.Scheme, "hg") + if isgit { + if !validgit { + // This is unreachable for now, as the git schemes are a + // superset of the hg schemes + return nil, fmt.Errorf("%s is not a valid scheme for accessing a git repository", u.Scheme) + } + return maybeGitSource{url: u}, nil + } else if ishg { + if !validhg { + return nil, fmt.Errorf("%s is not a valid scheme for accessing an hg repository", u.Scheme) + } + return maybeHgSource{url: u}, nil + } else if !validgit && !validhg { + return nil, fmt.Errorf("%s is not a valid scheme for accessing either a git or hg repository", u.Scheme) + } + + // No other choice, make an option for both git and hg + return maybeSources{ + maybeHgSource{url: u}, + maybeGitSource{url: u}, + }, nil + } + + mb := make(maybeSources, 0) + // git is probably more common, even on bitbucket. however, bitbucket + // appears to fail _extremely_ slowly on git pings (ls-remote) when the + // underlying repository is actually an hg repository, so it's better + // to try hg first. + if !isgit { + for _, scheme := range hgSchemes { + u2 := *u + if scheme == "ssh" { + u2.User = url.User("hg") + } + u2.Scheme = scheme + mb = append(mb, maybeHgSource{url: &u2}) + } + } + + if !ishg { + for _, scheme := range gitSchemes { + u2 := *u + if scheme == "ssh" { + u2.User = url.User("git") + } + u2.Scheme = scheme + mb = append(mb, maybeGitSource{url: &u2}) + } + } + + return mb, nil +} + +type gopkginDeducer struct { + regexp *regexp.Regexp +} + +func (m gopkginDeducer) deduceRoot(p string) (string, error) { + v, err := m.parseAndValidatePath(p) + if err != nil { + return "", err + } + + return v[1], nil +} + +func (m gopkginDeducer) parseAndValidatePath(p string) ([]string, error) { + v := m.regexp.FindStringSubmatch(p) + if v == nil { + return nil, fmt.Errorf("%s is not a valid path for a source on gopkg.in", p) + } + + // We duplicate some logic from the gopkg.in server in order to validate the + // import path string without having to make a network request + if strings.Contains(v[4], ".") { + return nil, fmt.Errorf("%s is not a valid import path; gopkg.in only allows major versions (%q instead of %q)", + p, v[4][:strings.Index(v[4], ".")], v[4]) + } + + return v, nil +} + +func (m gopkginDeducer) deduceSource(p string, u *url.URL) (maybeSource, error) { + // Reuse root detection logic for initial validation + v, err := m.parseAndValidatePath(p) + if err != nil { + return nil, err + } + + // Putting a scheme on gopkg.in would be really weird, disallow it + if u.Scheme != "" { + return nil, fmt.Errorf("specifying alternate schemes on gopkg.in imports is not permitted") + } + + // gopkg.in is always backed by github + u.Host = "github.com" + if v[2] == "" { + elem := v[3][1:] + u.Path = path.Join("/go-"+elem, elem) + } else { + u.Path = path.Join(v[2], v[3]) + } + + unstable := false + majorStr := v[4] + + if strings.HasSuffix(majorStr, gopkgUnstableSuffix) { + unstable = true + majorStr = strings.TrimSuffix(majorStr, gopkgUnstableSuffix) + } + major, err := strconv.ParseUint(majorStr[1:], 10, 64) + if err != nil { + // this should only be reachable if there's an error in the regex + return nil, fmt.Errorf("could not parse %q as a gopkg.in major version", majorStr[1:]) + } + + mb := make(maybeSources, len(gopkginSchemes)) + for k, scheme := range gopkginSchemes { + u2 := *u + u2.Scheme = scheme + mb[k] = maybeGopkginSource{ + opath: v[1], + url: &u2, + major: major, + unstable: unstable, + } + } + + return mb, nil +} + +type launchpadDeducer struct { + regexp *regexp.Regexp +} + +func (m launchpadDeducer) deduceRoot(path string) (string, error) { + // TODO(sdboyer) lp handling is nasty - there's ambiguities which can only really + // be resolved with a metadata request. See https://github.com/golang/go/issues/11436 + v := m.regexp.FindStringSubmatch(path) + if v == nil { + return "", fmt.Errorf("%s is not a valid path for a source on launchpad.net", path) + } + + return "launchpad.net" + v[2], nil +} + +func (m launchpadDeducer) deduceSource(path string, u *url.URL) (maybeSource, error) { + v := m.regexp.FindStringSubmatch(path) + if v == nil { + return nil, fmt.Errorf("%s is not a valid path for a source on launchpad.net", path) + } + + u.Host = "launchpad.net" + u.Path = v[2] + + if u.Scheme != "" { + if !validateVCSScheme(u.Scheme, "bzr") { + return nil, fmt.Errorf("%s is not a valid scheme for accessing a bzr repository", u.Scheme) + } + return maybeBzrSource{url: u}, nil + } + + mb := make(maybeSources, len(bzrSchemes)) + for k, scheme := range bzrSchemes { + u2 := *u + u2.Scheme = scheme + mb[k] = maybeBzrSource{url: &u2} + } + + return mb, nil +} + +type launchpadGitDeducer struct { + regexp *regexp.Regexp +} + +func (m launchpadGitDeducer) deduceRoot(path string) (string, error) { + // TODO(sdboyer) same ambiguity issues as with normal bzr lp + v := m.regexp.FindStringSubmatch(path) + if v == nil { + return "", fmt.Errorf("%s is not a valid path for a source on git.launchpad.net", path) + } + + return "git.launchpad.net" + v[2], nil +} + +func (m launchpadGitDeducer) deduceSource(path string, u *url.URL) (maybeSource, error) { + v := m.regexp.FindStringSubmatch(path) + if v == nil { + return nil, fmt.Errorf("%s is not a valid path for a source on git.launchpad.net", path) + } + + u.Host = "git.launchpad.net" + u.Path = v[2] + + if u.Scheme != "" { + if !validateVCSScheme(u.Scheme, "git") { + return nil, fmt.Errorf("%s is not a valid scheme for accessing a git repository", u.Scheme) + } + return maybeGitSource{url: u}, nil + } + + mb := make(maybeSources, len(gitSchemes)) + for k, scheme := range gitSchemes { + u2 := *u + u2.Scheme = scheme + mb[k] = maybeGitSource{url: &u2} + } + + return mb, nil +} + +type jazzDeducer struct { + regexp *regexp.Regexp +} + +func (m jazzDeducer) deduceRoot(path string) (string, error) { + v := m.regexp.FindStringSubmatch(path) + if v == nil { + return "", fmt.Errorf("%s is not a valid path for a source on hub.jazz.net", path) + } + + return "hub.jazz.net" + v[2], nil +} + +func (m jazzDeducer) deduceSource(path string, u *url.URL) (maybeSource, error) { + v := m.regexp.FindStringSubmatch(path) + if v == nil { + return nil, fmt.Errorf("%s is not a valid path for a source on hub.jazz.net", path) + } + + u.Host = "hub.jazz.net" + u.Path = v[2] + + switch u.Scheme { + case "": + u.Scheme = "https" + fallthrough + case "https": + return maybeGitSource{url: u}, nil + default: + return nil, fmt.Errorf("IBM's jazz hub only supports https, %s is not allowed", u.String()) + } +} + +type apacheDeducer struct { + regexp *regexp.Regexp +} + +func (m apacheDeducer) deduceRoot(path string) (string, error) { + v := m.regexp.FindStringSubmatch(path) + if v == nil { + return "", fmt.Errorf("%s is not a valid path for a source on git.apache.org", path) + } + + return "git.apache.org" + v[2], nil +} + +func (m apacheDeducer) deduceSource(path string, u *url.URL) (maybeSource, error) { + v := m.regexp.FindStringSubmatch(path) + if v == nil { + return nil, fmt.Errorf("%s is not a valid path for a source on git.apache.org", path) + } + + u.Host = "git.apache.org" + u.Path = v[2] + + if u.Scheme != "" { + if !validateVCSScheme(u.Scheme, "git") { + return nil, fmt.Errorf("%s is not a valid scheme for accessing a git repository", u.Scheme) + } + return maybeGitSource{url: u}, nil + } + + mb := make(maybeSources, len(gitSchemes)) + for k, scheme := range gitSchemes { + u2 := *u + u2.Scheme = scheme + mb[k] = maybeGitSource{url: &u2} + } + + return mb, nil +} + +type vcsExtensionDeducer struct { + regexp *regexp.Regexp +} + +func (m vcsExtensionDeducer) deduceRoot(path string) (string, error) { + v := m.regexp.FindStringSubmatch(path) + if v == nil { + return "", fmt.Errorf("%s contains no vcs extension hints for matching", path) + } + + return v[1], nil +} + +func (m vcsExtensionDeducer) deduceSource(path string, u *url.URL) (maybeSource, error) { + v := m.regexp.FindStringSubmatch(path) + if v == nil { + return nil, fmt.Errorf("%s contains no vcs extension hints for matching", path) + } + + switch v[4] { + case "git", "hg", "bzr": + x := strings.SplitN(v[1], "/", 2) + // TODO(sdboyer) is this actually correct for bzr? + u.Host = x[0] + u.Path = "/" + x[1] + + if u.Scheme != "" { + if !validateVCSScheme(u.Scheme, v[4]) { + return nil, fmt.Errorf("%s is not a valid scheme for accessing %s repositories (path %s)", u.Scheme, v[4], path) + } + + switch v[4] { + case "git": + return maybeGitSource{url: u}, nil + case "bzr": + return maybeBzrSource{url: u}, nil + case "hg": + return maybeHgSource{url: u}, nil + } + } + + var schemes []string + var mb maybeSources + var f func(k int, u *url.URL) + + switch v[4] { + case "git": + schemes = gitSchemes + f = func(k int, u *url.URL) { + mb[k] = maybeGitSource{url: u} + } + case "bzr": + schemes = bzrSchemes + f = func(k int, u *url.URL) { + mb[k] = maybeBzrSource{url: u} + } + case "hg": + schemes = hgSchemes + f = func(k int, u *url.URL) { + mb[k] = maybeHgSource{url: u} + } + } + + mb = make(maybeSources, len(schemes)) + for k, scheme := range schemes { + u2 := *u + u2.Scheme = scheme + f(k, &u2) + } + + return mb, nil + default: + return nil, fmt.Errorf("unknown repository type: %q", v[4]) + } +} + +// A deducer takes an import path and inspects it to determine where the +// corresponding project root should be. It applies a number of matching +// techniques, eventually falling back to an HTTP request for go-get metadata if +// none of the explicit rules succeed. +// +// The only real implementation is deductionCoordinator. The interface is +// primarily intended for testing purposes. +type deducer interface { + deduceRootPath(ctx context.Context, path string) (pathDeduction, error) +} + +type deductionCoordinator struct { + suprvsr *supervisor + mut sync.RWMutex + rootxt *radix.Tree + deducext *deducerTrie +} + +func newDeductionCoordinator(superv *supervisor) *deductionCoordinator { + dc := &deductionCoordinator{ + suprvsr: superv, + rootxt: radix.New(), + deducext: pathDeducerTrie(), + } + + return dc +} + +// deduceRootPath takes an import path and attempts to deduce various +// metadata about it - what type of source should handle it, and where its +// "root" is (for vcs repositories, the repository root). +// +// If no errors are encountered, the returned pathDeduction will contain both +// the root path and a list of maybeSources, which can be subsequently used to +// create a handler that will manage the particular source. +func (dc *deductionCoordinator) deduceRootPath(ctx context.Context, path string) (pathDeduction, error) { + if err := dc.suprvsr.ctx.Err(); err != nil { + return pathDeduction{}, err + } + + // First, check the rootxt to see if there's a prefix match - if so, we + // can return that and move on. + dc.mut.RLock() + prefix, data, has := dc.rootxt.LongestPrefix(path) + dc.mut.RUnlock() + if has && isPathPrefixOrEqual(prefix, path) { + switch d := data.(type) { + case maybeSource: + return pathDeduction{root: prefix, mb: d}, nil + case *httpMetadataDeducer: + // Multiple calls have come in for a similar path shape during + // the window in which the HTTP request to retrieve go get + // metadata is in flight. Fold this request in with the existing + // one(s) by calling the deduction method, which will avoid + // duplication of work through a sync.Once. + return d.deduce(ctx, path) + } + + panic(fmt.Sprintf("unexpected %T in deductionCoordinator.rootxt: %v", data, data)) + } + + // No match. Try known path deduction first. + pd, err := dc.deduceKnownPaths(path) + if err == nil { + // Deduction worked; store it in the rootxt, send on retchan and + // terminate. + // FIXME(sdboyer) deal with changing path vs. root. Probably needs + // to be predeclared and reused in the hmd returnFunc + dc.mut.Lock() + dc.rootxt.Insert(pd.root, pd.mb) + dc.mut.Unlock() + return pd, nil + } + + if err != errNoKnownPathMatch { + return pathDeduction{}, err + } + + // The err indicates no known path matched. It's still possible that + // retrieving go get metadata might do the trick. + hmd := &httpMetadataDeducer{ + basePath: path, + suprvsr: dc.suprvsr, + // The vanity deducer will call this func with a completed + // pathDeduction if it succeeds in finding one. We process it + // back through the action channel to ensure serialized + // access to the rootxt map. + returnFunc: func(pd pathDeduction) { + dc.mut.Lock() + dc.rootxt.Insert(pd.root, pd.mb) + dc.mut.Unlock() + }, + } + + // Save the hmd in the rootxt so that calls checking on similar + // paths made while the request is in flight can be folded together. + dc.mut.Lock() + dc.rootxt.Insert(path, hmd) + dc.mut.Unlock() + + // Trigger the HTTP-backed deduction process for this requestor. + return hmd.deduce(ctx, path) +} + +// pathDeduction represents the results of a successful import path deduction - +// a root path, plus a maybeSource that can be used to attempt to connect to +// the source. +type pathDeduction struct { + root string + mb maybeSource +} + +var errNoKnownPathMatch = errors.New("no known path match") + +func (dc *deductionCoordinator) deduceKnownPaths(path string) (pathDeduction, error) { + u, path, err := normalizeURI(path) + if err != nil { + return pathDeduction{}, err + } + + // First, try the root path-based matches + if _, mtch, has := dc.deducext.LongestPrefix(path); has { + root, err := mtch.deduceRoot(path) + if err != nil { + return pathDeduction{}, err + } + mb, err := mtch.deduceSource(path, u) + if err != nil { + return pathDeduction{}, err + } + + return pathDeduction{ + root: root, + mb: mb, + }, nil + } + + // Next, try the vcs extension-based (infix) matcher + exm := vcsExtensionDeducer{regexp: vcsExtensionRegex} + if root, err := exm.deduceRoot(path); err == nil { + mb, err := exm.deduceSource(path, u) + if err != nil { + return pathDeduction{}, err + } + + return pathDeduction{ + root: root, + mb: mb, + }, nil + } + + return pathDeduction{}, errNoKnownPathMatch +} + +type httpMetadataDeducer struct { + once sync.Once + deduced pathDeduction + deduceErr error + basePath string + returnFunc func(pathDeduction) + suprvsr *supervisor +} + +func (hmd *httpMetadataDeducer) deduce(ctx context.Context, path string) (pathDeduction, error) { + hmd.once.Do(func() { + opath := path + u, path, err := normalizeURI(path) + if err != nil { + err = errors.Wrapf(err, "unable to normalize URI") + hmd.deduceErr = err + return + } + + pd := pathDeduction{} + + // Make the HTTP call to attempt to retrieve go-get metadata + var root, vcs, reporoot string + err = hmd.suprvsr.do(ctx, path, ctHTTPMetadata, func(ctx context.Context) error { + root, vcs, reporoot, err = getMetadata(ctx, path, u.Scheme) + if err != nil { + err = errors.Wrapf(err, "unable to read metadata") + } + return err + }) + if err != nil { + err = errors.Wrapf(err, "unable to deduce repository and source type for %q", opath) + hmd.deduceErr = err + return + } + pd.root = root + + // If we got something back at all, then it supersedes the actual input for + // the real URL to hit + repoURL, err := url.Parse(reporoot) + if err != nil { + err = errors.Wrapf(err, "server returned bad URL in go-get metadata, reporoot=%q", reporoot) + hmd.deduceErr = err + return + } + + // If the input path specified a scheme, then try to honor it. + if u.Scheme != "" && repoURL.Scheme != u.Scheme { + // If the input scheme was http, but the go-get metadata + // nevertheless indicated https should be used for the repo, then + // trust the metadata and use https. + // + // To err on the secure side, do NOT allow the same in the other + // direction (https -> http). + if u.Scheme != "http" || repoURL.Scheme != "https" { + hmd.deduceErr = errors.Errorf("scheme mismatch for %q: input asked for %q, but go-get metadata specified %q", path, u.Scheme, repoURL.Scheme) + return + } + } + + switch vcs { + case "git": + pd.mb = maybeGitSource{url: repoURL} + case "bzr": + pd.mb = maybeBzrSource{url: repoURL} + case "hg": + pd.mb = maybeHgSource{url: repoURL} + default: + hmd.deduceErr = errors.Errorf("unsupported vcs type %s in go-get metadata from %s", vcs, path) + return + } + + hmd.deduced = pd + // All data is assigned for other goroutines that may be waiting. Now, + // send the pathDeduction back to the deductionCoordinator by calling + // the returnFunc. This will also remove the reference to this hmd in + // the coordinator's trie. + // + // When this call finishes, it is guaranteed the coordinator will have + // at least begun running the action to insert the path deduction, which + // means no other deduction request will be able to interleave and + // request the same path before the pathDeduction can be processed, but + // after this hmd has been dereferenced from the trie. + hmd.returnFunc(pd) + }) + + return hmd.deduced, hmd.deduceErr +} + +// normalizeURI takes a path string - which can be a plain import path, or a +// proper URI, or something SCP-shaped - performs basic validity checks, and +// returns both a full URL and just the path portion. +func normalizeURI(p string) (*url.URL, string, error) { + var u *url.URL + var newpath string + if m := scpSyntaxRe.FindStringSubmatch(p); m != nil { + // Match SCP-like syntax and convert it to a URL. + // Eg, "git@github.com:user/repo" becomes + // "ssh://git@github.com/user/repo". + u = &url.URL{ + Scheme: "ssh", + User: url.User(m[1]), + Host: m[2], + Path: "/" + m[3], + // TODO(sdboyer) This is what stdlib sets; grok why better + //RawPath: m[3], + } + } else { + var err error + u, err = url.Parse(p) + if err != nil { + return nil, "", errors.Errorf("%q is not a valid URI", p) + } + } + + // If no scheme was passed, then the entire path will have been put into + // u.Path. Either way, construct the normalized path correctly. + if u.Host == "" { + newpath = p + } else { + newpath = path.Join(u.Host, u.Path) + } + + return u, newpath, nil +} + +// fetchMetadata fetches the remote metadata for path. +func fetchMetadata(ctx context.Context, path, scheme string) (rc io.ReadCloser, err error) { + if scheme == "http" { + rc, err = doFetchMetadata(ctx, "http", path) + return + } + + rc, err = doFetchMetadata(ctx, "https", path) + if err == nil { + return + } + + rc, err = doFetchMetadata(ctx, "http", path) + return +} + +func doFetchMetadata(ctx context.Context, scheme, path string) (io.ReadCloser, error) { + url := fmt.Sprintf("%s://%s?go-get=1", scheme, path) + switch scheme { + case "https", "http": + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return nil, errors.Wrapf(err, "unable to build HTTP request for URL %q", url) + } + + resp, err := http.DefaultClient.Do(req.WithContext(ctx)) + if err != nil { + return nil, errors.Wrapf(err, "failed HTTP request to URL %q", url) + } + + return resp.Body, nil + default: + return nil, errors.Errorf("unknown remote protocol scheme: %q", scheme) + } +} + +// getMetadata fetches and decodes remote metadata for path. +// +// scheme is optional. If it's http, only http will be attempted for fetching. +// Any other scheme (including none) will first try https, then fall back to +// http. +func getMetadata(ctx context.Context, path, scheme string) (string, string, string, error) { + rc, err := fetchMetadata(ctx, path, scheme) + if err != nil { + return "", "", "", errors.Wrapf(err, "unable to fetch raw metadata") + } + defer rc.Close() + + imports, err := parseMetaGoImports(rc) + if err != nil { + return "", "", "", errors.Wrapf(err, "unable to parse go-import metadata") + } + match := -1 + for i, im := range imports { + if !strings.HasPrefix(path, im.Prefix) { + continue + } + if match != -1 { + return "", "", "", errors.Errorf("multiple meta tags match import path %q", path) + } + match = i + } + if match == -1 { + return "", "", "", errors.Errorf("go-import metadata not found") + } + return imports[match].Prefix, imports[match].VCS, imports[match].RepoRoot, nil +} diff --git a/vendor/github.com/golang/dep/gps/deduce_test.go b/vendor/github.com/golang/dep/gps/deduce_test.go new file mode 100644 index 00000000..bb44d1f5 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/deduce_test.go @@ -0,0 +1,679 @@ +// Copyright 2017 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 gps + +import ( + "bytes" + "context" + "errors" + "fmt" + "net/url" + "reflect" + "testing" +) + +type pathDeductionFixture struct { + in string + root string + rerr error + mb maybeSource + srcerr error +} + +// helper func to generate testing *url.URLs, panicking on err +func mkurl(s string) (u *url.URL) { + var err error + u, err = url.Parse(s) + if err != nil { + panic(fmt.Sprint("string is not a valid URL:", s)) + } + return +} + +var pathDeductionFixtures = map[string][]pathDeductionFixture{ + "github": { + { + in: "github.com/sdboyer/gps", + root: "github.com/sdboyer/gps", + mb: maybeSources{ + maybeGitSource{url: mkurl("https://github.com/sdboyer/gps")}, + maybeGitSource{url: mkurl("ssh://git@github.com/sdboyer/gps")}, + maybeGitSource{url: mkurl("git://github.com/sdboyer/gps")}, + maybeGitSource{url: mkurl("http://github.com/sdboyer/gps")}, + }, + }, + { + in: "github.com/sdboyer/gps/foo", + root: "github.com/sdboyer/gps", + mb: maybeSources{ + maybeGitSource{url: mkurl("https://github.com/sdboyer/gps")}, + maybeGitSource{url: mkurl("ssh://git@github.com/sdboyer/gps")}, + maybeGitSource{url: mkurl("git://github.com/sdboyer/gps")}, + maybeGitSource{url: mkurl("http://github.com/sdboyer/gps")}, + }, + }, + { + // TODO(sdboyer) is this a problem for enforcing uniqueness? do we + // need to collapse these extensions? + in: "github.com/sdboyer/gps.git/foo", + root: "github.com/sdboyer/gps.git", + mb: maybeSources{ + maybeGitSource{url: mkurl("https://github.com/sdboyer/gps.git")}, + maybeGitSource{url: mkurl("ssh://git@github.com/sdboyer/gps.git")}, + maybeGitSource{url: mkurl("git://github.com/sdboyer/gps.git")}, + maybeGitSource{url: mkurl("http://github.com/sdboyer/gps.git")}, + }, + }, + { + in: "git@github.com:sdboyer/gps", + root: "github.com/sdboyer/gps", + mb: maybeGitSource{url: mkurl("ssh://git@github.com/sdboyer/gps")}, + }, + { + in: "https://github.com/sdboyer/gps", + root: "github.com/sdboyer/gps", + mb: maybeGitSource{url: mkurl("https://github.com/sdboyer/gps")}, + }, + { + in: "https://github.com/sdboyer/gps/foo/bar", + root: "github.com/sdboyer/gps", + mb: maybeGitSource{url: mkurl("https://github.com/sdboyer/gps")}, + }, + { + in: "github.com/sdboyer-/gps/foo", + root: "github.com/sdboyer-/gps", + mb: maybeSources{ + maybeGitSource{url: mkurl("https://github.com/sdboyer-/gps")}, + maybeGitSource{url: mkurl("ssh://git@github.com/sdboyer-/gps")}, + maybeGitSource{url: mkurl("git://github.com/sdboyer-/gps")}, + maybeGitSource{url: mkurl("http://github.com/sdboyer-/gps")}, + }, + }, + { + in: "github.com/a/gps/foo", + root: "github.com/a/gps", + mb: maybeSources{ + maybeGitSource{url: mkurl("https://github.com/a/gps")}, + maybeGitSource{url: mkurl("ssh://git@github.com/a/gps")}, + maybeGitSource{url: mkurl("git://github.com/a/gps")}, + maybeGitSource{url: mkurl("http://github.com/a/gps")}, + }, + }, + // some invalid github username patterns + { + in: "github.com/-sdboyer/gps/foo", + rerr: errors.New("github.com/-sdboyer/gps/foo is not a valid path for a source on github.com"), + }, + { + in: "github.com/sdbo.yer/gps/foo", + rerr: errors.New("github.com/sdbo.yer/gps/foo is not a valid path for a source on github.com"), + }, + { + in: "github.com/sdbo_yer/gps/foo", + rerr: errors.New("github.com/sdbo_yer/gps/foo is not a valid path for a source on github.com"), + }, + // Regression - gh does allow two-letter usernames + { + in: "github.com/kr/pretty", + root: "github.com/kr/pretty", + mb: maybeSources{ + maybeGitSource{url: mkurl("https://github.com/kr/pretty")}, + maybeGitSource{url: mkurl("ssh://git@github.com/kr/pretty")}, + maybeGitSource{url: mkurl("git://github.com/kr/pretty")}, + maybeGitSource{url: mkurl("http://github.com/kr/pretty")}, + }, + }, + }, + "gopkg.in": { + { + in: "gopkg.in/sdboyer/gps.v0", + root: "gopkg.in/sdboyer/gps.v0", + mb: maybeSources{ + maybeGopkginSource{opath: "gopkg.in/sdboyer/gps.v0", url: mkurl("https://github.com/sdboyer/gps"), major: 0}, + maybeGopkginSource{opath: "gopkg.in/sdboyer/gps.v0", url: mkurl("http://github.com/sdboyer/gps"), major: 0}, + }, + }, + { + in: "gopkg.in/sdboyer/gps.v0/foo", + root: "gopkg.in/sdboyer/gps.v0", + mb: maybeSources{ + maybeGopkginSource{opath: "gopkg.in/sdboyer/gps.v0", url: mkurl("https://github.com/sdboyer/gps"), major: 0}, + maybeGopkginSource{opath: "gopkg.in/sdboyer/gps.v0", url: mkurl("http://github.com/sdboyer/gps"), major: 0}, + }, + }, + { + in: "gopkg.in/sdboyer/gps.v1/foo/bar", + root: "gopkg.in/sdboyer/gps.v1", + mb: maybeSources{ + maybeGopkginSource{opath: "gopkg.in/sdboyer/gps.v1", url: mkurl("https://github.com/sdboyer/gps"), major: 1}, + maybeGopkginSource{opath: "gopkg.in/sdboyer/gps.v1", url: mkurl("http://github.com/sdboyer/gps"), major: 1}, + }, + }, + { + in: "gopkg.in/yaml.v1", + root: "gopkg.in/yaml.v1", + mb: maybeSources{ + maybeGopkginSource{opath: "gopkg.in/yaml.v1", url: mkurl("https://github.com/go-yaml/yaml"), major: 1}, + maybeGopkginSource{opath: "gopkg.in/yaml.v1", url: mkurl("http://github.com/go-yaml/yaml"), major: 1}, + }, + }, + { + in: "gopkg.in/yaml.v1/foo/bar", + root: "gopkg.in/yaml.v1", + mb: maybeSources{ + maybeGopkginSource{opath: "gopkg.in/yaml.v1", url: mkurl("https://github.com/go-yaml/yaml"), major: 1}, + maybeGopkginSource{opath: "gopkg.in/yaml.v1", url: mkurl("http://github.com/go-yaml/yaml"), major: 1}, + }, + }, + { + in: "gopkg.in/inf.v0", + root: "gopkg.in/inf.v0", + mb: maybeSources{ + maybeGopkginSource{opath: "gopkg.in/inf.v0", url: mkurl("https://github.com/go-inf/inf"), major: 0}, + maybeGopkginSource{opath: "gopkg.in/inf.v0", url: mkurl("http://github.com/go-inf/inf"), major: 0}, + }, + }, + { + // gopkg.in only allows specifying major version in import path + in: "gopkg.in/yaml.v1.2", + rerr: errors.New("gopkg.in/yaml.v1.2 is not a valid import path; gopkg.in only allows major versions (\"v1\" instead of \"v1.2\")"), + }, + }, + "jazz": { + // IBM hub devops services - fixtures borrowed from go get + { + in: "hub.jazz.net/git/user1/pkgname", + root: "hub.jazz.net/git/user1/pkgname", + mb: maybeGitSource{url: mkurl("https://hub.jazz.net/git/user1/pkgname")}, + }, + { + in: "hub.jazz.net/git/user1/pkgname/submodule/submodule/submodule", + root: "hub.jazz.net/git/user1/pkgname", + mb: maybeGitSource{url: mkurl("https://hub.jazz.net/git/user1/pkgname")}, + }, + { + in: "hub.jazz.net/someotherprefix", + rerr: errors.New("hub.jazz.net/someotherprefix is not a valid path for a source on hub.jazz.net"), + }, + { + in: "hub.jazz.net/someotherprefix/user1/packagename", + rerr: errors.New("hub.jazz.net/someotherprefix/user1/packagename is not a valid path for a source on hub.jazz.net"), + }, + // Spaces are not valid in user names or package names + { + in: "hub.jazz.net/git/User 1/pkgname", + rerr: errors.New("hub.jazz.net/git/User 1/pkgname is not a valid path for a source on hub.jazz.net"), + }, + { + in: "hub.jazz.net/git/user1/pkg name", + rerr: errors.New("hub.jazz.net/git/user1/pkg name is not a valid path for a source on hub.jazz.net"), + }, + // Dots are not valid in user names + { + in: "hub.jazz.net/git/user.1/pkgname", + rerr: errors.New("hub.jazz.net/git/user.1/pkgname is not a valid path for a source on hub.jazz.net"), + }, + { + in: "hub.jazz.net/git/user1/pkg.name", + root: "hub.jazz.net/git/user1/pkg.name", + mb: maybeGitSource{url: mkurl("https://hub.jazz.net/git/user1/pkg.name")}, + }, + // User names cannot have uppercase letters + { + in: "hub.jazz.net/git/USER/pkgname", + rerr: errors.New("hub.jazz.net/git/USER/pkgname is not a valid path for a source on hub.jazz.net"), + }, + }, + "bitbucket": { + { + in: "bitbucket.org/sdboyer/reporoot", + root: "bitbucket.org/sdboyer/reporoot", + mb: maybeSources{ + maybeHgSource{url: mkurl("https://bitbucket.org/sdboyer/reporoot")}, + maybeHgSource{url: mkurl("ssh://hg@bitbucket.org/sdboyer/reporoot")}, + maybeHgSource{url: mkurl("http://bitbucket.org/sdboyer/reporoot")}, + maybeGitSource{url: mkurl("https://bitbucket.org/sdboyer/reporoot")}, + maybeGitSource{url: mkurl("ssh://git@bitbucket.org/sdboyer/reporoot")}, + maybeGitSource{url: mkurl("git://bitbucket.org/sdboyer/reporoot")}, + maybeGitSource{url: mkurl("http://bitbucket.org/sdboyer/reporoot")}, + }, + }, + { + in: "bitbucket.org/sdboyer/reporoot/foo/bar", + root: "bitbucket.org/sdboyer/reporoot", + mb: maybeSources{ + maybeHgSource{url: mkurl("https://bitbucket.org/sdboyer/reporoot")}, + maybeHgSource{url: mkurl("ssh://hg@bitbucket.org/sdboyer/reporoot")}, + maybeHgSource{url: mkurl("http://bitbucket.org/sdboyer/reporoot")}, + maybeGitSource{url: mkurl("https://bitbucket.org/sdboyer/reporoot")}, + maybeGitSource{url: mkurl("ssh://git@bitbucket.org/sdboyer/reporoot")}, + maybeGitSource{url: mkurl("git://bitbucket.org/sdboyer/reporoot")}, + maybeGitSource{url: mkurl("http://bitbucket.org/sdboyer/reporoot")}, + }, + }, + { + in: "https://bitbucket.org/sdboyer/reporoot/foo/bar", + root: "bitbucket.org/sdboyer/reporoot", + mb: maybeSources{ + maybeHgSource{url: mkurl("https://bitbucket.org/sdboyer/reporoot")}, + maybeGitSource{url: mkurl("https://bitbucket.org/sdboyer/reporoot")}, + }, + }, + // Less standard behaviors possible due to the hg/git ambiguity + { + in: "bitbucket.org/sdboyer/reporoot.git", + root: "bitbucket.org/sdboyer/reporoot.git", + mb: maybeSources{ + maybeGitSource{url: mkurl("https://bitbucket.org/sdboyer/reporoot.git")}, + maybeGitSource{url: mkurl("ssh://git@bitbucket.org/sdboyer/reporoot.git")}, + maybeGitSource{url: mkurl("git://bitbucket.org/sdboyer/reporoot.git")}, + maybeGitSource{url: mkurl("http://bitbucket.org/sdboyer/reporoot.git")}, + }, + }, + { + in: "git@bitbucket.org:sdboyer/reporoot.git", + root: "bitbucket.org/sdboyer/reporoot.git", + mb: maybeGitSource{url: mkurl("ssh://git@bitbucket.org/sdboyer/reporoot.git")}, + }, + { + in: "bitbucket.org/sdboyer/reporoot.hg", + root: "bitbucket.org/sdboyer/reporoot.hg", + mb: maybeSources{ + maybeHgSource{url: mkurl("https://bitbucket.org/sdboyer/reporoot.hg")}, + maybeHgSource{url: mkurl("ssh://hg@bitbucket.org/sdboyer/reporoot.hg")}, + maybeHgSource{url: mkurl("http://bitbucket.org/sdboyer/reporoot.hg")}, + }, + }, + { + in: "hg@bitbucket.org:sdboyer/reporoot", + root: "bitbucket.org/sdboyer/reporoot", + mb: maybeHgSource{url: mkurl("ssh://hg@bitbucket.org/sdboyer/reporoot")}, + }, + { + in: "git://bitbucket.org/sdboyer/reporoot.hg", + root: "bitbucket.org/sdboyer/reporoot.hg", + srcerr: errors.New("git is not a valid scheme for accessing an hg repository"), + }, + }, + "launchpad": { + // tests for launchpad, mostly bazaar + // TODO(sdboyer) need more tests to deal w/launchpad's oddities + { + in: "launchpad.net/govcstestbzrrepo", + root: "launchpad.net/govcstestbzrrepo", + mb: maybeSources{ + maybeBzrSource{url: mkurl("https://launchpad.net/govcstestbzrrepo")}, + maybeBzrSource{url: mkurl("bzr+ssh://launchpad.net/govcstestbzrrepo")}, + maybeBzrSource{url: mkurl("bzr://launchpad.net/govcstestbzrrepo")}, + maybeBzrSource{url: mkurl("http://launchpad.net/govcstestbzrrepo")}, + }, + }, + { + in: "launchpad.net/govcstestbzrrepo/foo/bar", + root: "launchpad.net/govcstestbzrrepo", + mb: maybeSources{ + maybeBzrSource{url: mkurl("https://launchpad.net/govcstestbzrrepo")}, + maybeBzrSource{url: mkurl("bzr+ssh://launchpad.net/govcstestbzrrepo")}, + maybeBzrSource{url: mkurl("bzr://launchpad.net/govcstestbzrrepo")}, + maybeBzrSource{url: mkurl("http://launchpad.net/govcstestbzrrepo")}, + }, + }, + { + in: "launchpad.net/repo root", + rerr: errors.New("launchpad.net/repo root is not a valid path for a source on launchpad.net"), + }, + }, + "git.launchpad": { + { + in: "git.launchpad.net/reporoot", + root: "git.launchpad.net/reporoot", + mb: maybeSources{ + maybeGitSource{url: mkurl("https://git.launchpad.net/reporoot")}, + maybeGitSource{url: mkurl("ssh://git.launchpad.net/reporoot")}, + maybeGitSource{url: mkurl("git://git.launchpad.net/reporoot")}, + maybeGitSource{url: mkurl("http://git.launchpad.net/reporoot")}, + }, + }, + { + in: "git.launchpad.net/reporoot/foo/bar", + root: "git.launchpad.net/reporoot", + mb: maybeSources{ + maybeGitSource{url: mkurl("https://git.launchpad.net/reporoot")}, + maybeGitSource{url: mkurl("ssh://git.launchpad.net/reporoot")}, + maybeGitSource{url: mkurl("git://git.launchpad.net/reporoot")}, + maybeGitSource{url: mkurl("http://git.launchpad.net/reporoot")}, + }, + }, + { + in: "git.launchpad.net/repo root", + rerr: errors.New("git.launchpad.net/repo root is not a valid path for a source on git.launchpad.net"), + }, + }, + "apache": { + { + in: "git.apache.org/package-name.git", + root: "git.apache.org/package-name.git", + mb: maybeSources{ + maybeGitSource{url: mkurl("https://git.apache.org/package-name.git")}, + maybeGitSource{url: mkurl("ssh://git.apache.org/package-name.git")}, + maybeGitSource{url: mkurl("git://git.apache.org/package-name.git")}, + maybeGitSource{url: mkurl("http://git.apache.org/package-name.git")}, + }, + }, + { + in: "git.apache.org/package-name.git/foo/bar", + root: "git.apache.org/package-name.git", + mb: maybeSources{ + maybeGitSource{url: mkurl("https://git.apache.org/package-name.git")}, + maybeGitSource{url: mkurl("ssh://git.apache.org/package-name.git")}, + maybeGitSource{url: mkurl("git://git.apache.org/package-name.git")}, + maybeGitSource{url: mkurl("http://git.apache.org/package-name.git")}, + }, + }, + }, + "vcsext": { + // VCS extension-based syntax + { + in: "foobar.com/baz.git", + root: "foobar.com/baz.git", + mb: maybeSources{ + maybeGitSource{url: mkurl("https://foobar.com/baz.git")}, + maybeGitSource{url: mkurl("ssh://foobar.com/baz.git")}, + maybeGitSource{url: mkurl("git://foobar.com/baz.git")}, + maybeGitSource{url: mkurl("http://foobar.com/baz.git")}, + }, + }, + { + in: "foobar.com/baz.git/extra/path", + root: "foobar.com/baz.git", + mb: maybeSources{ + maybeGitSource{url: mkurl("https://foobar.com/baz.git")}, + maybeGitSource{url: mkurl("ssh://foobar.com/baz.git")}, + maybeGitSource{url: mkurl("git://foobar.com/baz.git")}, + maybeGitSource{url: mkurl("http://foobar.com/baz.git")}, + }, + }, + { + in: "foobar.com/baz.bzr", + root: "foobar.com/baz.bzr", + mb: maybeSources{ + maybeBzrSource{url: mkurl("https://foobar.com/baz.bzr")}, + maybeBzrSource{url: mkurl("bzr+ssh://foobar.com/baz.bzr")}, + maybeBzrSource{url: mkurl("bzr://foobar.com/baz.bzr")}, + maybeBzrSource{url: mkurl("http://foobar.com/baz.bzr")}, + }, + }, + { + in: "foo-bar.com/baz.hg", + root: "foo-bar.com/baz.hg", + mb: maybeSources{ + maybeHgSource{url: mkurl("https://foo-bar.com/baz.hg")}, + maybeHgSource{url: mkurl("ssh://foo-bar.com/baz.hg")}, + maybeHgSource{url: mkurl("http://foo-bar.com/baz.hg")}, + }, + }, + { + in: "git@foobar.com:baz.git", + root: "foobar.com/baz.git", + mb: maybeGitSource{url: mkurl("ssh://git@foobar.com/baz.git")}, + }, + { + in: "bzr+ssh://foobar.com/baz.bzr", + root: "foobar.com/baz.bzr", + mb: maybeBzrSource{url: mkurl("bzr+ssh://foobar.com/baz.bzr")}, + }, + { + in: "ssh://foobar.com/baz.bzr", + root: "foobar.com/baz.bzr", + mb: maybeBzrSource{url: mkurl("ssh://foobar.com/baz.bzr")}, + }, + { + in: "https://foobar.com/baz.hg", + root: "foobar.com/baz.hg", + mb: maybeHgSource{url: mkurl("https://foobar.com/baz.hg")}, + }, + { + in: "git://foobar.com/baz.hg", + root: "foobar.com/baz.hg", + srcerr: errors.New("git is not a valid scheme for accessing hg repositories (path foobar.com/baz.hg)"), + }, + // who knows why anyone would do this, but having a second vcs ext + // shouldn't throw us off - only the first one counts + { + in: "foobar.com/baz.git/quark/quizzle.bzr/quorum", + root: "foobar.com/baz.git", + mb: maybeSources{ + maybeGitSource{url: mkurl("https://foobar.com/baz.git")}, + maybeGitSource{url: mkurl("ssh://foobar.com/baz.git")}, + maybeGitSource{url: mkurl("git://foobar.com/baz.git")}, + maybeGitSource{url: mkurl("http://foobar.com/baz.git")}, + }, + }, + }, + "vanity": { + // Vanity imports + { + in: "golang.org/x/exp", + root: "golang.org/x/exp", + mb: maybeGitSource{url: mkurl("https://go.googlesource.com/exp")}, + }, + { + in: "golang.org/x/exp/inotify", + root: "golang.org/x/exp", + mb: maybeGitSource{url: mkurl("https://go.googlesource.com/exp")}, + }, + { + in: "golang.org/x/net/html", + root: "golang.org/x/net", + mb: maybeGitSource{url: mkurl("https://go.googlesource.com/net")}, + }, + }, +} + +func TestDeduceFromPath(t *testing.T) { + do := func(typ string, fixtures []pathDeductionFixture, t *testing.T) { + t.Run(typ, func(t *testing.T) { + t.Parallel() + + var deducer pathDeducer + switch typ { + case "github": + deducer = githubDeducer{regexp: ghRegex} + case "gopkg.in": + deducer = gopkginDeducer{regexp: gpinNewRegex} + case "jazz": + deducer = jazzDeducer{regexp: jazzRegex} + case "bitbucket": + deducer = bitbucketDeducer{regexp: bbRegex} + case "launchpad": + deducer = launchpadDeducer{regexp: lpRegex} + case "git.launchpad": + deducer = launchpadGitDeducer{regexp: glpRegex} + case "apache": + deducer = apacheDeducer{regexp: apacheRegex} + case "vcsext": + deducer = vcsExtensionDeducer{regexp: vcsExtensionRegex} + default: + // Should just be the vanity imports, which we do elsewhere + t.Log("skipping") + t.SkipNow() + } + + var printmb func(mb maybeSource, t *testing.T) string + printmb = func(mb maybeSource, t *testing.T) string { + switch tmb := mb.(type) { + case maybeSources: + var buf bytes.Buffer + fmt.Fprintf(&buf, "%v maybeSources:", len(tmb)) + for _, elem := range tmb { + fmt.Fprintf(&buf, "\n\t\t%s", printmb(elem, t)) + } + return buf.String() + case maybeGitSource: + return fmt.Sprintf("%T: %s", tmb, ufmt(tmb.url)) + case maybeBzrSource: + return fmt.Sprintf("%T: %s", tmb, ufmt(tmb.url)) + case maybeHgSource: + return fmt.Sprintf("%T: %s", tmb, ufmt(tmb.url)) + case maybeGopkginSource: + return fmt.Sprintf("%T: %s (v%v) %s ", tmb, tmb.opath, tmb.major, ufmt(tmb.url)) + default: + t.Errorf("Unknown maybeSource type: %T", mb) + } + return "" + } + + for _, fix := range fixtures { + fix := fix + t.Run(fix.in, func(t *testing.T) { + t.Parallel() + u, in, uerr := normalizeURI(fix.in) + if uerr != nil { + if fix.rerr == nil { + t.Errorf("bad input URI %s", uerr) + } + t.SkipNow() + } + + root, rerr := deducer.deduceRoot(in) + if fix.rerr != nil { + if rerr == nil { + t.Errorf("Expected error on deducing root, got none:\n\t(WNT) %s", fix.rerr) + } else if fix.rerr.Error() != rerr.Error() { + t.Errorf("Got unexpected error on deducing root:\n\t(GOT) %s\n\t(WNT) %s", rerr, fix.rerr) + } + } else if rerr != nil { + t.Errorf("Got unexpected error on deducing root:\n\t(GOT) %s", rerr) + } else if root != fix.root { + t.Errorf("Deducer did not return expected root:\n\t(GOT) %s\n\t(WNT) %s", root, fix.root) + } + + mb, mberr := deducer.deduceSource(in, u) + if fix.srcerr != nil { + if mberr == nil { + t.Errorf("Expected error on deducing source, got none:\n\t(WNT) %s", fix.srcerr) + } else if fix.srcerr.Error() != mberr.Error() { + t.Errorf("Got unexpected error on deducing source:\n\t(GOT) %s\n\t(WNT) %s", mberr, fix.srcerr) + } + } else if mberr != nil { + // don't complain the fix already expected an rerr + if fix.rerr == nil { + t.Errorf("Got unexpected error on deducing source:\n\t(GOT) %s", mberr) + } + } else if !reflect.DeepEqual(mb, fix.mb) { + if mb == nil { + t.Errorf("Deducer returned source maybes, but none expected:\n\t(GOT) (none)\n\t(WNT) %s", printmb(fix.mb, t)) + } else if fix.mb == nil { + t.Errorf("Deducer returned source maybes, but none expected:\n\t(GOT) %s\n\t(WNT) (none)", printmb(mb, t)) + } else { + t.Errorf("Deducer did not return expected source:\n\t(GOT) %s\n\t(WNT) %s", printmb(mb, t), printmb(fix.mb, t)) + } + } else { + gotURLs, wantURLs := mb.possibleURLs(), fix.mb.possibleURLs() + if !reflect.DeepEqual(gotURLs, wantURLs) { + t.Errorf("Deducer did not return expected source:\n\t(GOT) %s\n\t(WNT) %s", gotURLs, wantURLs) + } + } + }) + } + }) + } + runSet := func(t *testing.T) { + for typ, fixtures := range pathDeductionFixtures { + do(typ, fixtures, t) + } + } + t.Run("first", runSet) + + // Run the test set twice to ensure results are correct for both cached + // and uncached deductions. + t.Run("second", runSet) +} + +func TestVanityDeduction(t *testing.T) { + if testing.Short() { + t.Skip("Skipping slow test in short mode") + } + + sm, clean := mkNaiveSM(t) + defer clean() + + vanities := pathDeductionFixtures["vanity"] + // group to avoid sourcemanager cleanup + ctx := context.Background() + do := func(t *testing.T) { + for _, fix := range vanities { + fix := fix + t.Run(fix.in, func(t *testing.T) { + t.Parallel() + + pr, err := sm.DeduceProjectRoot(fix.in) + if err != nil { + t.Errorf("Unexpected err on deducing project root: %s", err) + return + } else if string(pr) != fix.root { + t.Errorf("Deducer did not return expected root:\n\t(GOT) %s\n\t(WNT) %s", pr, fix.root) + } + + pd, err := sm.deduceCoord.deduceRootPath(ctx, fix.in) + if err != nil { + t.Errorf("Unexpected err on deducing source: %s", err) + return + } + + goturl, wanturl := pd.mb.(maybeGitSource).url.String(), fix.mb.(maybeGitSource).url.String() + if goturl != wanturl { + t.Errorf("Deduced repo ident does not match fixture:\n\t(GOT) %s\n\t(WNT) %s", goturl, wanturl) + } + + urls, err := sm.SourceURLsForPath(fix.in) + if err != nil { + t.Errorf("Unexpected err on deducing source urls: %s", err) + return + } + if len(urls) != 1 { + t.Errorf("Deduced source URLs count for a vanity import should be 1, got %d", len(urls)) + } + goturl = urls[0].String() + if goturl != wanturl { + t.Errorf("Deduced source URL does not match fixture:\n\t(GOT) %s\n\t(WNT) %s", goturl, wanturl) + } + }) + } + } + + // Run twice, to ensure correctness of cache + t.Run("first", do) + t.Run("second", do) +} + +func TestVanityDeductionSchemeMismatch(t *testing.T) { + if testing.Short() { + t.Skip("Skipping slow test in short mode") + } + + ctx := context.Background() + cm := newSupervisor(ctx) + dc := newDeductionCoordinator(cm) + _, err := dc.deduceRootPath(ctx, "ssh://golang.org/exp") + // TODO(sdboyer) this is not actually the error that it should be + if err == nil { + t.Error("should have errored on scheme mismatch between input and go-get metadata") + } +} + +// borrow from stdlib +// more useful string for debugging than fmt's struct printer +func ufmt(u *url.URL) string { + var user, pass interface{} + if u.User != nil { + user = u.User.Username() + if p, ok := u.User.Password(); ok { + pass = p + } + } + return fmt.Sprintf("host=%q, path=%q, opaque=%q, scheme=%q, user=%#v, pass=%#v, rawpath=%q, rawq=%q, frag=%q", + u.Host, u.Path, u.Opaque, u.Scheme, user, pass, u.RawPath, u.RawQuery, u.Fragment) +} diff --git a/vendor/github.com/golang/dep/gps/discovery.go b/vendor/github.com/golang/dep/gps/discovery.go new file mode 100644 index 00000000..8da4a66d --- /dev/null +++ b/vendor/github.com/golang/dep/gps/discovery.go @@ -0,0 +1,83 @@ +// Copyright 2012 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 gps + +// This code is taken from cmd/go/discovery.go; it is the logic go get itself +// uses to interpret meta imports information. + +import ( + "encoding/xml" + "fmt" + "io" + "strings" +) + +// charsetReader returns a reader for the given charset. Currently +// it only supports UTF-8 and ASCII. Otherwise, it returns a meaningful +// error which is printed by go get, so the user can find why the package +// wasn't downloaded if the encoding is not supported. Note that, in +// order to reduce potential errors, ASCII is treated as UTF-8 (i.e. characters +// greater than 0x7f are not rejected). +func charsetReader(charset string, input io.Reader) (io.Reader, error) { + switch strings.ToLower(charset) { + case "ascii": + return input, nil + default: + return nil, fmt.Errorf("can't decode XML document using charset %q", charset) + } +} + +type metaImport struct { + Prefix, VCS, RepoRoot string +} + +// parseMetaGoImports returns meta imports from the HTML in r. +// Parsing ends at the end of the section or the beginning of the . +func parseMetaGoImports(r io.Reader) (imports []metaImport, err error) { + d := xml.NewDecoder(r) + d.CharsetReader = charsetReader + d.Strict = false + var t xml.Token + for { + t, err = d.RawToken() + if err != nil { + if err == io.EOF || len(imports) > 0 { + err = nil + } + return + } + if e, ok := t.(xml.StartElement); ok && strings.EqualFold(e.Name.Local, "body") { + return + } + if e, ok := t.(xml.EndElement); ok && strings.EqualFold(e.Name.Local, "head") { + return + } + e, ok := t.(xml.StartElement) + if !ok || !strings.EqualFold(e.Name.Local, "meta") { + continue + } + if attrValue(e.Attr, "name") != "go-import" { + continue + } + if f := strings.Fields(attrValue(e.Attr, "content")); len(f) == 3 { + imports = append(imports, metaImport{ + Prefix: f[0], + VCS: f[1], + RepoRoot: f[2], + }) + } + } +} + +// attrValue returns the attribute value for the case-insensitive key +// `name', or the empty string if nothing is found. +func attrValue(attrs []xml.Attr, name string) string { + for _, a := range attrs { + if strings.EqualFold(a.Name.Local, name) { + return a.Value + } + } + return "" +} diff --git a/vendor/github.com/golang/dep/gps/example.go b/vendor/github.com/golang/dep/gps/example.go new file mode 100644 index 00000000..29657e0f --- /dev/null +++ b/vendor/github.com/golang/dep/gps/example.go @@ -0,0 +1,79 @@ +// Copyright 2017 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. + +// +build ignore + +package main + +import ( + "go/build" + "io/ioutil" + "log" + "os" + "path/filepath" + "strings" + + "github.com/golang/dep/gps" + "github.com/golang/dep/gps/pkgtree" +) + +// This is probably the simplest possible implementation of gps. It does the +// substantive work that `go get` does, except: +// 1. It drops the resulting tree into vendor instead of GOPATH +// 2. It prefers semver tags (if available) over branches +// 3. It removes any vendor directories nested within dependencies +// +// This will compile and work...and then blow away any vendor directory present +// in the cwd. Be careful! +func main() { + // Assume the current directory is correctly placed on a GOPATH, and that it's the + // root of the project. + root, _ := os.Getwd() + srcprefix := filepath.Join(build.Default.GOPATH, "src") + string(filepath.Separator) + importroot := filepath.ToSlash(strings.TrimPrefix(root, srcprefix)) + + // Set up params, including tracing + params := gps.SolveParameters{ + RootDir: root, + TraceLogger: log.New(os.Stdout, "", 0), + ProjectAnalyzer: NaiveAnalyzer{}, + } + // Perform static analysis on the current project to find all of its imports. + params.RootPackageTree, _ = pkgtree.ListPackages(root, importroot) + + // Set up a SourceManager. This manages interaction with sources (repositories). + tempdir, _ := ioutil.TempDir("", "gps-repocache") + sourcemgr, _ := gps.NewSourceManager(gps.SourceManagerConfig{Cachedir: filepath.Join(tempdir)}) + defer sourcemgr.Release() + + // Prep and run the solver + solver, _ := gps.Prepare(params, sourcemgr) + solution, err := solver.Solve() + if err == nil { + // If no failure, blow away the vendor dir and write a new one out, + // stripping nested vendor directories as we go. + os.RemoveAll(filepath.Join(root, "vendor")) + gps.WriteDepTree(filepath.Join(root, "vendor"), solution, sourcemgr, true) + } +} + +// NaiveAnalyzer is a project analyzer that implements gps.ProjectAnalyzer interface. +type NaiveAnalyzer struct{} + +// DeriveManifestAndLock is called when the solver needs manifest/lock data +// for a particular dependency project (identified by the gps.ProjectRoot +// parameter) at a particular version. That version will be checked out in a +// directory rooted at path. +func (a NaiveAnalyzer) DeriveManifestAndLock(path string, n gps.ProjectRoot) (gps.Manifest, gps.Lock, error) { + return nil, nil, nil +} + +// Info reports the name and version of the analyzer. This is used internally as part +// of gps' hashing memoization scheme. +func (a NaiveAnalyzer) Info() gps.ProjectAnalyzerInfo { + return gps.ProjectAnalyzerInfo{ + Name: "example-analyzer", + Version: 1, + } +} diff --git a/vendor/github.com/golang/dep/gps/filesystem.go b/vendor/github.com/golang/dep/gps/filesystem.go new file mode 100644 index 00000000..fd683f32 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/filesystem.go @@ -0,0 +1,136 @@ +// Copyright 2017 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 gps + +import ( + "os" + "path/filepath" + "strings" + + "github.com/pkg/errors" +) + +// fsLink represents a symbolic link. +type fsLink struct { + path string + to string + + // circular denotes if evaluating the symlink fails with "too many links" error. + // This errors means that it's very likely that the symlink has circual refernce. + circular bool + + // broken denotes that attempting to resolve the link fails, most likely because + // the destaination doesn't exist. + broken bool +} + +// filesystemState represents the state of a file system. +type filesystemState struct { + root string + dirs []string + files []string + links []fsLink +} + +func (s filesystemState) setup() error { + for _, dir := range s.dirs { + p := filepath.Join(s.root, dir) + + if err := os.MkdirAll(p, 0777); err != nil { + return errors.Errorf("os.MkdirAll(%q, 0777) err=%q", p, err) + } + } + + for _, file := range s.files { + p := filepath.Join(s.root, file) + + f, err := os.Create(p) + if err != nil { + return errors.Errorf("os.Create(%q) err=%q", p, err) + } + + if err := f.Close(); err != nil { + return errors.Errorf("file %q Close() err=%q", p, err) + } + } + + for _, link := range s.links { + p := filepath.Join(s.root, link.path) + + // On Windows, relative symlinks confuse filepath.Walk. So, we'll just sigh + // and do absolute links, assuming they are relative to the directory of + // link.path. + // + // Reference: https://github.com/golang/go/issues/17540 + // + // TODO(ibrasho): This was fixed in Go 1.9. Remove this when support for + // 1.8 is dropped. + dir := filepath.Dir(p) + to := "" + if link.to != "" { + to = filepath.Join(dir, link.to) + } + + if err := os.Symlink(to, p); err != nil { + return errors.Errorf("os.Symlink(%q, %q) err=%q", to, p, err) + } + } + + return nil +} + +// deriveFilesystemState returns a filesystemState based on the state of +// the filesystem on root. +func deriveFilesystemState(root string) (filesystemState, error) { + fs := filesystemState{root: root} + + err := filepath.Walk(fs.root, func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + + if path == fs.root { + return nil + } + + relPath, err := filepath.Rel(fs.root, path) + if err != nil { + return err + } + + if (info.Mode() & os.ModeSymlink) != 0 { + l := fsLink{path: relPath} + + l.to, err = filepath.EvalSymlinks(path) + if err != nil && strings.HasSuffix(err.Error(), "too many links") { + l.circular = true + } else if err != nil && os.IsNotExist(err) { + l.broken = true + } else if err != nil { + return err + } + + fs.links = append(fs.links, l) + + return nil + } + + if info.IsDir() { + fs.dirs = append(fs.dirs, relPath) + + return nil + } + + fs.files = append(fs.files, relPath) + + return nil + }) + + if err != nil { + return filesystemState{}, err + } + + return fs, nil +} diff --git a/vendor/github.com/golang/dep/gps/filesystem_test.go b/vendor/github.com/golang/dep/gps/filesystem_test.go new file mode 100644 index 00000000..af29846f --- /dev/null +++ b/vendor/github.com/golang/dep/gps/filesystem_test.go @@ -0,0 +1,220 @@ +// Copyright 2017 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 gps + +import ( + "fmt" + "os" + "path/filepath" + "reflect" + "testing" + + "github.com/golang/dep/internal/test" +) + +// This file contains utilities for running tests around file system state. + +type fsTestCase struct { + before, after filesystemState +} + +// assert makes sure that the tc.after state matches the state of the actual host +// file system at tc.after.root. +func (tc fsTestCase) assert(t *testing.T) { + dirMap := make(map[string]bool) + fileMap := make(map[string]bool) + linkMap := make(map[string]bool) + + for _, d := range tc.after.dirs { + dirMap[filepath.Join(tc.after.root, d)] = true + } + for _, f := range tc.after.files { + fileMap[filepath.Join(tc.after.root, f)] = true + } + for _, l := range tc.after.links { + linkMap[filepath.Join(tc.after.root, l.path)] = true + } + + err := filepath.Walk(tc.after.root, func(path string, info os.FileInfo, err error) error { + if err != nil { + t.Errorf("filepath.Walk path=%q err=%q", path, err) + return err + } + + if path == tc.after.root { + return nil + } + + // Careful! Have to check whether the path is a symlink first because, on + // windows, a symlink to a directory will return 'true' for info.IsDir(). + if (info.Mode() & os.ModeSymlink) != 0 { + if linkMap[path] { + delete(linkMap, path) + } else { + t.Errorf("unexpected symlink exists %q", path) + } + return nil + } + + if info.IsDir() { + if dirMap[path] { + delete(dirMap, path) + } else { + t.Errorf("unexpected directory exists %q", path) + } + return nil + } + + if fileMap[path] { + delete(fileMap, path) + } else { + t.Errorf("unexpected file exists %q", path) + } + return nil + }) + + if err != nil { + t.Errorf("filesystem.Walk err=%q", err) + } + + for d := range dirMap { + t.Errorf("could not find expected directory %q", d) + } + for f := range fileMap { + t.Errorf("could not find expected file %q", f) + } + for l := range linkMap { + t.Errorf("could not find expected symlink %q", l) + } +} + +// setup inflates fs onto the actual host file system at tc.before.root. +// It doesn't delete existing files and should be used on empty roots only. +func (tc fsTestCase) setup(t *testing.T) { + if err := tc.before.setup(); err != nil { + t.Fatal(err) + } +} + +func TestDeriveFilesystemState(t *testing.T) { + testcases := []struct { + name string + fs fsTestCase + }{ + { + name: "simple-case", + fs: fsTestCase{ + before: filesystemState{ + dirs: []string{ + "simple-dir", + }, + files: []string{ + "simple-file", + }, + }, + after: filesystemState{ + dirs: []string{ + "simple-dir", + }, + files: []string{ + "simple-file", + }, + }, + }, + }, + { + name: "simple-symlink-case", + fs: fsTestCase{ + before: filesystemState{ + dirs: []string{ + "simple-dir", + }, + files: []string{ + "simple-file", + }, + links: []fsLink{ + fsLink{ + path: "link", + to: "nonexisting", + broken: true, + }, + }, + }, + after: filesystemState{ + dirs: []string{ + "simple-dir", + }, + files: []string{ + "simple-file", + }, + links: []fsLink{ + fsLink{ + path: "link", + to: "", + broken: true, + }, + }, + }, + }, + }, + { + name: "complex-symlink-case", + fs: fsTestCase{ + before: filesystemState{ + links: []fsLink{ + fsLink{ + path: "link1", + to: "link2", + circular: true, + }, + fsLink{ + path: "link2", + to: "link1", + circular: true, + }, + }, + }, + after: filesystemState{ + links: []fsLink{ + fsLink{ + path: "link1", + to: "", + circular: true, + }, + fsLink{ + path: "link2", + to: "", + circular: true, + }, + }, + }, + }, + }, + } + + for _, tc := range testcases { + h := test.NewHelper(t) + + h.TempDir(tc.name) + + tc.fs.before.root = h.Path(tc.name) + tc.fs.after.root = h.Path(tc.name) + + tc.fs.setup(t) + + state, err := deriveFilesystemState(h.Path(tc.name)) + if err != nil { + t.Fatal(err) + } + + if !reflect.DeepEqual(tc.fs.after, state) { + fmt.Println(tc.fs.after) + fmt.Println(state) + t.Fatal("filesystem state mismatch") + } + + h.Cleanup() + } +} diff --git a/vendor/github.com/golang/dep/gps/hash.go b/vendor/github.com/golang/dep/gps/hash.go new file mode 100644 index 00000000..556933bc --- /dev/null +++ b/vendor/github.com/golang/dep/gps/hash.go @@ -0,0 +1,133 @@ +// Copyright 2017 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 gps + +import ( + "bytes" + "crypto/sha256" + "io" + "sort" + "strconv" + "strings" +) + +// string headers used to demarcate sections in hash input creation +const ( + hhConstraints = "-CONSTRAINTS-" + hhImportsReqs = "-IMPORTS/REQS-" + hhIgnores = "-IGNORES-" + hhOverrides = "-OVERRIDES-" + hhAnalyzer = "-ANALYZER-" +) + +// HashInputs computes a hash digest of all data in SolveParams and the +// RootManifest that act as function inputs to Solve(). +// +// The digest returned from this function is the same as the digest that would +// be included with a Solve() Result. As such, it's appropriate for comparison +// against the digest stored in a lock file, generated by a previous Solve(): if +// the digests match, then manifest and lock are in sync, and a Solve() is +// unnecessary. +// +// (Basically, this is for memoization.) +func (s *solver) HashInputs() (digest []byte) { + h := sha256.New() + s.writeHashingInputs(h) + + hd := h.Sum(nil) + digest = hd[:] + return +} + +func (s *solver) writeHashingInputs(w io.Writer) { + writeString := func(s string) { + // Skip zero-length string writes; it doesn't affect the real hash + // calculation, and keeps misleading newlines from showing up in the + // debug output. + if s != "" { + // All users of writeHashingInputs cannot error on Write(), so just + // ignore it + w.Write([]byte(s)) + } + } + + // We write "section headers" into the hash purely to ease scanning when + // debugging this input-constructing algorithm; as long as the headers are + // constant, then they're effectively a no-op. + writeString(hhConstraints) + + // getApplicableConstraints will apply overrides, incorporate requireds, + // apply local ignores, drop stdlib imports, and finally trim out + // ineffectual constraints. + for _, pd := range s.rd.getApplicableConstraints(s.stdLibFn) { + writeString(string(pd.Ident.ProjectRoot)) + writeString(pd.Ident.Source) + writeString(pd.Constraint.typedString()) + } + + // Write out each discrete import, including those derived from requires. + writeString(hhImportsReqs) + imports := s.rd.externalImportList(s.stdLibFn) + sort.Strings(imports) + for _, im := range imports { + writeString(im) + } + + // Add ignores, skipping any that point under the current project root; + // those will have already been implicitly incorporated by the import + // lister. + writeString(hhIgnores) + + ig := s.rd.ir.ToSlice() + sort.Strings(ig) + for _, igp := range ig { + // Typical prefix comparison checks will erroneously fail if the wildcard + // is present. Trim it off, if present. + tigp := strings.TrimSuffix(igp, "*") + if !strings.HasPrefix(tigp, s.rd.rpt.ImportRoot) || !isPathPrefixOrEqual(s.rd.rpt.ImportRoot, tigp) { + writeString(igp) + } + } + + // Overrides *also* need their own special entry distinct from basic + // constraints, to represent the unique effects they can have on the entire + // solving process beyond root's immediate scope. + writeString(hhOverrides) + for _, pc := range s.rd.ovr.asSortedSlice() { + writeString(string(pc.Ident.ProjectRoot)) + if pc.Ident.Source != "" { + writeString(pc.Ident.Source) + } + if pc.Constraint != nil { + writeString(pc.Constraint.typedString()) + } + } + + writeString(hhAnalyzer) + ai := s.rd.an.Info() + writeString(ai.Name) + writeString(strconv.Itoa(ai.Version)) +} + +// bytes.Buffer wrapper that injects newlines after each call to Write(). +type nlbuf bytes.Buffer + +func (buf *nlbuf) Write(p []byte) (n int, err error) { + n, _ = (*bytes.Buffer)(buf).Write(p) + (*bytes.Buffer)(buf).WriteByte('\n') + return n + 1, nil +} + +// HashingInputsAsString returns the raw input data used by Solver.HashInputs() +// as a string. +// +// This is primarily intended for debugging purposes. +func HashingInputsAsString(s Solver) string { + ts := s.(*solver) + buf := new(nlbuf) + ts.writeHashingInputs(buf) + + return (*bytes.Buffer)(buf).String() +} diff --git a/vendor/github.com/golang/dep/gps/hash_test.go b/vendor/github.com/golang/dep/gps/hash_test.go new file mode 100644 index 00000000..1be02f68 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/hash_test.go @@ -0,0 +1,686 @@ +// Copyright 2017 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 gps + +import ( + "bytes" + "crypto/sha256" + "fmt" + "strings" + "testing" + "text/tabwriter" + + "github.com/golang/dep/gps/pkgtree" +) + +func TestHashInputs(t *testing.T) { + fix := basicFixtures["shared dependency with overlapping constraints"] + + params := SolveParameters{ + RootDir: string(fix.ds[0].n), + RootPackageTree: fix.rootTree(), + Manifest: fix.rootmanifest(), + ProjectAnalyzer: naiveAnalyzer{}, + stdLibFn: func(string) bool { return false }, + mkBridgeFn: overrideMkBridge, + } + + s, err := Prepare(params, newdepspecSM(fix.ds, nil)) + if err != nil { + t.Fatalf("Unexpected error while prepping solver: %s", err) + } + + dig := s.HashInputs() + h := sha256.New() + + elems := []string{ + hhConstraints, + "a", + "sv-1.0.0", + "b", + "sv-1.0.0", + hhImportsReqs, + "a", + "b", + hhIgnores, + hhOverrides, + hhAnalyzer, + "naive-analyzer", + "1", + } + for _, v := range elems { + h.Write([]byte(v)) + } + correct := h.Sum(nil) + + if !bytes.Equal(dig, correct) { + t.Errorf("Hashes are not equal. Inputs:\n%s", diffHashingInputs(s, elems)) + } else if strings.Join(elems, "\n")+"\n" != HashingInputsAsString(s) { + t.Errorf("Hashes are equal, but hashing input strings are not:\n%s", diffHashingInputs(s, elems)) + } +} + +func TestHashInputsReqsIgs(t *testing.T) { + fix := basicFixtures["shared dependency with overlapping constraints"] + + rm := fix.rootmanifest().(simpleRootManifest).dup() + rm.ig = pkgtree.NewIgnoredRuleset([]string{"foo", "bar"}) + + params := SolveParameters{ + RootDir: string(fix.ds[0].n), + RootPackageTree: fix.rootTree(), + Manifest: rm, + ProjectAnalyzer: naiveAnalyzer{}, + stdLibFn: func(string) bool { return false }, + mkBridgeFn: overrideMkBridge, + } + + s, err := Prepare(params, newdepspecSM(fix.ds, nil)) + if err != nil { + t.Fatalf("Unexpected error while prepping solver: %s", err) + } + + dig := s.HashInputs() + h := sha256.New() + + elems := []string{ + hhConstraints, + "a", + "sv-1.0.0", + "b", + "sv-1.0.0", + hhImportsReqs, + "a", + "b", + hhIgnores, + "bar", + "foo", + hhOverrides, + hhAnalyzer, + "naive-analyzer", + "1", + } + for _, v := range elems { + h.Write([]byte(v)) + } + correct := h.Sum(nil) + + if !bytes.Equal(dig, correct) { + t.Errorf("Hashes are not equal. Inputs:\n%s", diffHashingInputs(s, elems)) + } + + // Add requires + rm.req = map[string]bool{ + "baz": true, + "qux": true, + } + + params.Manifest = rm + + s, err = Prepare(params, newdepspecSM(fix.ds, nil)) + if err != nil { + t.Fatalf("Unexpected error while prepping solver: %s", err) + } + + dig = s.HashInputs() + h = sha256.New() + + elems = []string{ + hhConstraints, + "a", + "sv-1.0.0", + "b", + "sv-1.0.0", + hhImportsReqs, + "a", + "b", + "baz", + "qux", + hhIgnores, + "bar", + "foo", + hhOverrides, + hhAnalyzer, + "naive-analyzer", + "1", + } + for _, v := range elems { + h.Write([]byte(v)) + } + correct = h.Sum(nil) + + if !bytes.Equal(dig, correct) { + t.Errorf("Hashes are not equal. Inputs:\n%s", diffHashingInputs(s, elems)) + } + + // remove ignores, just test requires alone + rm.ig = nil + params.Manifest = rm + + s, err = Prepare(params, newdepspecSM(fix.ds, nil)) + if err != nil { + t.Fatalf("Unexpected error while prepping solver: %s", err) + } + + dig = s.HashInputs() + h = sha256.New() + + elems = []string{ + hhConstraints, + "a", + "sv-1.0.0", + "b", + "sv-1.0.0", + hhImportsReqs, + "a", + "b", + "baz", + "qux", + hhIgnores, + hhOverrides, + hhAnalyzer, + "naive-analyzer", + "1", + } + for _, v := range elems { + h.Write([]byte(v)) + } + correct = h.Sum(nil) + + if !bytes.Equal(dig, correct) { + t.Errorf("Hashes are not equal. Inputs:\n%s", diffHashingInputs(s, elems)) + } +} + +func TestHashInputsOverrides(t *testing.T) { + basefix := basicFixtures["shared dependency with overlapping constraints"] + + // Set up base state that we'll mutate over the course of each test + rm := basefix.rootmanifest().(simpleRootManifest).dup() + params := SolveParameters{ + RootDir: string(basefix.ds[0].n), + RootPackageTree: basefix.rootTree(), + Manifest: rm, + ProjectAnalyzer: naiveAnalyzer{}, + stdLibFn: func(string) bool { return false }, + mkBridgeFn: overrideMkBridge, + } + + table := []struct { + name string + mut func() + elems []string + }{ + { + name: "override source; not imported, no deps pp", + mut: func() { + // First case - override just source, on something without + // corresponding project properties in the dependencies from + // root + rm.ovr = map[ProjectRoot]ProjectProperties{ + "c": { + Source: "car", + }, + } + }, + elems: []string{ + hhConstraints, + "a", + "sv-1.0.0", + "b", + "sv-1.0.0", + hhImportsReqs, + "a", + "b", + hhIgnores, + hhOverrides, + "c", + "car", + hhAnalyzer, + "naive-analyzer", + "1", + }, + }, + { + name: "override source; required, no deps pp", + mut: func() { + // Put c into the requires list, which should make it show up under + // constraints + rm.req = map[string]bool{ + "c": true, + } + }, + elems: []string{ + hhConstraints, + "a", + "sv-1.0.0", + "b", + "sv-1.0.0", + "c", + "car", + "any-*", // Any isn't included under the override, but IS for the constraint b/c it's equivalent + hhImportsReqs, + "a", + "b", + "c", + hhIgnores, + hhOverrides, + "c", + "car", + hhAnalyzer, + "naive-analyzer", + "1", + }, + }, + { + name: "override source; required & imported, no deps pp", + mut: func() { + // Put c in the root's imports + poe := params.RootPackageTree.Packages["root"] + poe.P.Imports = []string{"a", "b", "c"} + params.RootPackageTree.Packages["root"] = poe + }, + elems: []string{ + hhConstraints, + "a", + "sv-1.0.0", + "b", + "sv-1.0.0", + "c", + "car", + "any-*", // Any isn't included under the override, but IS for the constraint b/c it's equivalent + hhImportsReqs, + "a", + "b", + "c", + hhIgnores, + hhOverrides, + "c", + "car", + hhAnalyzer, + "naive-analyzer", + "1", + }, + }, + { + name: "override source; imported, no deps pp", + mut: func() { + // Take c out of requires list - now it's only imported + rm.req = nil + }, + elems: []string{ + hhConstraints, + "a", + "sv-1.0.0", + "b", + "sv-1.0.0", + "c", + "car", + "any-*", + hhImportsReqs, + "a", + "b", + "c", + hhIgnores, + hhOverrides, + "c", + "car", + hhAnalyzer, + "naive-analyzer", + "1", + }, + }, + { + name: "other override constraint; not imported, no deps pp", + mut: func() { + // Override not in root, just with constraint + rm.ovr["d"] = ProjectProperties{ + Constraint: NewBranch("foobranch"), + } + }, + elems: []string{ + hhConstraints, + "a", + "sv-1.0.0", + "b", + "sv-1.0.0", + "c", + "car", + "any-*", + hhImportsReqs, + "a", + "b", + "c", + hhIgnores, + hhOverrides, + "c", + "car", + "d", + "b-foobranch", + hhAnalyzer, + "naive-analyzer", + "1", + }, + }, + { + name: "override constraint; not imported, no deps pp", + mut: func() { + // Remove the "c" pkg from imports for remainder of tests + poe := params.RootPackageTree.Packages["root"] + poe.P.Imports = []string{"a", "b"} + params.RootPackageTree.Packages["root"] = poe + }, + elems: []string{ + hhConstraints, + "a", + "sv-1.0.0", + "b", + "sv-1.0.0", + hhImportsReqs, + "a", + "b", + hhIgnores, + hhOverrides, + "c", + "car", + "d", + "b-foobranch", + hhAnalyzer, + "naive-analyzer", + "1", + }, + }, + { + name: "override both; not imported, no deps pp", + mut: func() { + // Override not in root, both constraint and network name + rm.ovr["c"] = ProjectProperties{ + Source: "groucho", + Constraint: NewBranch("plexiglass"), + } + }, + elems: []string{ + hhConstraints, + "a", + "sv-1.0.0", + "b", + "sv-1.0.0", + hhImportsReqs, + "a", + "b", + hhIgnores, + hhOverrides, + "c", + "groucho", + "b-plexiglass", + "d", + "b-foobranch", + hhAnalyzer, + "naive-analyzer", + "1", + }, + }, + { + name: "override constraint; imported, with constraint", + mut: func() { + // Override dep present in root, just constraint + rm.ovr["a"] = ProjectProperties{ + Constraint: NewVersion("fluglehorn"), + } + }, + elems: []string{ + hhConstraints, + "a", + "pv-fluglehorn", + "b", + "sv-1.0.0", + hhImportsReqs, + "a", + "b", + hhIgnores, + hhOverrides, + "a", + "pv-fluglehorn", + "c", + "groucho", + "b-plexiglass", + "d", + "b-foobranch", + hhAnalyzer, + "naive-analyzer", + "1", + }, + }, + { + name: "override source; imported, with constraint", + mut: func() { + // Override in root, only network name + rm.ovr["a"] = ProjectProperties{ + Source: "nota", + } + }, + elems: []string{ + hhConstraints, + "a", + "nota", + "sv-1.0.0", + "b", + "sv-1.0.0", + hhImportsReqs, + "a", + "b", + hhIgnores, + hhOverrides, + "a", + "nota", + "c", + "groucho", + "b-plexiglass", + "d", + "b-foobranch", + hhAnalyzer, + "naive-analyzer", + "1", + }, + }, + { + name: "override both; imported, with constraint", + mut: func() { + // Override in root, network name and constraint + rm.ovr["a"] = ProjectProperties{ + Source: "nota", + Constraint: NewVersion("fluglehorn"), + } + }, + elems: []string{ + hhConstraints, + "a", + "nota", + "pv-fluglehorn", + "b", + "sv-1.0.0", + hhImportsReqs, + "a", + "b", + hhIgnores, + hhOverrides, + "a", + "nota", + "pv-fluglehorn", + "c", + "groucho", + "b-plexiglass", + "d", + "b-foobranch", + hhAnalyzer, + "naive-analyzer", + "1", + }, + }, + } + + for _, fix := range table { + fix.mut() + params.Manifest = rm + + s, err := Prepare(params, newdepspecSM(basefix.ds, nil)) + if err != nil { + t.Errorf("(fix: %q) Unexpected error while prepping solver: %s", fix.name, err) + continue + } + + h := sha256.New() + for _, v := range fix.elems { + h.Write([]byte(v)) + } + + if !bytes.Equal(s.HashInputs(), h.Sum(nil)) { + t.Errorf("(fix: %q) Hashes are not equal. Inputs:\n%s", fix.name, diffHashingInputs(s, fix.elems)) + } + } +} + +func diffHashingInputs(s Solver, wnt []string) string { + actual := HashingInputsAsString(s) + got := strings.Split(actual, "\n") + // got has a trailing empty, add that to wnt + wnt = append(wnt, "") + + lg, lw := len(got), len(wnt) + + var buf bytes.Buffer + tw := tabwriter.NewWriter(&buf, 4, 4, 2, ' ', 0) + fmt.Fprintln(tw, " (GOT) \t (WANT) \t") + + lmiss, rmiss := ">>>>>>>>>>", "<<<<<<<<<<" + if lg == lw { + // same length makes the loop pretty straightforward + for i := 0; i < lg; i++ { + fmt.Fprintf(tw, "%s\t%s\t\n", got[i], wnt[i]) + } + } else if lg > lw { + offset := 0 + for i := 0; i < lg; i++ { + if lw <= i-offset { + fmt.Fprintf(tw, "%s\t%s\t\n", got[i], rmiss) + } else if got[i] != wnt[i-offset] && i+1 < lg && got[i+1] == wnt[i-offset] { + // if the next slot is a match, realign by skipping this one and + // bumping the offset + fmt.Fprintf(tw, "%s\t%s\t\n", got[i], rmiss) + offset++ + } else { + fmt.Fprintf(tw, "%s\t%s\t\n", got[i], wnt[i-offset]) + } + } + } else { + offset := 0 + for i := 0; i < lw; i++ { + if lg <= i-offset { + fmt.Fprintf(tw, "%s\t%s\t\n", lmiss, wnt[i]) + } else if got[i-offset] != wnt[i] && i+1 < lw && got[i-offset] == wnt[i+1] { + // if the next slot is a match, realign by skipping this one and + // bumping the offset + fmt.Fprintf(tw, "%s\t%s\t\n", lmiss, wnt[i]) + offset++ + } else { + fmt.Fprintf(tw, "%s\t%s\t\n", got[i-offset], wnt[i]) + } + } + } + + tw.Flush() + return buf.String() +} + +func TestHashInputsIneffectualWildcardIgs(t *testing.T) { + fix := basicFixtures["shared dependency with overlapping constraints"] + + rm := fix.rootmanifest().(simpleRootManifest).dup() + + params := SolveParameters{ + RootDir: string(fix.ds[0].n), + RootPackageTree: fix.rootTree(), + Manifest: rm, + ProjectAnalyzer: naiveAnalyzer{}, + stdLibFn: func(string) bool { return false }, + mkBridgeFn: overrideMkBridge, + } + + cases := []struct { + name string + ignoreMap []string + elems []string + }{ + { + name: "no wildcard ignores", + elems: []string{ + hhConstraints, + "a", + "sv-1.0.0", + "b", + "sv-1.0.0", + hhImportsReqs, + "a", + "b", + hhIgnores, + hhOverrides, + hhAnalyzer, + "naive-analyzer", + "1", + }, + }, + { + name: "different wildcard ignores", + ignoreMap: []string{ + "foobar*", + "foobarbaz*", + "foozapbar*", + }, + elems: []string{ + hhConstraints, + "a", + "sv-1.0.0", + "b", + "sv-1.0.0", + hhImportsReqs, + "a", + "b", + hhIgnores, + "foobar*", + "foozapbar*", + hhOverrides, + hhAnalyzer, + "naive-analyzer", + "1", + }, + }, + } + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + + rm.ig = pkgtree.NewIgnoredRuleset(c.ignoreMap) + + params.Manifest = rm + + s, err := Prepare(params, newdepspecSM(fix.ds, nil)) + if err != nil { + t.Fatalf("Unexpected error while prepping solver: %s", err) + } + + dig := s.HashInputs() + h := sha256.New() + + for _, v := range c.elems { + h.Write([]byte(v)) + } + correct := h.Sum(nil) + + if !bytes.Equal(dig, correct) { + t.Errorf("Hashes are not equal. Inputs:\n%s", diffHashingInputs(s, c.elems)) + } + }) + } +} diff --git a/vendor/github.com/golang/dep/gps/identifier.go b/vendor/github.com/golang/dep/gps/identifier.go new file mode 100644 index 00000000..cf3ca235 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/identifier.go @@ -0,0 +1,226 @@ +// Copyright 2017 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 gps + +import ( + "fmt" + "math/rand" + "strconv" +) + +// ProjectRoot is the topmost import path in a tree of other import paths - the +// root of the tree. In gps' current design, ProjectRoots have to correspond to +// a repository root (mostly), but their real purpose is to identify the root +// import path of a "project", logically encompassing all child packages. +// +// Projects are a crucial unit of operation in gps. Constraints are declared by +// a project's manifest, and apply to all packages in a ProjectRoot's tree. +// Solving itself mostly proceeds on a project-by-project basis. +// +// Aliasing string types is usually a bit of an anti-pattern. gps does it here +// as a means of clarifying API intent. This is important because Go's package +// management domain has lots of different path-ish strings floating around: +// +// actual directories: +// /home/sdboyer/go/src/github.com/sdboyer/gps/example +// URLs: +// https://github.com/sdboyer/gps +// import paths: +// github.com/sdboyer/gps/example +// portions of import paths that refer to a package: +// example +// portions that could not possibly refer to anything sane: +// github.com/sdboyer +// portions that correspond to a repository root: +// github.com/sdboyer/gps +// +// While not a panacea, having ProjectRoot allows gps to clearly indicate via +// the type system when a path-ish string must have particular semantics. +type ProjectRoot string + +// A ProjectIdentifier provides the name and source location of a dependency. It +// is related to, but differs in two key ways from, a plain import path. +// +// First, ProjectIdentifiers do not identify a single package. Rather, they +// encompass the whole tree of packages, including tree's root - the +// ProjectRoot. In gps' current design, this ProjectRoot almost always +// corresponds to the root of a repository. +// +// Second, ProjectIdentifiers can optionally carry a Source, which +// identifies where the underlying source code can be located on the network. +// These can be either a full URL, including protocol, or plain import paths. +// So, these are all valid data for Source: +// +// github.com/sdboyer/gps +// github.com/fork/gps +// git@github.com:sdboyer/gps +// https://github.com/sdboyer/gps +// +// With plain import paths, network addresses are derived purely through an +// algorithm. By having an explicit network name, it becomes possible to, for +// example, transparently substitute a fork for the original upstream source +// repository. +// +// Note that gps makes no guarantees about the actual import paths contained in +// a repository aligning with ImportRoot. If tools, or their users, specify an +// alternate Source that contains a repository with incompatible internal +// import paths, gps' solving operations will error. (gps does no import +// rewriting.) +// +// Also note that if different projects' manifests report a different +// Source for a given ImportRoot, it is a solve failure. Everyone has to +// agree on where a given import path should be sourced from. +// +// If Source is not explicitly set, gps will derive the network address from +// the ImportRoot using a similar algorithm to that utilized by `go get`. +type ProjectIdentifier struct { + ProjectRoot ProjectRoot + Source string +} + +// Less compares by ProjectRoot then normalized Source. +func (i ProjectIdentifier) Less(j ProjectIdentifier) bool { + if i.ProjectRoot < j.ProjectRoot { + return true + } + if j.ProjectRoot < i.ProjectRoot { + return false + } + return i.normalizedSource() < j.normalizedSource() +} + +func (i ProjectIdentifier) eq(j ProjectIdentifier) bool { + if i.ProjectRoot != j.ProjectRoot { + return false + } + if i.Source == j.Source { + return true + } + + if (i.Source == "" && j.Source == string(j.ProjectRoot)) || + (j.Source == "" && i.Source == string(i.ProjectRoot)) { + return true + } + + return false +} + +// equiv will check if the two identifiers are "equivalent," under special +// rules. +// +// Given that the ProjectRoots are equal (==), equivalency occurs if: +// +// 1. The Sources are equal (==), OR +// 2. The LEFT (the receiver) Source is non-empty, and the right +// Source is empty. +// +// *This is asymmetry in this binary relation is intentional.* It facilitates +// the case where we allow for a ProjectIdentifier with an explicit Source +// to match one without. +func (i ProjectIdentifier) equiv(j ProjectIdentifier) bool { + if i.ProjectRoot != j.ProjectRoot { + return false + } + if i.Source == j.Source { + return true + } + + if i.Source != "" && j.Source == "" { + return true + } + + return false +} + +func (i ProjectIdentifier) normalizedSource() string { + if i.Source == "" { + return string(i.ProjectRoot) + } + return i.Source +} + +func (i ProjectIdentifier) String() string { + if i.Source == "" || i.Source == string(i.ProjectRoot) { + return string(i.ProjectRoot) + } + return fmt.Sprintf("%s (from %s)", i.ProjectRoot, i.Source) +} + +func (i ProjectIdentifier) normalize() ProjectIdentifier { + if i.Source == "" { + i.Source = string(i.ProjectRoot) + } + + return i +} + +// ProjectProperties comprise the properties that can be attached to a +// ProjectRoot. +// +// In general, these are declared in the context of a map of ProjectRoot to its +// ProjectProperties; they make little sense without their corresponding +// ProjectRoot. +type ProjectProperties struct { + Source string + Constraint Constraint +} + +// bimodalIdentifiers are used to track work to be done in the unselected queue. +type bimodalIdentifier struct { + id ProjectIdentifier + // List of packages required within/under the ProjectIdentifier + pl []string + // prefv is used to indicate a 'preferred' version. This is expected to be + // derived from a dep's lock data, or else is empty. + prefv Version + // Indicates that the bmi came from the root project originally + fromRoot bool +} + +type atom struct { + id ProjectIdentifier + v Version +} + +// With a random revision and no name, collisions are...unlikely +var nilpa = atom{ + v: Revision(strconv.FormatInt(rand.Int63(), 36)), +} + +type atomWithPackages struct { + a atom + pl []string +} + +// bmi converts an atomWithPackages into a bimodalIdentifier. +// +// This is mostly intended for (read-only) trace use, so the package list slice +// is not copied. It is the callers responsibility to not modify the pl slice, +// lest that backpropagate and cause inconsistencies. +func (awp atomWithPackages) bmi() bimodalIdentifier { + return bimodalIdentifier{ + id: awp.a.id, + pl: awp.pl, + } +} + +// completeDep (name hopefully to change) provides the whole picture of a +// dependency - the root (repo and project, since currently we assume the two +// are the same) name, a constraint, and the actual packages needed that are +// under that root. +type completeDep struct { + // The base workingConstraint + workingConstraint + // The specific packages required from the ProjectDep + pl []string +} + +// dependency represents an incomplete edge in the depgraph. It has a +// fully-realized atom as the depender (the tail/source of the edge), and a set +// of requirements that any atom to be attached at the head/target must satisfy. +type dependency struct { + depender atom + dep completeDep +} diff --git a/vendor/github.com/golang/dep/gps/internal/pb/pb.go b/vendor/github.com/golang/dep/gps/internal/pb/pb.go new file mode 100644 index 00000000..f622f388 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/internal/pb/pb.go @@ -0,0 +1,8 @@ +// Copyright 2017 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 pb provides generated Protocol Buffers for cache serialization. +package pb + +//go:generate protoc --go_out=. source_cache.proto diff --git a/vendor/github.com/golang/dep/gps/internal/pb/source_cache.pb.go b/vendor/github.com/golang/dep/gps/internal/pb/source_cache.pb.go new file mode 100644 index 00000000..8f9436c9 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/internal/pb/source_cache.pb.go @@ -0,0 +1,199 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: source_cache.proto + +/* +Package pb is a generated protocol buffer package. + +It is generated from these files: + source_cache.proto + +It has these top-level messages: + Constraint + ProjectProperties + LockedProject +*/ +package pb + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package + +type Constraint_Type int32 + +const ( + Constraint_Revision Constraint_Type = 0 + Constraint_Branch Constraint_Type = 1 + Constraint_DefaultBranch Constraint_Type = 2 + Constraint_Version Constraint_Type = 3 + Constraint_Semver Constraint_Type = 4 +) + +var Constraint_Type_name = map[int32]string{ + 0: "Revision", + 1: "Branch", + 2: "DefaultBranch", + 3: "Version", + 4: "Semver", +} +var Constraint_Type_value = map[string]int32{ + "Revision": 0, + "Branch": 1, + "DefaultBranch": 2, + "Version": 3, + "Semver": 4, +} + +func (x Constraint_Type) String() string { + return proto.EnumName(Constraint_Type_name, int32(x)) +} +func (Constraint_Type) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{0, 0} } + +// Constraint is a serializable representation of a gps.Constraint or gps.UnpairedVersion. +type Constraint struct { + Type Constraint_Type `protobuf:"varint,1,opt,name=type,enum=pb.Constraint_Type" json:"type,omitempty"` + Value string `protobuf:"bytes,2,opt,name=value" json:"value,omitempty"` +} + +func (m *Constraint) Reset() { *m = Constraint{} } +func (m *Constraint) String() string { return proto.CompactTextString(m) } +func (*Constraint) ProtoMessage() {} +func (*Constraint) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } + +func (m *Constraint) GetType() Constraint_Type { + if m != nil { + return m.Type + } + return Constraint_Revision +} + +func (m *Constraint) GetValue() string { + if m != nil { + return m.Value + } + return "" +} + +// ProjectProperties is a serializable representation of gps.ProjectRoot and gps.ProjectProperties. +type ProjectProperties struct { + Root string `protobuf:"bytes,1,opt,name=root" json:"root,omitempty"` + Source string `protobuf:"bytes,2,opt,name=source" json:"source,omitempty"` + Constraint *Constraint `protobuf:"bytes,3,opt,name=constraint" json:"constraint,omitempty"` +} + +func (m *ProjectProperties) Reset() { *m = ProjectProperties{} } +func (m *ProjectProperties) String() string { return proto.CompactTextString(m) } +func (*ProjectProperties) ProtoMessage() {} +func (*ProjectProperties) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } + +func (m *ProjectProperties) GetRoot() string { + if m != nil { + return m.Root + } + return "" +} + +func (m *ProjectProperties) GetSource() string { + if m != nil { + return m.Source + } + return "" +} + +func (m *ProjectProperties) GetConstraint() *Constraint { + if m != nil { + return m.Constraint + } + return nil +} + +// LockedProject is a serializable representation of gps.LockedProject. +type LockedProject struct { + Root string `protobuf:"bytes,1,opt,name=root" json:"root,omitempty"` + Source string `protobuf:"bytes,2,opt,name=source" json:"source,omitempty"` + UnpairedVersion *Constraint `protobuf:"bytes,3,opt,name=unpairedVersion" json:"unpairedVersion,omitempty"` + Revision string `protobuf:"bytes,4,opt,name=revision" json:"revision,omitempty"` + Packages []string `protobuf:"bytes,5,rep,name=packages" json:"packages,omitempty"` +} + +func (m *LockedProject) Reset() { *m = LockedProject{} } +func (m *LockedProject) String() string { return proto.CompactTextString(m) } +func (*LockedProject) ProtoMessage() {} +func (*LockedProject) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } + +func (m *LockedProject) GetRoot() string { + if m != nil { + return m.Root + } + return "" +} + +func (m *LockedProject) GetSource() string { + if m != nil { + return m.Source + } + return "" +} + +func (m *LockedProject) GetUnpairedVersion() *Constraint { + if m != nil { + return m.UnpairedVersion + } + return nil +} + +func (m *LockedProject) GetRevision() string { + if m != nil { + return m.Revision + } + return "" +} + +func (m *LockedProject) GetPackages() []string { + if m != nil { + return m.Packages + } + return nil +} + +func init() { + proto.RegisterType((*Constraint)(nil), "pb.Constraint") + proto.RegisterType((*ProjectProperties)(nil), "pb.ProjectProperties") + proto.RegisterType((*LockedProject)(nil), "pb.LockedProject") + proto.RegisterEnum("pb.Constraint_Type", Constraint_Type_name, Constraint_Type_value) +} + +func init() { proto.RegisterFile("source_cache.proto", fileDescriptor0) } + +var fileDescriptor0 = []byte{ + // 294 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x91, 0x4f, 0x4f, 0xc2, 0x40, + 0x14, 0xc4, 0x5d, 0x28, 0x08, 0x0f, 0x41, 0x78, 0x1a, 0xd3, 0x78, 0x6a, 0x7a, 0x91, 0x53, 0x0f, + 0x78, 0xf1, 0xac, 0x1e, 0x39, 0x90, 0x6a, 0xbc, 0x9a, 0xed, 0xf2, 0x94, 0x0a, 0x76, 0x37, 0xaf, + 0xdb, 0x26, 0x7c, 0x14, 0x3f, 0x84, 0xdf, 0xd1, 0x74, 0x59, 0xf1, 0x4f, 0xe2, 0xc1, 0x5b, 0xa7, + 0xf3, 0xcb, 0xce, 0xcc, 0x2e, 0x60, 0xa9, 0x2b, 0x56, 0xf4, 0xa8, 0xa4, 0x5a, 0x51, 0x62, 0x58, + 0x5b, 0x8d, 0x2d, 0x93, 0xc5, 0x6f, 0x02, 0xe0, 0x46, 0x17, 0xa5, 0x65, 0x99, 0x17, 0x16, 0x2f, + 0x20, 0xb0, 0x5b, 0x43, 0xa1, 0x88, 0xc4, 0x74, 0x34, 0x3b, 0x49, 0x4c, 0x96, 0x7c, 0xb9, 0xc9, + 0xfd, 0xd6, 0x50, 0xea, 0x00, 0x3c, 0x85, 0x4e, 0x2d, 0x37, 0x15, 0x85, 0xad, 0x48, 0x4c, 0xfb, + 0xe9, 0x4e, 0xc4, 0x73, 0x08, 0x1a, 0x06, 0x8f, 0xa0, 0x97, 0x52, 0x9d, 0x97, 0xb9, 0x2e, 0xc6, + 0x07, 0x08, 0xd0, 0xbd, 0x66, 0x59, 0xa8, 0xd5, 0x58, 0xe0, 0x04, 0x86, 0xb7, 0xf4, 0x24, 0xab, + 0x8d, 0xf5, 0xbf, 0x5a, 0x38, 0x80, 0xc3, 0x07, 0x62, 0xc7, 0xb6, 0x1b, 0xf6, 0x8e, 0x5e, 0x6b, + 0xe2, 0x71, 0x10, 0x6b, 0x98, 0x2c, 0x58, 0xbf, 0x90, 0xb2, 0x0b, 0xd6, 0x86, 0xd8, 0xe6, 0x54, + 0x22, 0x42, 0xc0, 0x5a, 0x5b, 0xd7, 0xb0, 0x9f, 0xba, 0x6f, 0x3c, 0x83, 0xee, 0x6e, 0x9e, 0x6f, + 0xe3, 0x15, 0x26, 0x00, 0x6a, 0xdf, 0x3e, 0x6c, 0x47, 0x62, 0x3a, 0x98, 0x8d, 0x7e, 0x6e, 0x4a, + 0xbf, 0x11, 0xf1, 0xbb, 0x80, 0xe1, 0x5c, 0xab, 0x35, 0x2d, 0x7d, 0xee, 0xbf, 0xd2, 0xae, 0xe0, + 0xb8, 0x2a, 0x8c, 0xcc, 0x99, 0x96, 0x7e, 0xcf, 0x1f, 0x91, 0xbf, 0x31, 0x3c, 0x87, 0x1e, 0xfb, + 0xeb, 0x0a, 0x03, 0x77, 0xe6, 0x5e, 0x37, 0x9e, 0x91, 0x6a, 0x2d, 0x9f, 0xa9, 0x0c, 0x3b, 0x51, + 0xbb, 0xf1, 0x3e, 0x75, 0xd6, 0x75, 0xef, 0x78, 0xf9, 0x11, 0x00, 0x00, 0xff, 0xff, 0xbd, 0x52, + 0x77, 0xb3, 0xdd, 0x01, 0x00, 0x00, +} diff --git a/vendor/github.com/golang/dep/gps/internal/pb/source_cache.proto b/vendor/github.com/golang/dep/gps/internal/pb/source_cache.proto new file mode 100644 index 00000000..7245318e --- /dev/null +++ b/vendor/github.com/golang/dep/gps/internal/pb/source_cache.proto @@ -0,0 +1,36 @@ +// Copyright 2017 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. + +syntax = "proto3"; +package pb; + +// Constraint is a serializable representation of a gps.Constraint or gps.UnpairedVersion. +message Constraint { + enum Type { + Revision = 0; + Branch = 1; + DefaultBranch = 2; + Version = 3; + Semver = 4; + } + Type type = 1; + string value = 2; + //TODO strongly typed Semver field +} + +// ProjectProperties is a serializable representation of gps.ProjectRoot and gps.ProjectProperties. +message ProjectProperties { + string root = 1; + string source = 2; + Constraint constraint = 3; +} + +// LockedProject is a serializable representation of gps.LockedProject. +message LockedProject { + string root = 1; + string source = 2; + Constraint unpairedVersion = 3; + string revision = 4; + repeated string packages = 5; +} diff --git a/vendor/github.com/golang/dep/gps/lock.go b/vendor/github.com/golang/dep/gps/lock.go new file mode 100644 index 00000000..8b776213 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/lock.go @@ -0,0 +1,235 @@ +// Copyright 2017 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 gps + +import ( + "bytes" + "fmt" + "sort" +) + +// Lock represents data from a lock file (or however the implementing tool +// chooses to store it) at a particular version that is relevant to the +// satisfiability solving process. +// +// In general, the information produced by gps on finding a successful +// solution is all that would be necessary to constitute a lock file, though +// tools can include whatever other information they want in their storage. +type Lock interface { + // The hash digest of inputs to gps that resulted in this lock data. + InputsDigest() []byte + + // Projects returns the list of LockedProjects contained in the lock data. + Projects() []LockedProject +} + +// LocksAreEq checks if two locks are equivalent. This checks that +// all contained LockedProjects are equal, and optionally (if the third +// parameter is true) whether the locks' input hashes are equal. +func LocksAreEq(l1, l2 Lock, checkHash bool) bool { + // Cheapest ops first + if checkHash && !bytes.Equal(l1.InputsDigest(), l2.InputsDigest()) { + return false + } + + p1, p2 := l1.Projects(), l2.Projects() + if len(p1) != len(p2) { + return false + } + + p1 = sortedLockedProjects(p1) + p2 = sortedLockedProjects(p2) + + for k, lp := range p1 { + if !lp.Eq(p2[k]) { + return false + } + } + return true +} + +// sortedLockedProjects returns a sorted copy of lps, or itself if already sorted. +func sortedLockedProjects(lps []LockedProject) []LockedProject { + if len(lps) <= 1 || sort.SliceIsSorted(lps, func(i, j int) bool { + return lps[i].Ident().Less(lps[j].Ident()) + }) { + return lps + } + cp := make([]LockedProject, len(lps)) + copy(cp, lps) + sort.Slice(cp, func(i, j int) bool { + return cp[i].Ident().Less(cp[j].Ident()) + }) + return cp +} + +// LockedProject is a single project entry from a lock file. It expresses the +// project's name, one or both of version and underlying revision, the network +// URI for accessing it, the path at which it should be placed within a vendor +// directory, and the packages that are used in it. +type LockedProject struct { + pi ProjectIdentifier + v UnpairedVersion + r Revision + pkgs []string +} + +// SimpleLock is a helper for tools to easily describe lock data when they know +// that no hash, or other complex information, is available. +type SimpleLock []LockedProject + +var _ Lock = SimpleLock{} + +// InputsDigest always returns an empty string for SimpleLock. This makes it useless +// as a stable lock to be written to disk, but still useful for some ephemeral +// purposes. +func (SimpleLock) InputsDigest() []byte { + return nil +} + +// Projects returns the entire contents of the SimpleLock. +func (l SimpleLock) Projects() []LockedProject { + return l +} + +// NewLockedProject creates a new LockedProject struct with a given +// ProjectIdentifier (name and optional upstream source URL), version. and list +// of packages required from the project. +// +// Note that passing a nil version will cause a panic. This is a correctness +// measure to ensure that the solver is never exposed to a version-less lock +// entry. Such a case would be meaningless - the solver would have no choice but +// to simply dismiss that project. By creating a hard failure case via panic +// instead, we are trying to avoid inflicting the resulting pain on the user by +// instead forcing a decision on the Analyzer implementation. +func NewLockedProject(id ProjectIdentifier, v Version, pkgs []string) LockedProject { + if v == nil { + panic("must provide a non-nil version to create a LockedProject") + } + + lp := LockedProject{ + pi: id, + pkgs: pkgs, + } + + switch tv := v.(type) { + case Revision: + lp.r = tv + case branchVersion: + lp.v = tv + case semVersion: + lp.v = tv + case plainVersion: + lp.v = tv + case versionPair: + lp.r = tv.r + lp.v = tv.v + } + + return lp +} + +// Ident returns the identifier describing the project. This includes both the +// local name (the root name by which the project is referenced in import paths) +// and the network name, where the upstream source lives. +func (lp LockedProject) Ident() ProjectIdentifier { + return lp.pi +} + +// Version assembles together whatever version and/or revision data is +// available into a single Version. +func (lp LockedProject) Version() Version { + if lp.r == "" { + return lp.v + } + + if lp.v == nil { + return lp.r + } + + return lp.v.Pair(lp.r) +} + +// Eq checks if two LockedProject instances are equal. +func (lp LockedProject) Eq(lp2 LockedProject) bool { + if lp.pi != lp2.pi { + return false + } + + if lp.r != lp2.r { + return false + } + + if len(lp.pkgs) != len(lp2.pkgs) { + return false + } + + for k, v := range lp.pkgs { + if lp2.pkgs[k] != v { + return false + } + } + + v1n := lp.v == nil + v2n := lp2.v == nil + + if v1n != v2n { + return false + } + + if !v1n && !lp.v.Matches(lp2.v) { + return false + } + + return true +} + +// Packages returns the list of packages from within the LockedProject that are +// actually used in the import graph. Some caveats: +// +// * The names given are relative to the root import path for the project. If +// the root package itself is imported, it's represented as ".". +// * Just because a package path isn't included in this list doesn't mean it's +// safe to remove - it could contain C files, or other assets, that can't be +// safely removed. +// * The slice is not a copy. If you need to modify it, copy it first. +func (lp LockedProject) Packages() []string { + return lp.pkgs +} + +func (lp LockedProject) String() string { + return fmt.Sprintf("%s@%s with packages: %v", + lp.Ident(), lp.Version(), lp.pkgs) +} + +type safeLock struct { + h []byte + p []LockedProject +} + +func (sl safeLock) InputsDigest() []byte { + return sl.h +} + +func (sl safeLock) Projects() []LockedProject { + return sl.p +} + +// prepLock ensures a lock is prepared and safe for use by the solver. This is +// mostly about defensively ensuring that no outside routine can modify the lock +// while the solver is in-flight. +// +// This is achieved by copying the lock's data into a new safeLock. +func prepLock(l Lock) safeLock { + pl := l.Projects() + + rl := safeLock{ + h: l.InputsDigest(), + p: make([]LockedProject, len(pl)), + } + copy(rl.p, pl) + + return rl +} diff --git a/vendor/github.com/golang/dep/gps/lock_test.go b/vendor/github.com/golang/dep/gps/lock_test.go new file mode 100644 index 00000000..3f9ca6ff --- /dev/null +++ b/vendor/github.com/golang/dep/gps/lock_test.go @@ -0,0 +1,184 @@ +// Copyright 2017 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 gps + +import ( + "reflect" + "sort" + "testing" +) + +func TestLockedProjectSorting(t *testing.T) { + // version doesn't matter here + lps := []LockedProject{ + NewLockedProject(mkPI("github.com/sdboyer/gps"), NewVersion("v0.10.0"), nil), + NewLockedProject(mkPI("foo"), NewVersion("nada"), nil), + NewLockedProject(mkPI("bar"), NewVersion("zip"), nil), + NewLockedProject(mkPI("qux"), NewVersion("zilch"), nil), + } + lps2 := make([]LockedProject, len(lps)) + copy(lps2, lps) + + sort.SliceStable(lps2, func(i, j int) bool { + return lps2[i].Ident().Less(lps2[j].Ident()) + }) + + // only the two should have switched positions + lps[0], lps[2] = lps[2], lps[0] + if !reflect.DeepEqual(lps, lps2) { + t.Errorf("SortLockedProject did not sort as expected:\n\t(GOT) %s\n\t(WNT) %s", lps2, lps) + } +} + +func TestLockedProjectsEq(t *testing.T) { + lps := []LockedProject{ + NewLockedProject(mkPI("github.com/sdboyer/gps"), NewVersion("v0.10.0"), []string{"gps"}), + NewLockedProject(mkPI("github.com/sdboyer/gps"), NewVersion("v0.10.0"), nil), + NewLockedProject(mkPI("github.com/sdboyer/gps"), NewVersion("v0.10.0"), []string{"gps", "flugle"}), + NewLockedProject(mkPI("foo"), NewVersion("nada"), []string{"foo"}), + NewLockedProject(mkPI("github.com/sdboyer/gps"), NewVersion("v0.10.0"), []string{"flugle", "gps"}), + NewLockedProject(mkPI("github.com/sdboyer/gps"), NewVersion("v0.10.0").Pair("278a227dfc3d595a33a77ff3f841fd8ca1bc8cd0"), []string{"gps"}), + NewLockedProject(mkPI("github.com/sdboyer/gps"), NewVersion("v0.11.0"), []string{"gps"}), + NewLockedProject(mkPI("github.com/sdboyer/gps"), Revision("278a227dfc3d595a33a77ff3f841fd8ca1bc8cd0"), []string{"gps"}), + } + + fix := map[string]struct { + l1, l2 int + shouldeq bool + err string + }{ + "with self": {0, 0, true, "lp does not eq self"}, + "with different revision": {0, 5, false, "should not eq with different rev"}, + "with different versions": {0, 6, false, "should not eq with different version"}, + "with same revsion": {5, 5, true, "should eq with same rev"}, + "with empty pkg": {0, 1, false, "should not eq when other pkg list is empty"}, + "with long pkg list": {0, 2, false, "should not eq when other pkg list is longer"}, + "with different orders": {2, 4, false, "should not eq when pkg lists are out of order"}, + "with different lp": {0, 3, false, "should not eq totally different lp"}, + "with only rev": {7, 7, true, "should eq with only rev"}, + "when only rev matches": {5, 7, false, "should not eq when only rev matches"}, + } + + for k, f := range fix { + k, f := k, f + t.Run(k, func(t *testing.T) { + if f.shouldeq { + if !lps[f.l1].Eq(lps[f.l2]) { + t.Error(f.err) + } + if !lps[f.l2].Eq(lps[f.l1]) { + t.Error(f.err + (" (reversed)")) + } + } else { + if lps[f.l1].Eq(lps[f.l2]) { + t.Error(f.err) + } + if lps[f.l2].Eq(lps[f.l1]) { + t.Error(f.err + (" (reversed)")) + } + } + }) + } +} + +func TestLocksAreEq(t *testing.T) { + gpl := NewLockedProject(mkPI("github.com/sdboyer/gps"), NewVersion("v0.10.0").Pair("278a227dfc3d595a33a77ff3f841fd8ca1bc8cd0"), []string{"gps"}) + svpl := NewLockedProject(mkPI("github.com/Masterminds/semver"), NewVersion("v2.0.0"), []string{"semver"}) + bbbt := NewLockedProject(mkPI("github.com/beeblebrox/browntown"), NewBranch("master").Pair("63fc17eb7966a6f4cc0b742bf42731c52c4ac740"), []string{"browntown", "smoochies"}) + + l1 := solution{ + hd: []byte("foo"), + p: []LockedProject{ + gpl, + bbbt, + svpl, + }, + } + + l2 := solution{ + p: []LockedProject{ + svpl, + gpl, + }, + } + + if LocksAreEq(l1, l2, true) { + t.Fatal("should have failed on hash check") + } + + if LocksAreEq(l1, l2, false) { + t.Fatal("should have failed on length check") + } + + l2.p = append(l2.p, bbbt) + + if !LocksAreEq(l1, l2, false) { + t.Fatal("should be eq, must have failed on individual lp check") + } + + // ensure original input sort order is maintained + if !l1.p[0].Eq(gpl) { + t.Error("checking equality resorted l1") + } + if !l2.p[0].Eq(svpl) { + t.Error("checking equality resorted l2") + } + + l1.p[0] = NewLockedProject(mkPI("github.com/sdboyer/gps"), NewVersion("v0.11.0"), []string{"gps"}) + if LocksAreEq(l1, l2, false) { + t.Error("should fail when individual lp were not eq") + } +} + +func TestLockedProjectsString(t *testing.T) { + tt := []struct { + name string + lp LockedProject + want string + }{ + { + name: "full info", + lp: NewLockedProject(mkPI("github.com/sdboyer/gps"), NewVersion("v0.10.0"), []string{"gps"}), + want: "github.com/sdboyer/gps@v0.10.0 with packages: [gps]", + }, + { + name: "empty package list", + lp: NewLockedProject(mkPI("github.com/sdboyer/gps"), NewVersion("v0.10.0"), []string{}), + want: "github.com/sdboyer/gps@v0.10.0 with packages: []", + }, + { + name: "nil package", + lp: NewLockedProject(mkPI("github.com/sdboyer/gps"), NewVersion("v0.10.0"), nil), + want: "github.com/sdboyer/gps@v0.10.0 with packages: []", + }, + { + name: "with source", + lp: NewLockedProject( + ProjectIdentifier{ProjectRoot: "github.com/sdboyer/gps", Source: "github.com/another/repo"}, + NewVersion("v0.10.0"), []string{"."}), + want: "github.com/sdboyer/gps (from github.com/another/repo)@v0.10.0 with packages: [.]", + }, + { + name: "version pair", + lp: NewLockedProject(mkPI("github.com/sdboyer/gps"), NewVersion("v0.10.0").Pair("278a227dfc3d595a33a77ff3f841fd8ca1bc8cd0"), []string{"gps"}), + want: "github.com/sdboyer/gps@v0.10.0 with packages: [gps]", + }, + { + name: "revision only", + lp: NewLockedProject(mkPI("github.com/sdboyer/gps"), Revision("278a227dfc3d595a33a77ff3f841fd8ca1bc8cd0"), []string{"gps"}), + want: "github.com/sdboyer/gps@278a227dfc3d595a33a77ff3f841fd8ca1bc8cd0 with packages: [gps]", + }, + } + + for _, tc := range tt { + t.Run(tc.name, func(t *testing.T) { + s := tc.lp.String() + if tc.want != s { + t.Fatalf("want %s, got %s", tc.want, s) + } + }) + } + +} diff --git a/vendor/github.com/golang/dep/gps/lockdiff.go b/vendor/github.com/golang/dep/gps/lockdiff.go new file mode 100644 index 00000000..839b49c5 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/lockdiff.go @@ -0,0 +1,245 @@ +// Copyright 2017 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 gps + +import ( + "encoding/hex" + "fmt" + "sort" + "strings" +) + +// StringDiff represents a modified string value. +// * Added: Previous = nil, Current != nil +// * Deleted: Previous != nil, Current = nil +// * Modified: Previous != nil, Current != nil +// * No Change: Previous = Current, or a nil pointer +type StringDiff struct { + Previous string + Current string +} + +func (diff *StringDiff) String() string { + if diff == nil { + return "" + } + + if diff.Previous == "" && diff.Current != "" { + return fmt.Sprintf("+ %s", diff.Current) + } + + if diff.Previous != "" && diff.Current == "" { + return fmt.Sprintf("- %s", diff.Previous) + } + + if diff.Previous != diff.Current { + return fmt.Sprintf("%s -> %s", diff.Previous, diff.Current) + } + + return diff.Current +} + +// LockDiff is the set of differences between an existing lock file and an updated lock file. +// Fields are only populated when there is a difference, otherwise they are empty. +type LockDiff struct { + HashDiff *StringDiff + Add []LockedProjectDiff + Remove []LockedProjectDiff + Modify []LockedProjectDiff +} + +// LockedProjectDiff contains the before and after snapshot of a project reference. +// Fields are only populated when there is a difference, otherwise they are empty. +type LockedProjectDiff struct { + Name ProjectRoot + Source *StringDiff + Version *StringDiff + Branch *StringDiff + Revision *StringDiff + Packages []StringDiff +} + +// DiffLocks compares two locks and identifies the differences between them. +// Returns nil if there are no differences. +func DiffLocks(l1 Lock, l2 Lock) *LockDiff { + // Default nil locks to empty locks, so that we can still generate a diff + if l1 == nil { + l1 = &SimpleLock{} + } + if l2 == nil { + l2 = &SimpleLock{} + } + + p1, p2 := l1.Projects(), l2.Projects() + + p1 = sortedLockedProjects(p1) + p2 = sortedLockedProjects(p2) + + diff := LockDiff{} + + h1 := hex.EncodeToString(l1.InputsDigest()) + h2 := hex.EncodeToString(l2.InputsDigest()) + if h1 != h2 { + diff.HashDiff = &StringDiff{Previous: h1, Current: h2} + } + + var i2next int + for i1 := 0; i1 < len(p1); i1++ { + lp1 := p1[i1] + pr1 := lp1.pi.ProjectRoot + + var matched bool + for i2 := i2next; i2 < len(p2); i2++ { + lp2 := p2[i2] + pr2 := lp2.pi.ProjectRoot + + switch strings.Compare(string(pr1), string(pr2)) { + case 0: // Found a matching project + matched = true + pdiff := DiffProjects(lp1, lp2) + if pdiff != nil { + diff.Modify = append(diff.Modify, *pdiff) + } + i2next = i2 + 1 // Don't evaluate to this again + case +1: // Found a new project + add := buildLockedProjectDiff(lp2) + diff.Add = append(diff.Add, add) + i2next = i2 + 1 // Don't evaluate to this again + continue // Keep looking for a matching project + case -1: // Project has been removed, handled below + continue + } + + break // Done evaluating this project, move onto the next + } + + if !matched { + remove := buildLockedProjectDiff(lp1) + diff.Remove = append(diff.Remove, remove) + } + } + + // Anything that still hasn't been evaluated are adds + for i2 := i2next; i2 < len(p2); i2++ { + lp2 := p2[i2] + add := buildLockedProjectDiff(lp2) + diff.Add = append(diff.Add, add) + } + + if diff.HashDiff == nil && len(diff.Add) == 0 && len(diff.Remove) == 0 && len(diff.Modify) == 0 { + return nil // The locks are the equivalent + } + return &diff +} + +func buildLockedProjectDiff(lp LockedProject) LockedProjectDiff { + s2 := lp.pi.Source + r2, b2, v2 := VersionComponentStrings(lp.Version()) + + var rev, version, branch, source *StringDiff + if s2 != "" { + source = &StringDiff{Previous: s2, Current: s2} + } + if r2 != "" { + rev = &StringDiff{Previous: r2, Current: r2} + } + if b2 != "" { + branch = &StringDiff{Previous: b2, Current: b2} + } + if v2 != "" { + version = &StringDiff{Previous: v2, Current: v2} + } + + add := LockedProjectDiff{ + Name: lp.pi.ProjectRoot, + Source: source, + Revision: rev, + Version: version, + Branch: branch, + Packages: make([]StringDiff, len(lp.Packages())), + } + for i, pkg := range lp.Packages() { + add.Packages[i] = StringDiff{Previous: pkg, Current: pkg} + } + return add +} + +// DiffProjects compares two projects and identifies the differences between them. +// Returns nil if there are no differences +func DiffProjects(lp1 LockedProject, lp2 LockedProject) *LockedProjectDiff { + diff := LockedProjectDiff{Name: lp1.pi.ProjectRoot} + + s1 := lp1.pi.Source + s2 := lp2.pi.Source + if s1 != s2 { + diff.Source = &StringDiff{Previous: s1, Current: s2} + } + + r1, b1, v1 := VersionComponentStrings(lp1.Version()) + r2, b2, v2 := VersionComponentStrings(lp2.Version()) + if r1 != r2 { + diff.Revision = &StringDiff{Previous: r1, Current: r2} + } + if b1 != b2 { + diff.Branch = &StringDiff{Previous: b1, Current: b2} + } + if v1 != v2 { + diff.Version = &StringDiff{Previous: v1, Current: v2} + } + + p1 := lp1.Packages() + p2 := lp2.Packages() + if !sort.StringsAreSorted(p1) { + p1 = make([]string, len(p1)) + copy(p1, lp1.Packages()) + sort.Strings(p1) + } + if !sort.StringsAreSorted(p2) { + p2 = make([]string, len(p2)) + copy(p2, lp2.Packages()) + sort.Strings(p2) + } + + var i2next int + for i1 := 0; i1 < len(p1); i1++ { + pkg1 := p1[i1] + + var matched bool + for i2 := i2next; i2 < len(p2); i2++ { + pkg2 := p2[i2] + + switch strings.Compare(pkg1, pkg2) { + case 0: // Found matching package + matched = true + i2next = i2 + 1 // Don't evaluate to this again + case +1: // Found a new package + add := StringDiff{Current: pkg2} + diff.Packages = append(diff.Packages, add) + i2next = i2 + 1 // Don't evaluate to this again + continue // Keep looking for a match + case -1: // Package has been removed (handled below) + continue + } + + break // Done evaluating this package, move onto the next + } + + if !matched { + diff.Packages = append(diff.Packages, StringDiff{Previous: pkg1}) + } + } + + // Anything that still hasn't been evaluated are adds + for i2 := i2next; i2 < len(p2); i2++ { + pkg2 := p2[i2] + add := StringDiff{Current: pkg2} + diff.Packages = append(diff.Packages, add) + } + + if diff.Source == nil && diff.Version == nil && diff.Revision == nil && len(diff.Packages) == 0 { + return nil // The projects are equivalent + } + return &diff +} diff --git a/vendor/github.com/golang/dep/gps/lockdiff_test.go b/vendor/github.com/golang/dep/gps/lockdiff_test.go new file mode 100644 index 00000000..46476281 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/lockdiff_test.go @@ -0,0 +1,501 @@ +// Copyright 2017 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 gps + +import ( + "bytes" + "encoding/hex" + "testing" +) + +func TestStringDiff_NoChange(t *testing.T) { + diff := StringDiff{Previous: "foo", Current: "foo"} + want := "foo" + got := diff.String() + if got != want { + t.Fatalf("Expected '%s', got '%s'", want, got) + } +} + +func TestStringDiff_Add(t *testing.T) { + diff := StringDiff{Current: "foo"} + got := diff.String() + if got != "+ foo" { + t.Fatalf("Expected '+ foo', got '%s'", got) + } +} + +func TestStringDiff_Remove(t *testing.T) { + diff := StringDiff{Previous: "foo"} + want := "- foo" + got := diff.String() + if got != want { + t.Fatalf("Expected '%s', got '%s'", want, got) + } +} + +func TestStringDiff_Modify(t *testing.T) { + diff := StringDiff{Previous: "foo", Current: "bar"} + want := "foo -> bar" + got := diff.String() + if got != want { + t.Fatalf("Expected '%s', got '%s'", want, got) + } +} + +func TestDiffProjects_NoChange(t *testing.T) { + p1 := NewLockedProject(mkPI("github.com/golang/dep/gps"), NewVersion("v0.10.0"), []string{"gps"}) + p2 := NewLockedProject(mkPI("github.com/golang/dep/gps"), NewVersion("v0.10.0"), []string{"gps"}) + + diff := DiffProjects(p1, p2) + if diff != nil { + t.Fatal("Expected the diff to be nil") + } +} + +func TestDiffProjects_Modify(t *testing.T) { + p1 := LockedProject{ + pi: ProjectIdentifier{ProjectRoot: "github.com/foo/bar"}, + v: NewBranch("master"), + r: "abc123", + pkgs: []string{"baz", "qux"}, + } + + p2 := LockedProject{ + pi: ProjectIdentifier{ProjectRoot: "github.com/foo/bar", Source: "https://github.com/mcfork/gps.git"}, + v: NewVersion("v1.0.0"), + r: "def456", + pkgs: []string{"baz", "derp"}, + } + + diff := DiffProjects(p1, p2) + if diff == nil { + t.Fatal("Expected the diff to be populated") + } + + wantSource := "+ https://github.com/mcfork/gps.git" + gotSource := diff.Source.String() + if gotSource != wantSource { + t.Fatalf("Expected diff.Source to be '%s', got '%s'", wantSource, diff.Source) + } + + wantVersion := "+ v1.0.0" + gotVersion := diff.Version.String() + if gotVersion != wantVersion { + t.Fatalf("Expected diff.Version to be '%s', got '%s'", wantVersion, gotVersion) + } + + wantRevision := "abc123 -> def456" + gotRevision := diff.Revision.String() + if gotRevision != wantRevision { + t.Fatalf("Expected diff.Revision to be '%s', got '%s'", wantRevision, gotRevision) + } + + wantBranch := "- master" + gotBranch := diff.Branch.String() + if gotBranch != wantBranch { + t.Fatalf("Expected diff.Branch to be '%s', got '%s'", wantBranch, gotBranch) + } + + fmtPkgs := func(pkgs []StringDiff) string { + b := bytes.NewBufferString("[") + for _, pkg := range pkgs { + b.WriteString(pkg.String()) + b.WriteString(",") + } + b.WriteString("]") + return b.String() + } + + wantPackages := "[+ derp,- qux,]" + gotPackages := fmtPkgs(diff.Packages) + if gotPackages != wantPackages { + t.Fatalf("Expected diff.Packages to be '%s', got '%s'", wantPackages, gotPackages) + } +} + +func TestDiffProjects_AddPackages(t *testing.T) { + p1 := LockedProject{ + pi: ProjectIdentifier{ProjectRoot: "github.com/foo/bar"}, + v: NewBranch("master"), + r: "abc123", + pkgs: []string{"foobar"}, + } + + p2 := LockedProject{ + pi: ProjectIdentifier{ProjectRoot: "github.com/foo/bar", Source: "https://github.com/mcfork/gps.git"}, + v: NewVersion("v1.0.0"), + r: "def456", + pkgs: []string{"bazqux", "foobar", "zugzug"}, + } + + diff := DiffProjects(p1, p2) + if diff == nil { + t.Fatal("Expected the diff to be populated") + } + + if len(diff.Packages) != 2 { + t.Fatalf("Expected diff.Packages to have 2 packages, got %d", len(diff.Packages)) + } + + want0 := "+ bazqux" + got0 := diff.Packages[0].String() + if got0 != want0 { + t.Fatalf("Expected diff.Packages[0] to contain %s, got %s", want0, got0) + } + + want1 := "+ zugzug" + got1 := diff.Packages[1].String() + if got1 != want1 { + t.Fatalf("Expected diff.Packages[1] to contain %s, got %s", want1, got1) + } +} + +func TestDiffProjects_RemovePackages(t *testing.T) { + p1 := LockedProject{ + pi: ProjectIdentifier{ProjectRoot: "github.com/foo/bar"}, + v: NewBranch("master"), + r: "abc123", + pkgs: []string{"athing", "foobar"}, + } + + p2 := LockedProject{ + pi: ProjectIdentifier{ProjectRoot: "github.com/foo/bar", Source: "https://github.com/mcfork/gps.git"}, + v: NewVersion("v1.0.0"), + r: "def456", + pkgs: []string{"bazqux"}, + } + + diff := DiffProjects(p1, p2) + if diff == nil { + t.Fatal("Expected the diff to be populated") + } + + if len(diff.Packages) > 3 { + t.Fatalf("Expected diff.Packages to have 3 packages, got %d", len(diff.Packages)) + } + + want0 := "- athing" + got0 := diff.Packages[0].String() + if got0 != want0 { + t.Fatalf("Expected diff.Packages[0] to contain %s, got %s", want0, got0) + } + + // diff.Packages[1] is '+ bazqux' + + want2 := "- foobar" + got2 := diff.Packages[2].String() + if got2 != want2 { + t.Fatalf("Expected diff.Packages[2] to contain %s, got %s", want2, got2) + } +} + +func TestDiffLocks_NoChange(t *testing.T) { + l1 := safeLock{ + h: []byte("abc123"), + p: []LockedProject{ + {pi: ProjectIdentifier{ProjectRoot: "github.com/foo/bar"}, v: NewVersion("v1.0.0")}, + }, + } + l2 := safeLock{ + h: []byte("abc123"), + p: []LockedProject{ + {pi: ProjectIdentifier{ProjectRoot: "github.com/foo/bar"}, v: NewVersion("v1.0.0")}, + }, + } + + diff := DiffLocks(l1, l2) + if diff != nil { + t.Fatal("Expected the diff to be nil") + } +} + +func TestDiffLocks_AddProjects(t *testing.T) { + l1 := safeLock{ + h: []byte("abc123"), + p: []LockedProject{ + {pi: ProjectIdentifier{ProjectRoot: "github.com/foo/bar"}, v: NewVersion("v1.0.0")}, + }, + } + l2 := safeLock{ + h: []byte("abc123"), + p: []LockedProject{ + { + pi: ProjectIdentifier{ProjectRoot: "github.com/baz/qux", Source: "https://github.com/mcfork/bazqux.git"}, + v: NewVersion("v0.5.0"), + r: "def456", + pkgs: []string{"p1", "p2"}, + }, + {pi: ProjectIdentifier{ProjectRoot: "github.com/foo/bar"}, v: NewVersion("v1.0.0")}, + {pi: ProjectIdentifier{ProjectRoot: "github.com/zug/zug"}, v: NewVersion("v1.0.0")}, + }, + } + + diff := DiffLocks(l1, l2) + if diff == nil { + t.Fatal("Expected the diff to be populated") + } + + if len(diff.Add) != 2 { + t.Fatalf("Expected diff.Add to have 2 projects, got %d", len(diff.Add)) + } + + want0 := "github.com/baz/qux" + got0 := string(diff.Add[0].Name) + if got0 != want0 { + t.Fatalf("Expected diff.Add[0] to contain %s, got %s", want0, got0) + } + + want1 := "github.com/zug/zug" + got1 := string(diff.Add[1].Name) + if got1 != want1 { + t.Fatalf("Expected diff.Add[1] to contain %s, got %s", want1, got1) + } + + add0 := diff.Add[0] + wantSource := "https://github.com/mcfork/bazqux.git" + gotSource := add0.Source.String() + if gotSource != wantSource { + t.Fatalf("Expected diff.Add[0].Source to be '%s', got '%s'", wantSource, add0.Source) + } + + wantVersion := "v0.5.0" + gotVersion := add0.Version.String() + if gotVersion != wantVersion { + t.Fatalf("Expected diff.Add[0].Version to be '%s', got '%s'", wantVersion, gotVersion) + } + + wantRevision := "def456" + gotRevision := add0.Revision.String() + if gotRevision != wantRevision { + t.Fatalf("Expected diff.Add[0].Revision to be '%s', got '%s'", wantRevision, gotRevision) + } + + wantBranch := "" + gotBranch := add0.Branch.String() + if gotBranch != wantBranch { + t.Fatalf("Expected diff.Add[0].Branch to be '%s', got '%s'", wantBranch, gotBranch) + } + + fmtPkgs := func(pkgs []StringDiff) string { + b := bytes.NewBufferString("[") + for _, pkg := range pkgs { + b.WriteString(pkg.String()) + b.WriteString(",") + } + b.WriteString("]") + return b.String() + } + + wantPackages := "[p1,p2,]" + gotPackages := fmtPkgs(add0.Packages) + if gotPackages != wantPackages { + t.Fatalf("Expected diff.Add[0].Packages to be '%s', got '%s'", wantPackages, gotPackages) + } +} + +func TestDiffLocks_RemoveProjects(t *testing.T) { + l1 := safeLock{ + h: []byte("abc123"), + p: []LockedProject{ + { + pi: ProjectIdentifier{ProjectRoot: "github.com/a/thing", Source: "https://github.com/mcfork/athing.git"}, + v: NewBranch("master"), + r: "def456", + pkgs: []string{"p1", "p2"}, + }, + {pi: ProjectIdentifier{ProjectRoot: "github.com/foo/bar"}, v: NewVersion("v1.0.0")}, + }, + } + l2 := safeLock{ + h: []byte("abc123"), + p: []LockedProject{ + {pi: ProjectIdentifier{ProjectRoot: "github.com/baz/qux"}, v: NewVersion("v1.0.0")}, + }, + } + + diff := DiffLocks(l1, l2) + if diff == nil { + t.Fatal("Expected the diff to be populated") + } + + if len(diff.Remove) != 2 { + t.Fatalf("Expected diff.Remove to have 2 projects, got %d", len(diff.Remove)) + } + + want0 := "github.com/a/thing" + got0 := string(diff.Remove[0].Name) + if got0 != want0 { + t.Fatalf("Expected diff.Remove[0] to contain %s, got %s", want0, got0) + } + + want1 := "github.com/foo/bar" + got1 := string(diff.Remove[1].Name) + if got1 != want1 { + t.Fatalf("Expected diff.Remove[1] to contain %s, got %s", want1, got1) + } + + remove0 := diff.Remove[0] + wantSource := "https://github.com/mcfork/athing.git" + gotSource := remove0.Source.String() + if gotSource != wantSource { + t.Fatalf("Expected diff.Remove[0].Source to be '%s', got '%s'", wantSource, remove0.Source) + } + + wantVersion := "" + gotVersion := remove0.Version.String() + if gotVersion != wantVersion { + t.Fatalf("Expected diff.Remove[0].Version to be '%s', got '%s'", wantVersion, gotVersion) + } + + wantRevision := "def456" + gotRevision := remove0.Revision.String() + if gotRevision != wantRevision { + t.Fatalf("Expected diff.Remove[0].Revision to be '%s', got '%s'", wantRevision, gotRevision) + } + + wantBranch := "master" + gotBranch := remove0.Branch.String() + if gotBranch != wantBranch { + t.Fatalf("Expected diff.Remove[0].Branch to be '%s', got '%s'", wantBranch, gotBranch) + } + + fmtPkgs := func(pkgs []StringDiff) string { + b := bytes.NewBufferString("[") + for _, pkg := range pkgs { + b.WriteString(pkg.String()) + b.WriteString(",") + } + b.WriteString("]") + return b.String() + } + + wantPackages := "[p1,p2,]" + gotPackages := fmtPkgs(remove0.Packages) + if gotPackages != wantPackages { + t.Fatalf("Expected diff.Remove[0].Packages to be '%s', got '%s'", wantPackages, gotPackages) + } +} + +func TestDiffLocks_ModifyProjects(t *testing.T) { + l1 := safeLock{ + h: []byte("abc123"), + p: []LockedProject{ + {pi: ProjectIdentifier{ProjectRoot: "github.com/foo/bar"}, v: NewVersion("v1.0.0")}, + {pi: ProjectIdentifier{ProjectRoot: "github.com/foo/bu"}, v: NewVersion("v1.0.0")}, + {pi: ProjectIdentifier{ProjectRoot: "github.com/zig/zag"}, v: NewVersion("v1.0.0")}, + }, + } + l2 := safeLock{ + h: []byte("abc123"), + p: []LockedProject{ + {pi: ProjectIdentifier{ProjectRoot: "github.com/baz/qux"}, v: NewVersion("v1.0.0")}, + {pi: ProjectIdentifier{ProjectRoot: "github.com/foo/bar"}, v: NewVersion("v2.0.0")}, + {pi: ProjectIdentifier{ProjectRoot: "github.com/zig/zag"}, v: NewVersion("v2.0.0")}, + {pi: ProjectIdentifier{ProjectRoot: "github.com/zug/zug"}, v: NewVersion("v1.0.0")}, + }, + } + + diff := DiffLocks(l1, l2) + if diff == nil { + t.Fatal("Expected the diff to be populated") + } + + if len(diff.Modify) != 2 { + t.Fatalf("Expected diff.Remove to have 2 projects, got %d", len(diff.Remove)) + } + + want0 := "github.com/foo/bar" + got0 := string(diff.Modify[0].Name) + if got0 != want0 { + t.Fatalf("Expected diff.Modify[0] to contain %s, got %s", want0, got0) + } + + want1 := "github.com/zig/zag" + got1 := string(diff.Modify[1].Name) + if got1 != want1 { + t.Fatalf("Expected diff.Modify[1] to contain %s, got %s", want1, got1) + } +} + +func TestDiffLocks_ModifyHash(t *testing.T) { + h1, _ := hex.DecodeString("abc123") + l1 := safeLock{ + h: h1, + p: []LockedProject{ + {pi: ProjectIdentifier{ProjectRoot: "github.com/foo/bar"}, v: NewVersion("v1.0.0")}, + }, + } + + h2, _ := hex.DecodeString("def456") + l2 := safeLock{ + h: h2, + p: []LockedProject{ + {pi: ProjectIdentifier{ProjectRoot: "github.com/foo/bar"}, v: NewVersion("v1.0.0")}, + }, + } + + diff := DiffLocks(l1, l2) + if diff == nil { + t.Fatal("Expected the diff to be populated") + } + + want := "abc123 -> def456" + got := diff.HashDiff.String() + if got != want { + t.Fatalf("Expected diff.HashDiff to be '%s', got '%s'", want, got) + } +} + +func TestDiffLocks_EmptyInitialLock(t *testing.T) { + h2, _ := hex.DecodeString("abc123") + l2 := safeLock{ + h: h2, + p: []LockedProject{ + {pi: ProjectIdentifier{ProjectRoot: "github.com/foo/bar"}, v: NewVersion("v1.0.0")}, + }, + } + + diff := DiffLocks(nil, l2) + + wantHash := "+ abc123" + gotHash := diff.HashDiff.String() + if gotHash != wantHash { + t.Fatalf("Expected diff.HashDiff to be '%s', got '%s'", wantHash, gotHash) + } + + if len(diff.Add) != 1 { + t.Fatalf("Expected diff.Add to contain 1 project, got %d", len(diff.Add)) + } +} + +func TestDiffLocks_EmptyFinalLock(t *testing.T) { + h1, _ := hex.DecodeString("abc123") + l1 := safeLock{ + h: h1, + p: []LockedProject{ + {pi: ProjectIdentifier{ProjectRoot: "github.com/foo/bar"}, v: NewVersion("v1.0.0")}, + }, + } + + diff := DiffLocks(l1, nil) + + wantHash := "- abc123" + gotHash := diff.HashDiff.String() + if gotHash != wantHash { + t.Fatalf("Expected diff.HashDiff to be '%s', got '%s'", wantHash, gotHash) + } + + if len(diff.Remove) != 1 { + t.Fatalf("Expected diff.Remove to contain 1 project, got %d", len(diff.Remove)) + } +} + +func TestDiffLocks_EmptyLocks(t *testing.T) { + diff := DiffLocks(nil, nil) + if diff != nil { + t.Fatal("Expected the diff to be empty") + } +} diff --git a/vendor/github.com/golang/dep/gps/manager_test.go b/vendor/github.com/golang/dep/gps/manager_test.go new file mode 100644 index 00000000..4551e608 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/manager_test.go @@ -0,0 +1,1053 @@ +// Copyright 2016 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 gps + +import ( + "bytes" + "context" + "fmt" + "io/ioutil" + "log" + "os" + "path" + "path/filepath" + "runtime" + "sort" + "sync" + "sync/atomic" + "testing" + "text/tabwriter" + "time" + + "github.com/golang/dep/internal/test" +) + +// An analyzer that passes nothing back, but doesn't error. This is the naive +// case - no constraints, no lock, and no errors. The SourceManager will +// interpret this as open/Any constraints on everything in the import graph. +type naiveAnalyzer struct{} + +func (naiveAnalyzer) DeriveManifestAndLock(string, ProjectRoot) (Manifest, Lock, error) { + return nil, nil, nil +} + +func (a naiveAnalyzer) Info() ProjectAnalyzerInfo { + return ProjectAnalyzerInfo{ + Name: "naive-analyzer", + Version: 1, + } +} + +func mkNaiveSM(t *testing.T) (*SourceMgr, func()) { + cpath, err := ioutil.TempDir("", "smcache") + if err != nil { + t.Fatalf("Failed to create temp dir: %s", err) + } + + sm, err := NewSourceManager(SourceManagerConfig{ + Cachedir: cpath, + Logger: log.New(test.Writer{TB: t}, "", 0), + }) + if err != nil { + t.Fatalf("Unexpected error on SourceManager creation: %s", err) + } + + return sm, func() { + sm.Release() + err := os.RemoveAll(cpath) + if err != nil { + t.Errorf("removeAll failed: %s", err) + } + } +} + +func remakeNaiveSM(osm *SourceMgr, t *testing.T) (*SourceMgr, func()) { + cpath := osm.cachedir + osm.Release() + + sm, err := NewSourceManager(SourceManagerConfig{ + Cachedir: cpath, + Logger: log.New(test.Writer{TB: t}, "", 0), + }) + if err != nil { + t.Fatalf("unexpected error on SourceManager recreation: %s", err) + } + + return sm, func() { + sm.Release() + err := os.RemoveAll(cpath) + if err != nil { + t.Errorf("removeAll failed: %s", err) + } + } +} + +func TestSourceManagerInit(t *testing.T) { + cpath, err := ioutil.TempDir("", "smcache") + if err != nil { + t.Errorf("Failed to create temp dir: %s", err) + } + cfg := SourceManagerConfig{ + Cachedir: cpath, + Logger: log.New(test.Writer{TB: t}, "", 0), + } + + sm, err := NewSourceManager(cfg) + + if err != nil { + t.Errorf("Unexpected error on SourceManager creation: %s", err) + } + + _, err = NewSourceManager(cfg) + if err == nil { + t.Errorf("Creating second SourceManager should have failed due to file lock contention") + } else if te, ok := err.(CouldNotCreateLockError); !ok { + t.Errorf("Should have gotten CouldNotCreateLockError error type, but got %T", te) + } + + if _, err = os.Stat(path.Join(cpath, "sm.lock")); err != nil { + t.Errorf("Global cache lock file not created correctly") + } + + sm.Release() + err = os.RemoveAll(cpath) + if err != nil { + t.Errorf("removeAll failed: %s", err) + } + + if _, err = os.Stat(path.Join(cpath, "sm.lock")); !os.IsNotExist(err) { + t.Fatalf("Global cache lock file not cleared correctly on Release()") + } + + err = os.MkdirAll(cpath, 0777) + if err != nil { + t.Errorf("Failed to re-create temp dir: %s", err) + } + defer func() { + err = os.RemoveAll(cpath) + if err != nil { + t.Errorf("removeAll failed: %s", err) + } + }() + // Set another one up at the same spot now, just to be sure + sm, err = NewSourceManager(cfg) + if err != nil { + t.Fatalf("Creating a second SourceManager should have succeeded when the first was released, but failed with err %s", err) + } + + sm.Release() +} + +func TestSourceInit(t *testing.T) { + // This test is a bit slow, skip it on -short + if testing.Short() { + t.Skip("Skipping project manager init test in short mode") + } + + cpath, err := ioutil.TempDir("", "smcache") + if err != nil { + t.Fatalf("Failed to create temp dir: %s", err) + } + + sm, err := NewSourceManager(SourceManagerConfig{ + Cachedir: cpath, + Logger: log.New(test.Writer{TB: t}, "", 0), + }) + if err != nil { + t.Fatalf("Unexpected error on SourceManager creation: %s", err) + } + + defer func() { + sm.Release() + err := os.RemoveAll(cpath) + if err != nil { + t.Errorf("removeAll failed: %s", err) + } + }() + + id := mkPI("github.com/sdboyer/gpkt").normalize() + pvl, err := sm.ListVersions(id) + if err != nil { + t.Errorf("Unexpected error during initial project setup/fetching %s", err) + } + + if len(pvl) != 7 { + t.Errorf("Expected seven version results from the test repo, got %v", len(pvl)) + } else { + expected := []PairedVersion{ + NewVersion("v2.0.0").Pair(Revision("4a54adf81c75375d26d376459c00d5ff9b703e5e")), + NewVersion("v1.1.0").Pair(Revision("b2cb48dda625f6640b34d9ffb664533359ac8b91")), + NewVersion("v1.0.0").Pair(Revision("bf85021c0405edbc4f3648b0603818d641674f72")), + newDefaultBranch("master").Pair(Revision("bf85021c0405edbc4f3648b0603818d641674f72")), + NewBranch("v1").Pair(Revision("e3777f683305eafca223aefe56b4e8ecf103f467")), + NewBranch("v1.1").Pair(Revision("f1fbc520489a98306eb28c235204e39fa8a89c84")), + NewBranch("v3").Pair(Revision("4a54adf81c75375d26d376459c00d5ff9b703e5e")), + } + + // SourceManager itself doesn't guarantee ordering; sort them here so we + // can dependably check output + SortPairedForUpgrade(pvl) + + for k, e := range expected { + if !pvl[k].Matches(e) { + t.Errorf("Expected version %s in position %v but got %s", e, k, pvl[k]) + } + } + } + + // Two birds, one stone - make sure the internal ProjectManager vlist cache + // works (or at least doesn't not work) by asking for the versions again, + // and do it through smcache to ensure its sorting works, as well. + smc := &bridge{ + sm: sm, + vlists: make(map[ProjectIdentifier][]Version), + s: &solver{mtr: newMetrics()}, + } + + vl, err := smc.listVersions(id) + if err != nil { + t.Errorf("Unexpected error during initial project setup/fetching %s", err) + } + + if len(vl) != 7 { + t.Errorf("Expected seven version results from the test repo, got %v", len(vl)) + } else { + expected := []Version{ + NewVersion("v2.0.0").Pair(Revision("4a54adf81c75375d26d376459c00d5ff9b703e5e")), + NewVersion("v1.1.0").Pair(Revision("b2cb48dda625f6640b34d9ffb664533359ac8b91")), + NewVersion("v1.0.0").Pair(Revision("bf85021c0405edbc4f3648b0603818d641674f72")), + newDefaultBranch("master").Pair(Revision("bf85021c0405edbc4f3648b0603818d641674f72")), + NewBranch("v1").Pair(Revision("e3777f683305eafca223aefe56b4e8ecf103f467")), + NewBranch("v1.1").Pair(Revision("f1fbc520489a98306eb28c235204e39fa8a89c84")), + NewBranch("v3").Pair(Revision("4a54adf81c75375d26d376459c00d5ff9b703e5e")), + } + + for k, e := range expected { + if !vl[k].Matches(e) { + t.Errorf("Expected version %s in position %v but got %s", e, k, vl[k]) + } + } + + if !vl[3].(versionPair).v.(branchVersion).isDefault { + t.Error("Expected master branch version to have isDefault flag, but it did not") + } + if vl[4].(versionPair).v.(branchVersion).isDefault { + t.Error("Expected v1 branch version not to have isDefault flag, but it did") + } + if vl[5].(versionPair).v.(branchVersion).isDefault { + t.Error("Expected v1.1 branch version not to have isDefault flag, but it did") + } + if vl[6].(versionPair).v.(branchVersion).isDefault { + t.Error("Expected v3 branch version not to have isDefault flag, but it did") + } + } + + present, err := smc.RevisionPresentIn(id, Revision("4a54adf81c75375d26d376459c00d5ff9b703e5e")) + if err != nil { + t.Errorf("Should have found revision in source, but got err: %s", err) + } else if !present { + t.Errorf("Should have found revision in source, but did not") + } + + // SyncSourceFor will ensure we have everything + err = smc.SyncSourceFor(id) + if err != nil { + t.Errorf("SyncSourceFor failed with unexpected error: %s", err) + } + + // Ensure that the appropriate cache dirs and files exist + _, err = os.Stat(filepath.Join(cpath, "sources", "https---github.com-sdboyer-gpkt", ".git")) + if err != nil { + t.Error("Cache repo does not exist in expected location") + } + + os.Stat(filepath.Join(cpath, "metadata", "github.com", "sdboyer", "gpkt", "cache.json")) + + // Ensure source existence values are what we expect + var exists bool + exists, err = sm.SourceExists(id) + if err != nil { + t.Errorf("Error on checking SourceExists: %s", err) + } + if !exists { + t.Error("Source should exist after non-erroring call to ListVersions") + } +} + +func TestDefaultBranchAssignment(t *testing.T) { + if testing.Short() { + t.Skip("Skipping default branch assignment test in short mode") + } + + sm, clean := mkNaiveSM(t) + defer clean() + + id := mkPI("github.com/sdboyer/test-multibranch") + v, err := sm.ListVersions(id) + if err != nil { + t.Errorf("Unexpected error during initial project setup/fetching %s", err) + } + + if len(v) != 3 { + t.Errorf("Expected three version results from the test repo, got %v", len(v)) + } else { + brev := Revision("fda020843ac81352004b9dca3fcccdd517600149") + mrev := Revision("9f9c3a591773d9b28128309ac7a9a72abcab267d") + expected := []PairedVersion{ + NewBranch("branchone").Pair(brev), + NewBranch("otherbranch").Pair(brev), + NewBranch("master").Pair(mrev), + } + + SortPairedForUpgrade(v) + + for k, e := range expected { + if !v[k].Matches(e) { + t.Errorf("Expected version %s in position %v but got %s", e, k, v[k]) + } + } + + if !v[0].(versionPair).v.(branchVersion).isDefault { + t.Error("Expected branchone branch version to have isDefault flag, but it did not") + } + if !v[0].(versionPair).v.(branchVersion).isDefault { + t.Error("Expected otherbranch branch version to have isDefault flag, but it did not") + } + if v[2].(versionPair).v.(branchVersion).isDefault { + t.Error("Expected master branch version not to have isDefault flag, but it did") + } + } +} + +func TestMgrMethodsFailWithBadPath(t *testing.T) { + // a symbol will always bork it up + bad := mkPI("foo/##&^").normalize() + sm, clean := mkNaiveSM(t) + defer clean() + + var err error + if _, err = sm.SourceExists(bad); err == nil { + t.Error("SourceExists() did not error on bad input") + } + if err = sm.SyncSourceFor(bad); err == nil { + t.Error("SyncSourceFor() did not error on bad input") + } + if _, err = sm.ListVersions(bad); err == nil { + t.Error("ListVersions() did not error on bad input") + } + if _, err = sm.RevisionPresentIn(bad, Revision("")); err == nil { + t.Error("RevisionPresentIn() did not error on bad input") + } + if _, err = sm.ListPackages(bad, nil); err == nil { + t.Error("ListPackages() did not error on bad input") + } + if _, _, err = sm.GetManifestAndLock(bad, nil, naiveAnalyzer{}); err == nil { + t.Error("GetManifestAndLock() did not error on bad input") + } + if err = sm.ExportProject(context.Background(), bad, nil, ""); err == nil { + t.Error("ExportProject() did not error on bad input") + } +} + +type sourceCreationTestFixture struct { + roots []ProjectIdentifier + namecount, srccount int +} + +func (f sourceCreationTestFixture) run(t *testing.T) { + t.Parallel() + sm, clean := mkNaiveSM(t) + defer clean() + + for _, pi := range f.roots { + _, err := sm.SourceExists(pi) + if err != nil { + t.Fatal(err) + } + } + + if len(sm.srcCoord.nameToURL) != f.namecount { + t.Errorf("want %v names in the name->url map, but got %v. contents: \n%v", f.namecount, len(sm.srcCoord.nameToURL), sm.srcCoord.nameToURL) + } + + if len(sm.srcCoord.srcs) != f.srccount { + t.Errorf("want %v gateways in the sources map, but got %v", f.srccount, len(sm.srcCoord.srcs)) + } + + var keys []string + for k := range sm.srcCoord.nameToURL { + keys = append(keys, k) + } + sort.Strings(keys) + + var buf bytes.Buffer + w := tabwriter.NewWriter(&buf, 0, 4, 2, ' ', 0) + fmt.Fprint(w, "NAME\tMAPPED URL\n") + for _, r := range keys { + fmt.Fprintf(w, "%s\t%s\n", r, sm.srcCoord.nameToURL[r]) + } + w.Flush() + t.Log("\n", buf.String()) + + t.Log("SRC KEYS") + for k := range sm.srcCoord.srcs { + t.Log(k) + } +} + +// This test is primarily about making sure that the logic around folding +// together different ways of referencing the same underlying resource - whether +// that be intentionally folding them, or intentionally keeping them separate - +// work as intended. +func TestSourceCreationCounts(t *testing.T) { + if testing.Short() { + t.Skip("Skipping slow test in short mode") + } + + fixtures := map[string]sourceCreationTestFixture{ + "gopkgin uniqueness": { + roots: []ProjectIdentifier{ + mkPI("gopkg.in/sdboyer/gpkt.v1"), + mkPI("gopkg.in/sdboyer/gpkt.v2"), + mkPI("gopkg.in/sdboyer/gpkt.v3"), + }, + namecount: 6, + srccount: 3, + }, + "gopkgin separation from github": { + roots: []ProjectIdentifier{ + mkPI("gopkg.in/sdboyer/gpkt.v1"), + mkPI("github.com/sdboyer/gpkt"), + }, + namecount: 4, + srccount: 2, + }, + "case variance across path and URL-based access": { + roots: []ProjectIdentifier{ + {ProjectRoot: ProjectRoot("github.com/sdboyer/gpkt"), Source: "https://github.com/Sdboyer/gpkt"}, + {ProjectRoot: ProjectRoot("github.com/sdboyer/gpkt"), Source: "https://github.com/SdbOyer/gpkt"}, + mkPI("github.com/sdboyer/gpkt"), + {ProjectRoot: ProjectRoot("github.com/sdboyer/gpkt"), Source: "https://github.com/sdboyeR/gpkt"}, + mkPI("github.com/sdboyeR/gpkt"), + }, + namecount: 6, + srccount: 1, + }, + } + + for name, fix := range fixtures { + t.Run(name, fix.run) + } +} + +func TestGetSources(t *testing.T) { + // This test is a tad slow, skip it on -short + if testing.Short() { + t.Skip("Skipping source setup test in short mode") + } + requiresBins(t, "git", "hg", "bzr") + + sm, clean := mkNaiveSM(t) + + pil := []ProjectIdentifier{ + mkPI("github.com/Masterminds/VCSTestRepo").normalize(), + mkPI("bitbucket.org/mattfarina/testhgrepo").normalize(), + mkPI("launchpad.net/govcstestbzrrepo").normalize(), + } + + ctx := context.Background() + // protects against premature release of sm + t.Run("inner", func(t *testing.T) { + for _, pi := range pil { + lpi := pi + t.Run(lpi.normalizedSource(), func(t *testing.T) { + t.Parallel() + + srcg, err := sm.srcCoord.getSourceGatewayFor(ctx, lpi) + if err != nil { + t.Errorf("unexpected error setting up source: %s", err) + return + } + + // Re-get the same, make sure they are the same + srcg2, err := sm.srcCoord.getSourceGatewayFor(ctx, lpi) + if err != nil { + t.Errorf("unexpected error re-getting source: %s", err) + } else if srcg != srcg2 { + t.Error("first and second sources are not eq") + } + + // All of them _should_ select https, so this should work + lpi.Source = "https://" + lpi.Source + srcg3, err := sm.srcCoord.getSourceGatewayFor(ctx, lpi) + if err != nil { + t.Errorf("unexpected error getting explicit https source: %s", err) + } else if srcg != srcg3 { + t.Error("explicit https source should reuse autodetected https source") + } + + // Now put in http, and they should differ + lpi.Source = "http://" + string(lpi.ProjectRoot) + srcg4, err := sm.srcCoord.getSourceGatewayFor(ctx, lpi) + if err != nil { + t.Errorf("unexpected error getting explicit http source: %s", err) + } else if srcg == srcg4 { + t.Error("explicit http source should create a new src") + } + }) + } + }) + + // nine entries (of which three are dupes): for each vcs, raw import path, + // the https url, and the http url. also three more from case folding of + // github.com/Masterminds/VCSTestRepo -> github.com/masterminds/vcstestrepo + if len(sm.srcCoord.nameToURL) != 12 { + t.Errorf("Should have twelve discrete entries in the nameToURL map, got %v", len(sm.srcCoord.nameToURL)) + } + clean() +} + +func TestFSCaseSensitivityConvergesSources(t *testing.T) { + if testing.Short() { + t.Skip("Skipping slow test in short mode") + } + + f := func(name string, pi1, pi2 ProjectIdentifier) { + t.Run(name, func(t *testing.T) { + t.Parallel() + sm, clean := mkNaiveSM(t) + defer clean() + + sm.SyncSourceFor(pi1) + sg1, err := sm.srcCoord.getSourceGatewayFor(context.Background(), pi1) + if err != nil { + t.Fatal(err) + } + + sm.SyncSourceFor(pi2) + sg2, err := sm.srcCoord.getSourceGatewayFor(context.Background(), pi2) + if err != nil { + t.Fatal(err) + } + + path1 := sg1.src.(*gitSource).repo.LocalPath() + t.Log("path1:", path1) + stat1, err := os.Stat(path1) + if err != nil { + t.Fatal(err) + } + path2 := sg2.src.(*gitSource).repo.LocalPath() + t.Log("path2:", path2) + stat2, err := os.Stat(path2) + if err != nil { + t.Fatal(err) + } + + same, count := os.SameFile(stat1, stat2), len(sm.srcCoord.srcs) + if same && count != 1 { + t.Log("are same, count", count) + t.Fatal("on case-insensitive filesystem, case-varying sources should have been folded together but were not") + } + if !same && count != 2 { + t.Log("not same, count", count) + t.Fatal("on case-sensitive filesystem, case-varying sources should not have been folded together, but were") + } + }) + } + + folded := mkPI("github.com/sdboyer/deptest").normalize() + casevar1 := mkPI("github.com/Sdboyer/deptest").normalize() + casevar2 := mkPI("github.com/SdboyeR/deptest").normalize() + f("folded first", folded, casevar1) + f("folded second", casevar1, folded) + f("both unfolded", casevar1, casevar2) +} + +// Regression test for #32 +func TestGetInfoListVersionsOrdering(t *testing.T) { + // This test is quite slow, skip it on -short + if testing.Short() { + t.Skip("Skipping slow test in short mode") + } + + sm, clean := mkNaiveSM(t) + defer clean() + + // setup done, now do the test + + id := mkPI("github.com/sdboyer/gpkt").normalize() + + _, _, err := sm.GetManifestAndLock(id, NewVersion("v1.0.0"), naiveAnalyzer{}) + if err != nil { + t.Errorf("Unexpected error from GetInfoAt %s", err) + } + + v, err := sm.ListVersions(id) + if err != nil { + t.Errorf("Unexpected error from ListVersions %s", err) + } + + if len(v) != 7 { + t.Errorf("Expected seven results from ListVersions, got %v", len(v)) + } +} + +func TestDeduceProjectRoot(t *testing.T) { + sm, clean := mkNaiveSM(t) + defer clean() + + in := "github.com/sdboyer/gps" + pr, err := sm.DeduceProjectRoot(in) + if err != nil { + t.Errorf("Problem while detecting root of %q %s", in, err) + } + if string(pr) != in { + t.Errorf("Wrong project root was deduced;\n\t(GOT) %s\n\t(WNT) %s", pr, in) + } + if sm.deduceCoord.rootxt.Len() != 1 { + t.Errorf("Root path trie should have one element after one deduction, has %v", sm.deduceCoord.rootxt.Len()) + } + + pr, err = sm.DeduceProjectRoot(in) + if err != nil { + t.Errorf("Problem while detecting root of %q %s", in, err) + } else if string(pr) != in { + t.Errorf("Wrong project root was deduced;\n\t(GOT) %s\n\t(WNT) %s", pr, in) + } + if sm.deduceCoord.rootxt.Len() != 1 { + t.Errorf("Root path trie should still have one element after performing the same deduction twice; has %v", sm.deduceCoord.rootxt.Len()) + } + + // Now do a subpath + sub := path.Join(in, "foo") + pr, err = sm.DeduceProjectRoot(sub) + if err != nil { + t.Errorf("Problem while detecting root of %q %s", sub, err) + } else if string(pr) != in { + t.Errorf("Wrong project root was deduced;\n\t(GOT) %s\n\t(WNT) %s", pr, in) + } + if sm.deduceCoord.rootxt.Len() != 1 { + t.Errorf("Root path trie should still have one element, as still only one unique root has gone in; has %v", sm.deduceCoord.rootxt.Len()) + } + + // Now do a fully different root, but still on github + in2 := "github.com/bagel/lox" + sub2 := path.Join(in2, "cheese") + pr, err = sm.DeduceProjectRoot(sub2) + if err != nil { + t.Errorf("Problem while detecting root of %q %s", sub2, err) + } else if string(pr) != in2 { + t.Errorf("Wrong project root was deduced;\n\t(GOT) %s\n\t(WNT) %s", pr, in) + } + if sm.deduceCoord.rootxt.Len() != 2 { + t.Errorf("Root path trie should have two elements, one for each unique root; has %v", sm.deduceCoord.rootxt.Len()) + } + + // Ensure that our prefixes are bounded by path separators + in4 := "github.com/bagel/loxx" + pr, err = sm.DeduceProjectRoot(in4) + if err != nil { + t.Errorf("Problem while detecting root of %q %s", in4, err) + } else if string(pr) != in4 { + t.Errorf("Wrong project root was deduced;\n\t(GOT) %s\n\t(WNT) %s", pr, in) + } + if sm.deduceCoord.rootxt.Len() != 3 { + t.Errorf("Root path trie should have three elements, one for each unique root; has %v", sm.deduceCoord.rootxt.Len()) + } + + // Ensure that vcs extension-based matching comes through + in5 := "ffffrrrraaaaaapppppdoesnotresolve.com/baz.git" + pr, err = sm.DeduceProjectRoot(in5) + if err != nil { + t.Errorf("Problem while detecting root of %q %s", in5, err) + } else if string(pr) != in5 { + t.Errorf("Wrong project root was deduced;\n\t(GOT) %s\n\t(WNT) %s", pr, in) + } + if sm.deduceCoord.rootxt.Len() != 4 { + t.Errorf("Root path trie should have four elements, one for each unique root; has %v", sm.deduceCoord.rootxt.Len()) + } +} + +func TestMultiFetchThreadsafe(t *testing.T) { + // This test is quite slow, skip it on -short + if testing.Short() { + t.Skip("Skipping slow test in short mode") + } + + projects := []ProjectIdentifier{ + mkPI("github.com/sdboyer/gps"), + mkPI("github.com/sdboyer/gpkt"), + { + ProjectRoot: ProjectRoot("github.com/sdboyer/gpkt"), + Source: "https://github.com/sdboyer/gpkt", + }, + mkPI("github.com/sdboyer/gogl"), + mkPI("github.com/sdboyer/gliph"), + mkPI("github.com/sdboyer/frozone"), + mkPI("gopkg.in/sdboyer/gpkt.v1"), + mkPI("gopkg.in/sdboyer/gpkt.v2"), + mkPI("github.com/Masterminds/VCSTestRepo"), + mkPI("github.com/go-yaml/yaml"), + mkPI("github.com/sirupsen/logrus"), + mkPI("github.com/Masterminds/semver"), + mkPI("github.com/Masterminds/vcs"), + //mkPI("bitbucket.org/sdboyer/withbm"), + //mkPI("bitbucket.org/sdboyer/nobm"), + } + + do := func(name string, sm SourceManager) { + t.Run(name, func(t *testing.T) { + // This gives us ten calls per op, per project, which should be(?) + // decently likely to reveal underlying concurrency problems + ops := 4 + cnum := len(projects) * ops * 10 + + for i := 0; i < cnum; i++ { + // Trigger all four ops on each project, then move on to the next + // project. + id, op := projects[(i/ops)%len(projects)], i%ops + // The count of times this op has been been invoked on this project + // (after the upcoming invocation) + opcount := i/(ops*len(projects)) + 1 + + switch op { + case 0: + t.Run(fmt.Sprintf("deduce:%v:%s", opcount, id), func(t *testing.T) { + t.Parallel() + if _, err := sm.DeduceProjectRoot(string(id.ProjectRoot)); err != nil { + t.Error(err) + } + }) + case 1: + t.Run(fmt.Sprintf("sync:%v:%s", opcount, id), func(t *testing.T) { + t.Parallel() + err := sm.SyncSourceFor(id) + if err != nil { + t.Error(err) + } + }) + case 2: + t.Run(fmt.Sprintf("listVersions:%v:%s", opcount, id), func(t *testing.T) { + t.Parallel() + vl, err := sm.ListVersions(id) + if err != nil { + t.Fatal(err) + } + if len(vl) == 0 { + t.Error("no versions returned") + } + }) + case 3: + t.Run(fmt.Sprintf("exists:%v:%s", opcount, id), func(t *testing.T) { + t.Parallel() + y, err := sm.SourceExists(id) + if err != nil { + t.Fatal(err) + } + if !y { + t.Error("said source does not exist") + } + }) + default: + panic(fmt.Sprintf("wtf, %s %v", id, op)) + } + } + }) + } + + sm, _ := mkNaiveSM(t) + do("first", sm) + + // Run the thing twice with a remade sm so that we cover both the cases of + // pre-existing and new clones. + // + // This triggers a release of the first sm, which is much of what we're + // testing here - that the release is complete and clean, and can be + // immediately followed by a new sm coming in. + sm2, clean := remakeNaiveSM(sm, t) + do("second", sm2) + clean() +} + +// Ensure that we don't see concurrent map writes when calling ListVersions. +// Regression test for https://github.com/sdboyer/gps/issues/156. +// +// Ideally this would be caught by TestMultiFetchThreadsafe, but perhaps the +// high degree of parallelism pretty much eliminates that as a realistic +// possibility? +func TestListVersionsRacey(t *testing.T) { + // This test is quite slow, skip it on -short + if testing.Short() { + t.Skip("Skipping slow test in short mode") + } + + sm, clean := mkNaiveSM(t) + defer clean() + + wg := &sync.WaitGroup{} + id := mkPI("github.com/sdboyer/gps") + for i := 0; i < 20; i++ { + wg.Add(1) + go func() { + _, err := sm.ListVersions(id) + if err != nil { + t.Errorf("listing versions failed with err %s", err.Error()) + } + wg.Done() + }() + } + + wg.Wait() +} + +func TestErrAfterRelease(t *testing.T) { + sm, clean := mkNaiveSM(t) + clean() + id := ProjectIdentifier{} + + _, err := sm.SourceExists(id) + if err == nil { + t.Errorf("SourceExists did not error after calling Release()") + } else if err != ErrSourceManagerIsReleased { + t.Errorf("SourceExists errored after Release(), but with unexpected error: %T %s", err, err.Error()) + } + + err = sm.SyncSourceFor(id) + if err == nil { + t.Errorf("SyncSourceFor did not error after calling Release()") + } else if err != ErrSourceManagerIsReleased { + t.Errorf("SyncSourceFor errored after Release(), but with unexpected error: %T %s", err, err.Error()) + } + + _, err = sm.ListVersions(id) + if err == nil { + t.Errorf("ListVersions did not error after calling Release()") + } else if err != ErrSourceManagerIsReleased { + t.Errorf("ListVersions errored after Release(), but with unexpected error: %T %s", err, err.Error()) + } + + _, err = sm.RevisionPresentIn(id, "") + if err == nil { + t.Errorf("RevisionPresentIn did not error after calling Release()") + } else if err != ErrSourceManagerIsReleased { + t.Errorf("RevisionPresentIn errored after Release(), but with unexpected error: %T %s", err, err.Error()) + } + + _, err = sm.ListPackages(id, nil) + if err == nil { + t.Errorf("ListPackages did not error after calling Release()") + } else if err != ErrSourceManagerIsReleased { + t.Errorf("ListPackages errored after Release(), but with unexpected error: %T %s", err, err.Error()) + } + + _, _, err = sm.GetManifestAndLock(id, nil, naiveAnalyzer{}) + if err == nil { + t.Errorf("GetManifestAndLock did not error after calling Release()") + } else if err != ErrSourceManagerIsReleased { + t.Errorf("GetManifestAndLock errored after Release(), but with unexpected error: %T %s", err, err.Error()) + } + + err = sm.ExportProject(context.Background(), id, nil, "") + if err == nil { + t.Errorf("ExportProject did not error after calling Release()") + } else if err != ErrSourceManagerIsReleased { + t.Errorf("ExportProject errored after Release(), but with unexpected error: %T %s", err, err.Error()) + } + + _, err = sm.DeduceProjectRoot("") + if err == nil { + t.Errorf("DeduceProjectRoot did not error after calling Release()") + } else if err != ErrSourceManagerIsReleased { + t.Errorf("DeduceProjectRoot errored after Release(), but with unexpected error: %T %s", err, err.Error()) + } +} + +func TestSignalHandling(t *testing.T) { + if testing.Short() { + t.Skip("Skipping slow test in short mode") + } + + sm, clean := mkNaiveSM(t) + + sigch := make(chan os.Signal) + sm.HandleSignals(sigch) + + sigch <- os.Interrupt + <-time.After(10 * time.Millisecond) + + if atomic.LoadInt32(&sm.releasing) != 1 { + t.Error("Releasing flag did not get set") + } + + clean() + + // Test again, this time with a running call + sm, clean = mkNaiveSM(t) + sm.HandleSignals(sigch) + + errchan := make(chan error) + go func() { + _, callerr := sm.DeduceProjectRoot("k8s.io/kubernetes") + errchan <- callerr + }() + go func() { sigch <- os.Interrupt }() + runtime.Gosched() + + callerr := <-errchan + if callerr == nil { + t.Error("network call could not have completed before cancellation, should have gotten an error") + } + if atomic.LoadInt32(&sm.releasing) != 1 { + t.Error("Releasing flag did not get set") + } + clean() + + sm, clean = mkNaiveSM(t) + // Ensure that handling also works after stopping and restarting itself, + // and that Release happens only once. + sm.UseDefaultSignalHandling() + sm.StopSignalHandling() + sm.HandleSignals(sigch) + + go func() { + _, callerr := sm.DeduceProjectRoot("k8s.io/kubernetes") + errchan <- callerr + }() + go func() { + sigch <- os.Interrupt + sm.Release() + }() + runtime.Gosched() + + after := time.After(2 * time.Second) + select { + case <-sm.qch: + case <-after: + t.Error("did not shut down in reasonable time") + } + + clean() +} + +func TestUnreachableSource(t *testing.T) { + // If a git remote is unreachable (maybe the server is only accessible behind a VPN, or + // something), we should return a clear error, not a panic. + if testing.Short() { + t.Skip("Skipping slow test in short mode") + } + + sm, clean := mkNaiveSM(t) + defer clean() + + id := mkPI("github.com/golang/notexist").normalize() + err := sm.SyncSourceFor(id) + if err == nil { + t.Error("expected err when listing versions of a bogus source, but got nil") + } +} + +func TestSupervisor(t *testing.T) { + bgc := context.Background() + ctx, cancelFunc := context.WithCancel(bgc) + superv := newSupervisor(ctx) + + ci := callInfo{ + name: "foo", + typ: 0, + } + + _, err := superv.start(ci) + if err != nil { + t.Fatal("unexpected err on setUpCall:", err) + } + + tc, exists := superv.running[ci] + if !exists { + t.Fatal("running call not recorded in map") + } + + if tc.count != 1 { + t.Fatalf("wrong count of running ci: wanted 1 got %v", tc.count) + } + + // run another, but via do + block, wait := make(chan struct{}), make(chan struct{}) + errchan := make(chan error) + go func() { + wait <- struct{}{} + err := superv.do(bgc, "foo", 0, func(ctx context.Context) error { + <-block + return nil + }) + errchan <- err + //if err != nil { + // t.Fatal("unexpected err on do() completion:", err) + //} + close(wait) + }() + <-wait + + superv.mu.Lock() + tc, exists = superv.running[ci] + if !exists { + t.Fatal("running call not recorded in map") + } + + // TODO (kris-nova) We need to disable this bypass here, and in the .travis.yml + // as soon as dep#501 is fixed + bypass := os.Getenv("DEPTESTBYPASS501") + if bypass != "" { + t.Log("bypassing tc.count check for running ci") + } else if tc.count != 2 { + t.Fatalf("wrong count of running ci: wanted 2 got %v", tc.count) + } + superv.mu.Unlock() + + close(block) + + possibleConcurrentError := <-errchan + if possibleConcurrentError != nil { + t.Fatal("unexpected err on do() completion:", err) + } + + <-wait + superv.mu.Lock() + if len(superv.ran) != 0 { + t.Fatal("should not record metrics until last one drops") + } + + tc, exists = superv.running[ci] + if !exists { + t.Fatal("running call not recorded in map") + } + + if tc.count != 1 { + t.Fatalf("wrong count of running ci: wanted 1 got %v", tc.count) + } + superv.mu.Unlock() + + superv.done(ci) + superv.mu.Lock() + ran, exists := superv.ran[0] + if !exists { + t.Fatal("should have metrics after closing last of a ci, but did not") + } + + if ran.count != 1 { + t.Fatalf("wrong count of serial runs of a call: wanted 1 got %v", ran.count) + } + superv.mu.Unlock() + + cancelFunc() + _, err = superv.start(ci) + if err == nil { + t.Fatal("should have errored on cm.run() after canceling cm's input context") + } + + superv.do(bgc, "foo", 0, func(ctx context.Context) error { + t.Fatal("calls should not be initiated by do() after main context is cancelled") + return nil + }) +} diff --git a/vendor/github.com/golang/dep/gps/manifest.go b/vendor/github.com/golang/dep/gps/manifest.go new file mode 100644 index 00000000..d36f8935 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/manifest.go @@ -0,0 +1,155 @@ +// Copyright 2017 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 gps + +import "github.com/golang/dep/gps/pkgtree" + +// Manifest represents manifest-type data for a project at a particular version. +// The constraints expressed in a manifest determine the set of versions that +// are acceptable to try for a given project. +// +// Expressing a constraint in a manifest does not guarantee that a particular +// dependency will be present. It only guarantees that if packages in the +// project specified by the dependency are discovered through static analysis of +// the (transitive) import graph, then they will conform to the constraint. +// +// This does entail that manifests can express constraints on projects they do +// not themselves import. This is by design, but its implications are complex. +// See the gps docs for more information: https://github.com/sdboyer/gps/wiki +type Manifest interface { + // Returns a list of project-level constraints. + DependencyConstraints() ProjectConstraints +} + +// RootManifest extends Manifest to add special controls over solving that are +// only afforded to the root project. +type RootManifest interface { + Manifest + + // Overrides returns a list of ProjectConstraints that will unconditionally + // supersede any ProjectConstraint declarations made in either the root + // manifest, or in any dependency's manifest. + // + // Overrides are a special control afforded only to root manifests. Tool + // users should be encouraged to use them only as a last resort; they do not + // "play well with others" (that is their express goal), and overreliance on + // them can harm the ecosystem as a whole. + Overrides() ProjectConstraints + + // IngoredPackages returns a pkgtree.IgnoredRuleset, which comprises a set + // of import paths, or import path patterns, that are to be ignored during + // solving. These ignored import paths can be within the root project, or + // part of other projects. Ignoring a package means that both it and its + // (unique) imports will be disregarded by all relevant solver operations. + // + // It is an error to include a package in both the ignored and required + // sets. + IgnoredPackages() *pkgtree.IgnoredRuleset + + // RequiredPackages returns a set of import paths to require. These packages + // are required to be present in any solution. The list can include main + // packages. + // + // It is meaningless to specify packages that are within the + // PackageTree of the ProjectRoot (though not an error, because the + // RootManifest itself does not report a ProjectRoot). + // + // It is an error to include a package in both the ignored and required + // sets. + RequiredPackages() map[string]bool +} + +// SimpleManifest is a helper for tools to enumerate manifest data. It's +// generally intended for ephemeral manifests, such as those Analyzers create on +// the fly for projects with no manifest metadata, or metadata through a foreign +// tool's idioms. +type SimpleManifest struct { + Deps ProjectConstraints +} + +var _ Manifest = SimpleManifest{} + +// DependencyConstraints returns the project's dependencies. +func (m SimpleManifest) DependencyConstraints() ProjectConstraints { + return m.Deps +} + +// simpleRootManifest exists so that we have a safe value to swap into solver +// params when a nil Manifest is provided. +type simpleRootManifest struct { + c, ovr ProjectConstraints + ig *pkgtree.IgnoredRuleset + req map[string]bool +} + +func (m simpleRootManifest) DependencyConstraints() ProjectConstraints { + return m.c +} +func (m simpleRootManifest) Overrides() ProjectConstraints { + return m.ovr +} +func (m simpleRootManifest) IgnoredPackages() *pkgtree.IgnoredRuleset { + return m.ig +} +func (m simpleRootManifest) RequiredPackages() map[string]bool { + return m.req +} +func (m simpleRootManifest) dup() simpleRootManifest { + m2 := simpleRootManifest{ + c: make(ProjectConstraints, len(m.c)), + ovr: make(ProjectConstraints, len(m.ovr)), + req: make(map[string]bool, len(m.req)), + } + + for k, v := range m.c { + m2.c[k] = v + } + for k, v := range m.ovr { + m2.ovr[k] = v + } + for k, v := range m.req { + m2.req[k] = v + } + + // IgnoredRulesets are immutable, and safe to reuse. + m2.ig = m.ig + + return m2 +} + +// prepManifest ensures a manifest is prepared and safe for use by the solver. +// This is mostly about ensuring that no outside routine can modify the manifest +// while the solver is in-flight, but it also filters out any empty +// ProjectProperties. +// +// This is achieved by copying the manifest's data into a new SimpleManifest. +func prepManifest(m Manifest) SimpleManifest { + if m == nil { + return SimpleManifest{} + } + + deps := m.DependencyConstraints() + + rm := SimpleManifest{ + Deps: make(ProjectConstraints, len(deps)), + } + + for k, d := range deps { + // A zero-value ProjectProperties is equivalent to one with an + // anyConstraint{} in terms of how the solver will treat it. However, we + // normalize between these two by omitting such instances entirely, as + // it negates some possibility for false mismatches in input hashing. + if d.Constraint == nil { + if d.Source == "" { + continue + } + d.Constraint = anyConstraint{} + } + + rm.Deps[k] = d + } + + return rm +} diff --git a/vendor/github.com/golang/dep/gps/manifest_test.go b/vendor/github.com/golang/dep/gps/manifest_test.go new file mode 100644 index 00000000..a6ce9871 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/manifest_test.go @@ -0,0 +1,29 @@ +// Copyright 2017 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 gps + +import "testing" + +// Test that prep manifest sanitizes manifests appropriately +func TestPrepManifest(t *testing.T) { + m := SimpleManifest{ + Deps: ProjectConstraints{ + ProjectRoot("foo"): ProjectProperties{}, + ProjectRoot("bar"): ProjectProperties{ + Source: "whatever", + }, + }, + } + + prepped := prepManifest(m) + d := prepped.DependencyConstraints() + if len(d) != 1 { + t.Error("prepManifest did not eliminate empty ProjectProperties from deps map") + } + + if d[ProjectRoot("bar")].Constraint != any { + t.Error("prepManifest did not normalize nil constraint to anyConstraint in deps map") + } +} diff --git a/vendor/github.com/golang/dep/gps/maybe_source.go b/vendor/github.com/golang/dep/gps/maybe_source.go new file mode 100644 index 00000000..3128181d --- /dev/null +++ b/vendor/github.com/golang/dep/gps/maybe_source.go @@ -0,0 +1,262 @@ +// Copyright 2017 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 gps + +import ( + "bytes" + "context" + "fmt" + "net/url" + "path/filepath" + + "github.com/Masterminds/vcs" + "github.com/pkg/errors" +) + +// A maybeSource represents a set of information that, given some +// typically-expensive network effort, could be transformed into a proper source. +// +// Wrapping these up as their own type achieves two goals: +// +// * Allows control over when deduction logic triggers network activity +// * Makes it easy to attempt multiple URLs for a given import path +type maybeSource interface { + try(ctx context.Context, cachedir string, c singleSourceCache, superv *supervisor) (source, sourceState, error) + possibleURLs() []*url.URL +} + +type errorSlice []error + +func (errs *errorSlice) Error() string { + var buf bytes.Buffer + for _, err := range *errs { + fmt.Fprintf(&buf, "\n\t%s", err) + } + return buf.String() +} + +type maybeSources []maybeSource + +func (mbs maybeSources) try(ctx context.Context, cachedir string, c singleSourceCache, superv *supervisor) (source, sourceState, error) { + var errs errorSlice + for _, mb := range mbs { + src, state, err := mb.try(ctx, cachedir, c, superv) + if err == nil { + return src, state, nil + } + urls := "" + for _, url := range mb.possibleURLs() { + urls += url.String() + "\n" + } + errs = append(errs, errors.Wrapf(err, "failed to set up sources from the following URLs:\n%s", urls)) + } + + return nil, 0, errors.Wrap(&errs, "no valid source could be created") +} + +// This really isn't generally intended to be used - the interface is for +// maybeSources to be able to interrogate its members, not other things to +// interrogate a maybeSources. +func (mbs maybeSources) possibleURLs() []*url.URL { + urlslice := make([]*url.URL, 0, len(mbs)) + for _, mb := range mbs { + urlslice = append(urlslice, mb.possibleURLs()...) + } + return urlslice +} + +// sourceCachePath returns a url-sanitized source cache dir path. +func sourceCachePath(cacheDir, sourceURL string) string { + return filepath.Join(cacheDir, "sources", sanitizer.Replace(sourceURL)) +} + +type maybeGitSource struct { + url *url.URL +} + +func (m maybeGitSource) try(ctx context.Context, cachedir string, c singleSourceCache, superv *supervisor) (source, sourceState, error) { + ustr := m.url.String() + + r, err := newCtxRepo(vcs.Git, ustr, sourceCachePath(cachedir, ustr)) + if err != nil { + return nil, 0, unwrapVcsErr(err) + } + + src := &gitSource{ + baseVCSSource: baseVCSSource{ + repo: r, + }, + } + + // Pinging invokes the same action as calling listVersions, so just do that. + var vl []PairedVersion + if err := superv.do(ctx, "git:lv:maybe", ctListVersions, func(ctx context.Context) error { + var err error + vl, err = src.listVersions(ctx) + return errors.Wrapf(err, "remote repository at %s does not exist, or is inaccessible", ustr) + }); err != nil { + return nil, 0, err + } + + state := sourceIsSetUp | sourceExistsUpstream | sourceHasLatestVersionList + + if r.CheckLocal() { + state |= sourceExistsLocally + + if err := superv.do(ctx, "git", ctValidateLocal, func(ctx context.Context) error { + // If repository already exists on disk, make a pass to be sure + // everything's clean. + return src.ensureClean(ctx) + }); err != nil { + return nil, 0, err + } + } + + c.setVersionMap(vl) + return src, state, nil +} + +func (m maybeGitSource) possibleURLs() []*url.URL { + return []*url.URL{m.url} +} + +type maybeGopkginSource struct { + // the original gopkg.in import path. this is used to create the on-disk + // location to avoid duplicate resource management - e.g., if instances of + // a gopkg.in project are accessed via different schemes, or if the + // underlying github repository is accessed directly. + opath string + // the actual upstream URL - always github + url *url.URL + // the major version to apply for filtering + major uint64 + // whether or not the source package is "unstable" + unstable bool +} + +func (m maybeGopkginSource) try(ctx context.Context, cachedir string, c singleSourceCache, superv *supervisor) (source, sourceState, error) { + // We don't actually need a fully consistent transform into the on-disk path + // - just something that's unique to the particular gopkg.in domain context. + // So, it's OK to just dumb-join the scheme with the path. + aliasURL := m.url.Scheme + "://" + m.opath + path := sourceCachePath(cachedir, aliasURL) + ustr := m.url.String() + + r, err := newCtxRepo(vcs.Git, ustr, path) + if err != nil { + return nil, 0, unwrapVcsErr(err) + } + + src := &gopkginSource{ + gitSource: gitSource{ + baseVCSSource: baseVCSSource{ + repo: r, + }, + }, + major: m.major, + unstable: m.unstable, + aliasURL: aliasURL, + } + + var vl []PairedVersion + if err := superv.do(ctx, "git:lv:maybe", ctListVersions, func(ctx context.Context) error { + var err error + vl, err = src.listVersions(ctx) + return errors.Wrapf(err, "remote repository at %s does not exist, or is inaccessible", ustr) + }); err != nil { + return nil, 0, err + } + + c.setVersionMap(vl) + state := sourceIsSetUp | sourceExistsUpstream | sourceHasLatestVersionList + + if r.CheckLocal() { + state |= sourceExistsLocally + } + + return src, state, nil +} + +func (m maybeGopkginSource) possibleURLs() []*url.URL { + return []*url.URL{m.url} +} + +type maybeBzrSource struct { + url *url.URL +} + +func (m maybeBzrSource) try(ctx context.Context, cachedir string, c singleSourceCache, superv *supervisor) (source, sourceState, error) { + ustr := m.url.String() + + r, err := newCtxRepo(vcs.Bzr, ustr, sourceCachePath(cachedir, ustr)) + if err != nil { + return nil, 0, unwrapVcsErr(err) + } + + if err := superv.do(ctx, "bzr:ping", ctSourcePing, func(ctx context.Context) error { + if !r.Ping() { + return fmt.Errorf("remote repository at %s does not exist, or is inaccessible", ustr) + } + return nil + }); err != nil { + return nil, 0, err + } + + state := sourceIsSetUp | sourceExistsUpstream + if r.CheckLocal() { + state |= sourceExistsLocally + } + + src := &bzrSource{ + baseVCSSource: baseVCSSource{ + repo: r, + }, + } + + return src, state, nil +} + +func (m maybeBzrSource) possibleURLs() []*url.URL { + return []*url.URL{m.url} +} + +type maybeHgSource struct { + url *url.URL +} + +func (m maybeHgSource) try(ctx context.Context, cachedir string, c singleSourceCache, superv *supervisor) (source, sourceState, error) { + ustr := m.url.String() + + r, err := newCtxRepo(vcs.Hg, ustr, sourceCachePath(cachedir, ustr)) + if err != nil { + return nil, 0, unwrapVcsErr(err) + } + + if err := superv.do(ctx, "hg:ping", ctSourcePing, func(ctx context.Context) error { + if !r.Ping() { + return fmt.Errorf("remote repository at %s does not exist, or is inaccessible", ustr) + } + return nil + }); err != nil { + return nil, 0, err + } + + state := sourceIsSetUp | sourceExistsUpstream + if r.CheckLocal() { + state |= sourceExistsLocally + } + + src := &hgSource{ + baseVCSSource: baseVCSSource{ + repo: r, + }, + } + + return src, state, nil +} + +func (m maybeHgSource) possibleURLs() []*url.URL { + return []*url.URL{m.url} +} diff --git a/vendor/github.com/golang/dep/gps/metrics.go b/vendor/github.com/golang/dep/gps/metrics.go new file mode 100644 index 00000000..5462f4bf --- /dev/null +++ b/vendor/github.com/golang/dep/gps/metrics.go @@ -0,0 +1,84 @@ +// Copyright 2017 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 gps + +import ( + "bytes" + "fmt" + "log" + "sort" + "text/tabwriter" + "time" +) + +type metrics struct { + stack []string + times map[string]time.Duration + last time.Time +} + +func newMetrics() *metrics { + return &metrics{ + stack: []string{"other"}, + times: map[string]time.Duration{ + "other": 0, + }, + last: time.Now(), + } +} + +func (m *metrics) push(name string) { + cn := m.stack[len(m.stack)-1] + m.times[cn] = m.times[cn] + time.Since(m.last) + + m.stack = append(m.stack, name) + m.last = time.Now() +} + +func (m *metrics) pop() { + on := m.stack[len(m.stack)-1] + m.times[on] = m.times[on] + time.Since(m.last) + + m.stack = m.stack[:len(m.stack)-1] + m.last = time.Now() +} + +func (m *metrics) dump(l *log.Logger) { + s := make(ndpairs, len(m.times)) + k := 0 + for n, d := range m.times { + s[k] = ndpair{ + n: n, + d: d, + } + k++ + } + + sort.Sort(sort.Reverse(s)) + + var tot time.Duration + var buf bytes.Buffer + w := tabwriter.NewWriter(&buf, 0, 0, 1, ' ', tabwriter.AlignRight) + for _, nd := range s { + tot += nd.d + fmt.Fprintf(w, "\t%s:\t%v\t\n", nd.n, nd.d) + } + fmt.Fprintf(w, "\n\tTOTAL:\t%v\t\n", tot) + w.Flush() + + l.Println("\nSolver wall times by segment:") + l.Println((&buf).String()) +} + +type ndpair struct { + n string + d time.Duration +} + +type ndpairs []ndpair + +func (s ndpairs) Less(i, j int) bool { return s[i].d < s[j].d } +func (s ndpairs) Swap(i, j int) { s[i], s[j] = s[j], s[i] } +func (s ndpairs) Len() int { return len(s) } diff --git a/vendor/github.com/golang/dep/gps/paths/paths.go b/vendor/github.com/golang/dep/gps/paths/paths.go new file mode 100644 index 00000000..af930494 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/paths/paths.go @@ -0,0 +1,21 @@ +// Copyright 2017 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 paths + +import "strings" + +// IsStandardImportPath reports whether $GOROOT/src/path should be considered +// part of the standard distribution. For historical reasons we allow people to add +// their own code to $GOROOT instead of using $GOPATH, but we assume that +// code will start with a domain name (dot in the first element). +// This was lovingly taken from src/cmd/go/pkg.go in Go's code (isStandardImportPath). +func IsStandardImportPath(path string) bool { + i := strings.Index(path, "/") + if i < 0 { + i = len(path) + } + + return !strings.Contains(path[:i], ".") +} diff --git a/vendor/github.com/golang/dep/gps/paths/paths_test.go b/vendor/github.com/golang/dep/gps/paths/paths_test.go new file mode 100644 index 00000000..2e0fc8b0 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/paths/paths_test.go @@ -0,0 +1,37 @@ +// Copyright 2017 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 paths + +import ( + "testing" + + _ "github.com/golang/dep/internal/test" // DO NOT REMOVE, allows go test ./... -update to work +) + +func TestIsStandardImportPath(t *testing.T) { + fix := []struct { + ip string + is bool + }{ + {"appengine", true}, + {"net/http", true}, + {"github.com/anything", false}, + {"github.com", false}, + {"foo", true}, + {".", false}, + } + + for _, f := range fix { + r := IsStandardImportPath(f.ip) + if r != f.is { + if r { + t.Errorf("%s was marked stdlib but should not have been", f.ip) + } else { + t.Errorf("%s was not marked stdlib but should have been", f.ip) + + } + } + } +} diff --git a/vendor/github.com/golang/dep/gps/pkgtree/digest.go b/vendor/github.com/golang/dep/gps/pkgtree/digest.go new file mode 100644 index 00000000..31ed243a --- /dev/null +++ b/vendor/github.com/golang/dep/gps/pkgtree/digest.go @@ -0,0 +1,472 @@ +// Copyright 2017 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 pkgtree + +import ( + "bytes" + "crypto/sha256" + "encoding/binary" + "hash" + "io" + "os" + "path/filepath" + "strconv" + + "github.com/pkg/errors" +) + +const osPathSeparator = string(filepath.Separator) + +// lineEndingReader is a `io.Reader` that converts CRLF sequences to LF. +// +// When cloning or checking out repositories, some Version Control Systems, +// VCSs, on some supported Go Operating System architectures, GOOS, will +// automatically convert line endings that end in a single line feed byte, LF, +// to line endings that end in a two byte sequence of carriage return, CR, +// followed by LF. This LF to CRLF conversion would cause otherwise identical +// versioned files to have different on disk contents simply based on which VCS +// and GOOS are involved. Different file contents for the same file would cause +// the resultant hashes to differ. In order to ensure file contents normalize +// and produce the same hash, this structure wraps an io.Reader that modifies +// the file's contents when it is read, translating all CRLF sequences to LF. +type lineEndingReader struct { + src io.Reader // source io.Reader from which this reads + prevReadEndedCR bool // used to track whether final byte of previous Read was CR +} + +// newLineEndingReader returns a new lineEndingReader that reads from the +// specified source io.Reader. +func newLineEndingReader(src io.Reader) *lineEndingReader { + return &lineEndingReader{src: src} +} + +var crlf = []byte("\r\n") + +// Read consumes bytes from the structure's source io.Reader to fill the +// specified slice of bytes. It converts all CRLF byte sequences to LF, and +// handles cases where CR and LF straddle across two Read operations. +func (f *lineEndingReader) Read(buf []byte) (int, error) { + buflen := len(buf) + if f.prevReadEndedCR { + // Read one fewer bytes so we have room if the first byte of the + // upcoming Read is not a LF, in which case we will need to insert + // trailing CR from previous read. + buflen-- + } + nr, er := f.src.Read(buf[:buflen]) + if nr > 0 { + if f.prevReadEndedCR && buf[0] != '\n' { + // Having a CRLF split across two Read operations is rare, so the + // performance impact of copying entire buffer to the right by one + // byte, while suboptimal, will at least will not happen very + // often. This negative performance impact is mitigated somewhat on + // many Go compilation architectures, GOARCH, because the `copy` + // builtin uses a machine opcode for performing the memory copy on + // possibly overlapping regions of memory. This machine opcodes is + // not instantaneous and does require multiple CPU cycles to + // complete, but is significantly faster than the application + // looping through bytes. + copy(buf[1:nr+1], buf[:nr]) // shift data to right one byte + buf[0] = '\r' // insert the previous skipped CR byte at start of buf + nr++ // pretend we read one more byte + } + + // Remove any CRLF sequences in the buffer using `bytes.Index` because, + // like the `copy` builtin on many GOARCHs, it also takes advantage of a + // machine opcode to search for byte patterns. + var searchOffset int // index within buffer from whence the search will commence for each loop; set to the index of the end of the previous loop. + var shiftCount int // each subsequenct shift operation needs to shift bytes to the left by one more position than the shift that preceded it. + previousIndex := -1 // index of previously found CRLF; -1 means no previous index + for { + index := bytes.Index(buf[searchOffset:nr], crlf) + if index == -1 { + break + } + index += searchOffset // convert relative index to absolute + if previousIndex != -1 { + // shift substring between previous index and this index + copy(buf[previousIndex-shiftCount:], buf[previousIndex+1:index]) + shiftCount++ // next shift needs to be 1 byte to the left + } + previousIndex = index + searchOffset = index + 2 // start next search after len(crlf) + } + if previousIndex != -1 { + // handle final shift + copy(buf[previousIndex-shiftCount:], buf[previousIndex+1:nr]) + shiftCount++ + } + nr -= shiftCount // shorten byte read count by number of shifts executed + + // When final byte from a read operation is CR, do not emit it until + // ensure first byte on next read is not LF. + if f.prevReadEndedCR = buf[nr-1] == '\r'; f.prevReadEndedCR { + nr-- // pretend byte was never read from source + } + } else if f.prevReadEndedCR { + // Reading from source returned nothing, but this struct is sitting on a + // trailing CR from previous Read, so let's give it to client now. + buf[0] = '\r' + nr = 1 + er = nil + f.prevReadEndedCR = false // prevent infinite loop + } + return nr, er +} + +// writeBytesWithNull appends the specified data to the specified hash, followed by +// the NULL byte, in order to make accidental hash collisions less likely. +func writeBytesWithNull(h hash.Hash, data []byte) { + // Ignore return values from writing to the hash, because hash write always + // returns nil error. + _, _ = h.Write(append(data, 0)) +} + +// dirWalkClosure is used to reduce number of allocation involved in closing +// over these variables. +type dirWalkClosure struct { + someCopyBufer []byte // allocate once and reuse for each file copy + someModeBytes []byte // allocate once and reuse for each node + someDirLen int + someHash hash.Hash +} + +// DigestFromDirectory returns a hash of the specified directory contents, which +// will match the hash computed for any directory on any supported Go platform +// whose contents exactly match the specified directory. +// +// This function ignores any file system node named `vendor`, `.bzr`, `.git`, +// `.hg`, and `.svn`, as these are typically used as Version Control System +// (VCS) directories. +// +// Other than the `vendor` and VCS directories mentioned above, the calculated +// hash includes the pathname to every discovered file system node, whether it +// is an empty directory, a non-empty directory, empty file, non-empty file, or +// symbolic link. If a symbolic link, the referent name is included. If a +// non-empty file, the file's contents are included. If a non-empty directory, +// the contents of the directory are included. +// +// While filepath.Walk could have been used, that standard library function +// skips symbolic links, and for now, we want the hash to include the symbolic +// link referents. +func DigestFromDirectory(osDirname string) ([]byte, error) { + osDirname = filepath.Clean(osDirname) + + // Create a single hash instance for the entire operation, rather than a new + // hash for each node we encounter. + + closure := dirWalkClosure{ + someCopyBufer: make([]byte, 4*1024), // only allocate a single page + someModeBytes: make([]byte, 4), // scratch place to store encoded os.FileMode (uint32) + someDirLen: len(osDirname) + len(osPathSeparator), + someHash: sha256.New(), + } + + err := DirWalk(osDirname, func(osPathname string, info os.FileInfo, err error) error { + if err != nil { + return err // DirWalk received an error during initial Lstat + } + + var osRelative string + if len(osPathname) > closure.someDirLen { + osRelative = osPathname[closure.someDirLen:] + } + + switch filepath.Base(osRelative) { + case "vendor", ".bzr", ".git", ".hg", ".svn": + return filepath.SkipDir + } + + // We could make our own enum-like data type for encoding the file type, + // but Go's runtime already gives us architecture independent file + // modes, as discussed in `os/types.go`: + // + // Go's runtime FileMode type has same definition on all systems, so + // that information about files can be moved from one system to + // another portably. + var mt os.FileMode + + // We only care about the bits that identify the type of a file system + // node, and can ignore append, exclusive, temporary, setuid, setgid, + // permission bits, and sticky bits, which are coincident to bits which + // declare type of the file system node. + modeType := info.Mode() & os.ModeType + var shouldSkip bool // skip some types of file system nodes + + switch { + case modeType&os.ModeDir > 0: + mt = os.ModeDir + // DirWalkFunc itself does not need to enumerate children, because + // DirWalk will do that for us. + shouldSkip = true + case modeType&os.ModeSymlink > 0: + mt = os.ModeSymlink + case modeType&os.ModeNamedPipe > 0: + mt = os.ModeNamedPipe + shouldSkip = true + case modeType&os.ModeSocket > 0: + mt = os.ModeSocket + shouldSkip = true + case modeType&os.ModeDevice > 0: + mt = os.ModeDevice + shouldSkip = true + } + + // Write the relative pathname to hash because the hash is a function of + // the node names, node types, and node contents. Added benefit is that + // empty directories, named pipes, sockets, devices, and symbolic links + // will also affect final hash value. Use `filepath.ToSlash` to ensure + // relative pathname is os-agnostic. + writeBytesWithNull(closure.someHash, []byte(filepath.ToSlash(osRelative))) + + binary.LittleEndian.PutUint32(closure.someModeBytes, uint32(mt)) // encode the type of mode + writeBytesWithNull(closure.someHash, closure.someModeBytes) // and write to hash + + if shouldSkip { + return nil // nothing more to do for some of the node types + } + + if mt == os.ModeSymlink { // okay to check for equivalence because we set to this value + osRelative, err = os.Readlink(osPathname) // read the symlink referent + if err != nil { + return errors.Wrap(err, "cannot Readlink") + } + writeBytesWithNull(closure.someHash, []byte(filepath.ToSlash(osRelative))) // write referent to hash + return nil // proceed to next node in queue + } + + // If we get here, node is a regular file. + fh, err := os.Open(osPathname) + if err != nil { + return errors.Wrap(err, "cannot Open") + } + + var bytesWritten int64 + bytesWritten, err = io.CopyBuffer(closure.someHash, newLineEndingReader(fh), closure.someCopyBufer) // fast copy of file contents to hash + err = errors.Wrap(err, "cannot Copy") // errors.Wrap only wraps non-nil, so skip extra check + writeBytesWithNull(closure.someHash, []byte(strconv.FormatInt(bytesWritten, 10))) // 10: format file size as base 10 integer + + // Close the file handle to the open file without masking + // possible previous error value. + if er := fh.Close(); err == nil { + err = errors.Wrap(er, "cannot Close") + } + return err + }) + if err != nil { + return nil, err + } + return closure.someHash.Sum(nil), nil +} + +// VendorStatus represents one of a handful of possible status conditions for a +// particular file system node in the vendor directory tree. +type VendorStatus uint8 + +const ( + // NotInLock is used when a file system node exists for which there is no + // corresponding dependency in the lock file. + NotInLock VendorStatus = iota + + // NotInTree is used when a lock file dependency exists for which there is + // no corresponding file system node. + NotInTree + + // NoMismatch is used when the digest for a dependency listed in the + // lockfile matches what is calculated from the file system. + NoMismatch + + // EmptyDigestInLock is used when the digest for a dependency listed in the + // lock file is the empty string. While this is a special case of + // DigestMismatchInLock, keeping both cases discrete is a desired feature. + EmptyDigestInLock + + // DigestMismatchInLock is used when the digest for a dependency listed in + // the lock file does not match what is calculated from the file system. + DigestMismatchInLock +) + +func (ls VendorStatus) String() string { + switch ls { + case NotInTree: + return "not in tree" + case NotInLock: + return "not in lock" + case NoMismatch: + return "match" + case EmptyDigestInLock: + return "empty digest in lock" + case DigestMismatchInLock: + return "mismatch" + } + return "unknown" +} + +// fsnode is used to track which file system nodes are required by the lock +// file. When a directory is found whose name matches one of the declared +// projects in the lock file, e.g., "github.com/alice/alice1", an fsnode is +// created for that directory, but not for any of its children. All other file +// system nodes encountered will result in a fsnode created to represent it. +type fsnode struct { + osRelative string // os-specific relative path of a resource under vendor root + isRequiredAncestor bool // true iff this node or one of its descendants is in the lock file + myIndex, parentIndex int // index of this node and its parent in the tree's slice +} + +// VerifyDepTree verifies a dependency tree according to expected digest sums, +// and returns an associative array of file system nodes and their respective +// vendor status conditions. +// +// The keys to the expected digest sums associative array represent the +// project's dependencies, and each is required to be expressed using the +// solidus character, `/`, as its path separator. For example, even on a GOOS +// platform where the file system path separator is a character other than +// solidus, one particular dependency would be represented as +// "github.com/alice/alice1". +func VerifyDepTree(osDirname string, wantSums map[string][]byte) (map[string]VendorStatus, error) { + osDirname = filepath.Clean(osDirname) + + // Ensure top level pathname is a directory + fi, err := os.Stat(osDirname) + if err != nil { + return nil, errors.Wrap(err, "cannot Stat") + } + if !fi.IsDir() { + return nil, errors.Errorf("cannot verify non directory: %q", osDirname) + } + + // Initialize work queue with a node representing the specified directory + // name by declaring its relative pathname under the directory name as the + // empty string. + currentNode := &fsnode{osRelative: "", parentIndex: -1, isRequiredAncestor: true} + queue := []*fsnode{currentNode} // queue of directories that must be inspected + + // In order to identify all file system nodes that are not in the lock file, + // represented by the specified expected sums parameter, and in order to + // only report the top level of a subdirectory of file system nodes, rather + // than every node internal to them, we will create a tree of nodes stored + // in a slice. We do this because we cannot predict the depth at which + // project roots occur. Some projects are fewer than and some projects more + // than the typical three layer subdirectory under the vendor root + // directory. + // + // For a following few examples, assume the below vendor root directory: + // + // github.com/alice/alice1/a1.go + // github.com/alice/alice2/a2.go + // github.com/bob/bob1/b1.go + // github.com/bob/bob2/b2.go + // launchpad.net/nifty/n1.go + // + // 1) If only the `alice1` and `alice2` projects were in the lock file, we'd + // prefer the output to state that `github.com/bob` is `NotInLock`, and + // `launchpad.net/nifty` is `NotInLock`. + // + // 2) If `alice1`, `alice2`, and `bob1` were in the lock file, we'd want to + // report `github.com/bob/bob2` as `NotInLock`, and `launchpad.net/nifty` is + // `NotInLock`. + // + // 3) If none of `alice1`, `alice2`, `bob1`, or `bob2` were in the lock + // file, the entire `github.com` directory would be reported as `NotInLock`, + // along with `launchpad.net/nifty` is `NotInLock`. + // + // Each node in our tree has the slice index of its parent node, so once we + // can categorically state a particular directory is required because it is + // in the lock file, we can mark all of its ancestors as also being + // required. Then, when we finish walking the directory hierarchy, any nodes + // which are not required but have a required parent will be marked as + // `NotInLock`. + nodes := []*fsnode{currentNode} + + // Create associative array to store the results of calling this function. + slashStatus := make(map[string]VendorStatus) + + // Mark directories of expected projects as required. When each respective + // project is later found while traversing the vendor root hierarchy, its + // status will be updated to reflect whether its digest is empty, or, + // whether or not it matches the expected digest. + for slashPathname := range wantSums { + slashStatus[slashPathname] = NotInTree + } + + for len(queue) > 0 { + // Pop node from the top of queue (depth first traversal, reverse + // lexicographical order inside a directory), clearing the value stored + // in the slice's backing array as we proceed. + lq1 := len(queue) - 1 + currentNode, queue[lq1], queue = queue[lq1], nil, queue[:lq1] + slashPathname := filepath.ToSlash(currentNode.osRelative) + osPathname := filepath.Join(osDirname, currentNode.osRelative) + + if expectedSum, ok := wantSums[slashPathname]; ok { + ls := EmptyDigestInLock + if len(expectedSum) > 0 { + projectSum, err := DigestFromDirectory(osPathname) + if err != nil { + return nil, errors.Wrap(err, "cannot compute dependency hash") + } + if bytes.Equal(projectSum, expectedSum) { + ls = NoMismatch + } else { + ls = DigestMismatchInLock + } + } + slashStatus[slashPathname] = ls + + // Mark current nodes and all its parents as required. + for i := currentNode.myIndex; i != -1; i = nodes[i].parentIndex { + nodes[i].isRequiredAncestor = true + } + + // Do not need to process this directory's contents because we + // already accounted for its contents while calculating its digest. + continue + } + + osChildrenNames, err := sortedChildrenFromDirname(osPathname) + if err != nil { + return nil, errors.Wrap(err, "cannot get sorted list of directory children") + } + for _, osChildName := range osChildrenNames { + switch osChildName { + case ".", "..", "vendor", ".bzr", ".git", ".hg", ".svn": + // skip + default: + osChildRelative := filepath.Join(currentNode.osRelative, osChildName) + osChildPathname := filepath.Join(osDirname, osChildRelative) + + // Create a new fsnode for this file system node, with a parent + // index set to the index of the current node. + otherNode := &fsnode{osRelative: osChildRelative, myIndex: len(nodes), parentIndex: currentNode.myIndex} + + fi, err := os.Stat(osChildPathname) + if err != nil { + return nil, errors.Wrap(err, "cannot Stat") + } + nodes = append(nodes, otherNode) // Track all file system nodes... + if fi.IsDir() { + queue = append(queue, otherNode) // but only need to add directories to the work queue. + } + } + } + } + + // Ignoring first node in the list, walk nodes from last to first. Whenever + // the current node is not required, but its parent is required, then the + // current node ought to be marked as `NotInLock`. + for len(nodes) > 1 { + // Pop node from top of queue, clearing the value stored in the slice's + // backing array as we proceed. + ln1 := len(nodes) - 1 + currentNode, nodes[ln1], nodes = nodes[ln1], nil, nodes[:ln1] + + if !currentNode.isRequiredAncestor && nodes[currentNode.parentIndex].isRequiredAncestor { + slashStatus[filepath.ToSlash(currentNode.osRelative)] = NotInLock + } + } + currentNode, nodes = nil, nil + + return slashStatus, nil +} diff --git a/vendor/github.com/golang/dep/gps/pkgtree/digest_test.go b/vendor/github.com/golang/dep/gps/pkgtree/digest_test.go new file mode 100644 index 00000000..574b3842 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/pkgtree/digest_test.go @@ -0,0 +1,220 @@ +// Copyright 2017 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 pkgtree + +import ( + "bytes" + "io" + "os" + "path/filepath" + "testing" +) + +// crossBuffer is a test io.Reader that emits a few canned responses. +type crossBuffer struct { + readCount int + iterations []string +} + +func (cb *crossBuffer) Read(buf []byte) (int, error) { + if cb.readCount == len(cb.iterations) { + return 0, io.EOF + } + cb.readCount++ + return copy(buf, cb.iterations[cb.readCount-1]), nil +} + +func streamThruLineEndingReader(t *testing.T, iterations []string) []byte { + dst := new(bytes.Buffer) + n, err := io.Copy(dst, newLineEndingReader(&crossBuffer{iterations: iterations})) + if got, want := err, error(nil); got != want { + t.Errorf("(GOT): %v; (WNT): %v", got, want) + } + if got, want := n, int64(dst.Len()); got != want { + t.Errorf("(GOT): %v; (WNT): %v", got, want) + } + return dst.Bytes() +} + +func TestLineEndingReader(t *testing.T) { + testCases := []struct { + input []string + output string + }{ + {[]string{"\r"}, "\r"}, + {[]string{"\r\n"}, "\n"}, + {[]string{"now is the time\r\n"}, "now is the time\n"}, + {[]string{"now is the time\r\n(trailing data)"}, "now is the time\n(trailing data)"}, + {[]string{"now is the time\n"}, "now is the time\n"}, + {[]string{"now is the time\r"}, "now is the time\r"}, // trailing CR ought to convey + {[]string{"\rnow is the time"}, "\rnow is the time"}, // CR not followed by LF ought to convey + {[]string{"\rnow is the time\r"}, "\rnow is the time\r"}, // CR not followed by LF ought to convey + + // no line splits + {[]string{"first", "second", "third"}, "firstsecondthird"}, + + // 1->2 and 2->3 both break across a CRLF + {[]string{"first\r", "\nsecond\r", "\nthird"}, "first\nsecond\nthird"}, + + // 1->2 breaks across CRLF and 2->3 does not + {[]string{"first\r", "\nsecond", "third"}, "first\nsecondthird"}, + + // 1->2 breaks across CRLF and 2 ends in CR but 3 does not begin LF + {[]string{"first\r", "\nsecond\r", "third"}, "first\nsecond\rthird"}, + + // 1 ends in CR but 2 does not begin LF, and 2->3 breaks across CRLF + {[]string{"first\r", "second\r", "\nthird"}, "first\rsecond\nthird"}, + + // 1 ends in CR but 2 does not begin LF, and 2->3 does not break across CRLF + {[]string{"first\r", "second\r", "\nthird"}, "first\rsecond\nthird"}, + + // 1->2 and 2->3 both break across a CRLF, but 3->4 does not + {[]string{"first\r", "\nsecond\r", "\nthird\r", "fourth"}, "first\nsecond\nthird\rfourth"}, + {[]string{"first\r", "\nsecond\r", "\nthird\n", "fourth"}, "first\nsecond\nthird\nfourth"}, + + {[]string{"this is the result\r\nfrom the first read\r", "\nthis is the result\r\nfrom the second read\r"}, + "this is the result\nfrom the first read\nthis is the result\nfrom the second read\r"}, + {[]string{"now is the time\r\nfor all good engineers\r\nto improve their test coverage!\r\n"}, + "now is the time\nfor all good engineers\nto improve their test coverage!\n"}, + {[]string{"now is the time\r\nfor all good engineers\r", "\nto improve their test coverage!\r\n"}, + "now is the time\nfor all good engineers\nto improve their test coverage!\n"}, + } + + for _, testCase := range testCases { + got := streamThruLineEndingReader(t, testCase.input) + if want := []byte(testCase.output); !bytes.Equal(got, want) { + t.Errorf("Input: %#v; (GOT): %#q; (WNT): %#q", testCase.input, got, want) + } + } +} + +//////////////////////////////////////// + +func getTestdataVerifyRoot(t *testing.T) string { + cwd, err := os.Getwd() + if err != nil { + t.Fatal(err) + } + return filepath.Join(filepath.Dir(cwd), "_testdata/digest") +} + +func TestDigestFromDirectoryBailsUnlessDirectory(t *testing.T) { + prefix := getTestdataVerifyRoot(t) + relativePathname := "launchpad.net/match" + _, err := DigestFromDirectory(filepath.Join(prefix, relativePathname)) + if got, want := err, error(nil); got != want { + t.Errorf("\n(GOT): %v; (WNT): %v", got, want) + } +} + +func TestDigestFromDirectory(t *testing.T) { + relativePathname := "launchpad.net/match" + want := []byte{0x7e, 0x10, 0x6, 0x2f, 0x8, 0x3, 0x3c, 0x76, 0xae, 0xbc, 0xa4, 0xc9, 0xec, 0x73, 0x67, 0x15, 0x70, 0x2b, 0x0, 0x89, 0x27, 0xbb, 0x61, 0x9d, 0xc7, 0xc3, 0x39, 0x46, 0x3, 0x91, 0xb7, 0x3b} + + // NOTE: Create the hash using both an absolute and a relative pathname to + // ensure hash ignores prefix. + + t.Run("AbsolutePrefix", func(t *testing.T) { + prefix := getTestdataVerifyRoot(t) + got, err := DigestFromDirectory(filepath.Join(prefix, relativePathname)) + if err != nil { + t.Fatal(err) + } + if !bytes.Equal(got, want) { + t.Errorf("\n(GOT):\n\t%#v\n(WNT):\n\t%#v", got, want) + } + }) + + t.Run("RelativePrefix", func(t *testing.T) { + prefix := "../_testdata/digest" + got, err := DigestFromDirectory(filepath.Join(prefix, relativePathname)) + if err != nil { + t.Fatal(err) + } + if !bytes.Equal(got, want) { + t.Errorf("\n(GOT):\n\t%#v\n(WNT):\n\t%#v", got, want) + } + }) +} + +func TestVerifyDepTree(t *testing.T) { + vendorRoot := getTestdataVerifyRoot(t) + + wantSums := map[string][]byte{ + "github.com/alice/match": {0x7e, 0x10, 0x6, 0x2f, 0x8, 0x3, 0x3c, 0x76, 0xae, 0xbc, 0xa4, 0xc9, 0xec, 0x73, 0x67, 0x15, 0x70, 0x2b, 0x0, 0x89, 0x27, 0xbb, 0x61, 0x9d, 0xc7, 0xc3, 0x39, 0x46, 0x3, 0x91, 0xb7, 0x3b}, + "github.com/alice/mismatch": []byte("some non-matching digest"), + "github.com/bob/emptyDigest": nil, // empty hash result + "github.com/bob/match": {0x7e, 0x10, 0x6, 0x2f, 0x8, 0x3, 0x3c, 0x76, 0xae, 0xbc, 0xa4, 0xc9, 0xec, 0x73, 0x67, 0x15, 0x70, 0x2b, 0x0, 0x89, 0x27, 0xbb, 0x61, 0x9d, 0xc7, 0xc3, 0x39, 0x46, 0x3, 0x91, 0xb7, 0x3b}, + "github.com/charlie/notInTree": nil, // not in tree result ought to superseede empty digest result + // matching result at seldomly found directory level + "launchpad.net/match": {0x7e, 0x10, 0x6, 0x2f, 0x8, 0x3, 0x3c, 0x76, 0xae, 0xbc, 0xa4, 0xc9, 0xec, 0x73, 0x67, 0x15, 0x70, 0x2b, 0x0, 0x89, 0x27, 0xbb, 0x61, 0x9d, 0xc7, 0xc3, 0x39, 0x46, 0x3, 0x91, 0xb7, 0x3b}, + } + + status, err := VerifyDepTree(vendorRoot, wantSums) + if err != nil { + t.Fatal(err) + } + + if got, want := len(status), 7; got != want { + t.Errorf("\n(GOT): %v; (WNT): %v", got, want) + } + + checkStatus := func(t *testing.T, status map[string]VendorStatus, key string, want VendorStatus) { + got, ok := status[key] + if !ok { + t.Errorf("Want key: %q", key) + return + } + if got != want { + t.Errorf("Key: %q; (GOT): %v; (WNT): %v", key, got, want) + } + } + + checkStatus(t, status, "github.com/alice/match", NoMismatch) + checkStatus(t, status, "github.com/alice/mismatch", DigestMismatchInLock) + checkStatus(t, status, "github.com/alice/notInLock", NotInLock) + checkStatus(t, status, "github.com/bob/match", NoMismatch) + checkStatus(t, status, "github.com/bob/emptyDigest", EmptyDigestInLock) + checkStatus(t, status, "github.com/charlie/notInTree", NotInTree) + checkStatus(t, status, "launchpad.net/match", NoMismatch) + + if t.Failed() { + for k, want := range wantSums { + got, err := DigestFromDirectory(filepath.Join(vendorRoot, k)) + if err != nil { + t.Error(err) + } + if !bytes.Equal(got, want) { + t.Errorf("%q\n(GOT):\n\t%#v\n(WNT):\n\t%#v", k, got, want) + } + } + } +} + +func BenchmarkDigestFromDirectory(b *testing.B) { + b.Skip("Eliding benchmark of user's Go source directory") + + prefix := filepath.Join(os.Getenv("GOPATH"), "src") + + for i := 0; i < b.N; i++ { + _, err := DigestFromDirectory(prefix) + if err != nil { + b.Fatal(err) + } + } +} + +func BenchmarkVerifyDepTree(b *testing.B) { + b.Skip("Eliding benchmark of user's Go source directory") + + prefix := filepath.Join(os.Getenv("GOPATH"), "src") + + for i := 0; i < b.N; i++ { + _, err := VerifyDepTree(prefix, nil) + if err != nil { + b.Fatal(err) + } + } +} diff --git a/vendor/github.com/golang/dep/gps/pkgtree/dirwalk.go b/vendor/github.com/golang/dep/gps/pkgtree/dirwalk.go new file mode 100644 index 00000000..350c1606 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/pkgtree/dirwalk.go @@ -0,0 +1,139 @@ +// Copyright 2017 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 pkgtree + +import ( + "os" + "path/filepath" + "sort" + "strings" + + "github.com/pkg/errors" +) + +// DirWalkFunc is the type of the function called for each file system node +// visited by DirWalk. The path argument contains the argument to DirWalk as a +// prefix; that is, if DirWalk is called with "dir", which is a directory +// containing the file "a", the walk function will be called with the argument +// "dir/a", using the correct os.PathSeparator for the Go Operating System +// architecture, GOOS. The info argument is the os.FileInfo for the named path. +// +// If there was a problem walking to the file or directory named by path, the +// incoming error will describe the problem and the function can decide how to +// handle that error (and DirWalk will not descend into that directory). If an +// error is returned, processing stops. The sole exception is when the function +// returns the special value filepath.SkipDir. If the function returns +// filepath.SkipDir when invoked on a directory, DirWalk skips the directory's +// contents entirely. If the function returns filepath.SkipDir when invoked on a +// non-directory file system node, DirWalk skips the remaining files in the +// containing directory. +type DirWalkFunc func(osPathname string, info os.FileInfo, err error) error + +// DirWalk walks the file tree rooted at osDirname, calling for each file system +// node in the tree, including root. All errors that arise visiting nodes are +// filtered by walkFn. The nodes are walked in lexical order, which makes the +// output deterministic but means that for very large directories DirWalk can be +// inefficient. Unlike filepath.Walk, DirWalk does follow symbolic links. +func DirWalk(osDirname string, walkFn DirWalkFunc) error { + osDirname = filepath.Clean(osDirname) + + // Ensure parameter is a directory + fi, err := os.Stat(osDirname) + if err != nil { + return errors.Wrap(err, "cannot read node") + } + if !fi.IsDir() { + return errors.Errorf("cannot walk non directory: %q", osDirname) + } + + // Initialize a work queue with the empty string, which signifies the + // starting directory itself. + queue := []string{""} + + var osRelative string // os-specific relative pathname under directory name + + // As we enumerate over the queue and encounter a directory, its children + // will be added to the work queue. + for len(queue) > 0 { + // Unshift a pathname from the queue (breadth-first traversal of + // hierarchy) + osRelative, queue = queue[0], queue[1:] + osPathname := filepath.Join(osDirname, osRelative) + + // walkFn needs to choose how to handle symbolic links, therefore obtain + // lstat rather than stat. + fi, err = os.Lstat(osPathname) + if err == nil { + err = walkFn(osPathname, fi, nil) + } else { + err = walkFn(osPathname, nil, errors.Wrap(err, "cannot read node")) + } + + if err != nil { + if err == filepath.SkipDir { + if fi.Mode()&os.ModeSymlink > 0 { + // Resolve symbolic link referent to determine whether node + // is directory or not. + fi, err = os.Stat(osPathname) + if err != nil { + return errors.Wrap(err, "cannot visit node") + } + } + // If current node is directory, then skip this + // directory. Otherwise, skip all nodes in the same parent + // directory. + if !fi.IsDir() { + // Consume nodes from queue while they have the same parent + // as the current node. + osParent := filepath.Dir(osPathname) + osPathSeparator + for len(queue) > 0 && strings.HasPrefix(queue[0], osParent) { + queue = queue[1:] // drop sibling from queue + } + } + + continue + } + return errors.Wrap(err, "DirWalkFunction") // wrap error returned by walkFn + } + + if fi.IsDir() { + osChildrenNames, err := sortedChildrenFromDirname(osPathname) + if err != nil { + return errors.Wrap(err, "cannot get list of directory children") + } + for _, osChildName := range osChildrenNames { + switch osChildName { + case ".", "..": + // skip + default: + queue = append(queue, filepath.Join(osRelative, osChildName)) + } + } + } + } + return nil +} + +// sortedChildrenFromDirname returns a lexicographically sorted list of child +// nodes for the specified directory. +func sortedChildrenFromDirname(osDirname string) ([]string, error) { + fh, err := os.Open(osDirname) + if err != nil { + return nil, errors.Wrap(err, "cannot Open") + } + + osChildrenNames, err := fh.Readdirnames(0) // 0: read names of all children + if err != nil { + return nil, errors.Wrap(err, "cannot Readdirnames") + } + sort.Strings(osChildrenNames) + + // Close the file handle to the open directory without masking possible + // previous error value. + if er := fh.Close(); err == nil { + err = errors.Wrap(er, "cannot Close") + } + return osChildrenNames, err +} diff --git a/vendor/github.com/golang/dep/gps/pkgtree/ignored_ruleset.go b/vendor/github.com/golang/dep/gps/pkgtree/ignored_ruleset.go new file mode 100644 index 00000000..30b92bd8 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/pkgtree/ignored_ruleset.go @@ -0,0 +1,111 @@ +// Copyright 2017 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 pkgtree + +import ( + "sort" + "strings" + + "github.com/armon/go-radix" +) + +// IgnoredRuleset comprises a set of rules for ignoring import paths. It can +// manage both literal and prefix-wildcard matches. +type IgnoredRuleset struct { + t *radix.Tree +} + +// NewIgnoredRuleset processes a set of strings into an IgnoredRuleset. Strings +// that end in "*" are treated as wildcards, where any import path with a +// matching prefix will be ignored. IgnoredRulesets are immutable once created. +// +// Duplicate and redundant (i.e. a literal path that has a prefix of a wildcard +// path) declarations are discarded. Consequently, it is possible that the +// returned IgnoredRuleset may have a smaller Len() than the input slice. +func NewIgnoredRuleset(ig []string) *IgnoredRuleset { + if len(ig) == 0 { + return &IgnoredRuleset{} + } + + ir := &IgnoredRuleset{ + t: radix.New(), + } + + // Sort the list of all the ignores in order to ensure that wildcard + // precedence is recorded correctly in the trie. + sort.Strings(ig) + for _, i := range ig { + // Skip global ignore and empty string. + if i == "*" || i == "" { + continue + } + + _, wildi, has := ir.t.LongestPrefix(i) + // We may not always have a value here, but if we do, then it's a bool. + wild, _ := wildi.(bool) + // Check if it's a wildcard ignore. + if strings.HasSuffix(i, "*") { + // Check if it is ineffectual. + if has && wild { + // Skip ineffectual wildcard ignore. + continue + } + // Create the ignore prefix and insert in the radix tree. + ir.t.Insert(i[:len(i)-1], true) + } else if !has || !wild { + ir.t.Insert(i, false) + } + } + + if ir.t.Len() == 0 { + ir.t = nil + } + + return ir +} + +// IsIgnored indicates whether the provided path should be ignored, according to +// the ruleset. +func (ir *IgnoredRuleset) IsIgnored(path string) bool { + if path == "" || ir == nil || ir.t == nil { + return false + } + + prefix, wildi, has := ir.t.LongestPrefix(path) + return has && (wildi.(bool) || path == prefix) +} + +// Len indicates the number of rules in the ruleset. +func (ir *IgnoredRuleset) Len() int { + if ir == nil || ir.t == nil { + return 0 + } + + return ir.t.Len() +} + +// ToSlice converts the contents of the IgnoredRuleset to a string slice. +// +// This operation is symmetrically dual to NewIgnoredRuleset. +func (ir *IgnoredRuleset) ToSlice() []string { + irlen := ir.Len() + if irlen == 0 { + return nil + } + + items := make([]string, 0, irlen) + ir.t.Walk(func(s string, v interface{}) bool { + if s != "" { + if v.(bool) { + items = append(items, s+"*") + } else { + items = append(items, s) + } + } + return false + }) + + return items +} diff --git a/vendor/github.com/golang/dep/gps/pkgtree/ignored_ruleset_test.go b/vendor/github.com/golang/dep/gps/pkgtree/ignored_ruleset_test.go new file mode 100644 index 00000000..0dab4309 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/pkgtree/ignored_ruleset_test.go @@ -0,0 +1,204 @@ +// Copyright 2017 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 pkgtree + +import "testing" + +func TestIgnoredRuleset(t *testing.T) { + type tfixm []struct { + path string + wild bool + } + cases := []struct { + name string + inputs []string + wantInTree tfixm + wantEmptyTree bool + shouldIgnore []string + shouldNotIgnore []string + }{ + { + name: "only skip global ignore", + inputs: []string{"*"}, + wantEmptyTree: true, + }, + { + name: "ignores without ignore suffix", + inputs: []string{ + "x/y/z", + "*a/b/c", + "gophers", + }, + wantInTree: tfixm{ + {path: "x/y/z", wild: false}, + {path: "*a/b/c", wild: false}, + {path: "gophers", wild: false}, + }, + shouldIgnore: []string{ + "x/y/z", + "gophers", + }, + shouldNotIgnore: []string{ + "x/y/z/q", + "x/y", + "gopher", + "gopherss", + }, + }, + { + name: "ignores with ignore suffix", + inputs: []string{ + "x/y/z*", + "a/b/c", + "gophers", + }, + wantInTree: tfixm{ + {path: "x/y/z", wild: true}, + {path: "a/b/c", wild: false}, + {path: "gophers", wild: false}, + }, + shouldIgnore: []string{ + "x/y/z", + "x/y/zz", + "x/y/z/", + "x/y/z/q", + }, + shouldNotIgnore: []string{ + "x/y", + "gopher", + }, + }, + { + name: "global ignore with other strings", + inputs: []string{ + "*", + "gophers*", + "x/y/z*", + "a/b/c", + }, + wantInTree: tfixm{ + {path: "x/y/z", wild: true}, + {path: "a/b/c", wild: false}, + {path: "gophers", wild: true}, + }, + shouldIgnore: []string{ + "x/y/z", + "x/y/z/", + "x/y/z/q", + "gophers", + "gopherss", + "gophers/foo", + }, + shouldNotIgnore: []string{ + "x/y", + "gopher", + }, + }, + { + name: "ineffectual ignore with wildcard", + inputs: []string{ + "a/b*", + "a/b/c*", + "a/b/x/y", + "a/c*", + }, + wantInTree: tfixm{ + {path: "a/c", wild: true}, + {path: "a/b", wild: true}, + }, + shouldIgnore: []string{ + "a/cb", + }, + shouldNotIgnore: []string{ + "a/", + "a/d", + }, + }, + { + name: "same path with and without wildcard", + inputs: []string{ + "a/b*", + "a/b", + }, + wantInTree: tfixm{ + {path: "a/b", wild: true}, + }, + shouldIgnore: []string{ + "a/b", + "a/bb", + }, + shouldNotIgnore: []string{ + "a/", + "a/d", + }, + }, + { + name: "empty paths", + inputs: []string{ + "", + "a/b*", + }, + wantInTree: tfixm{ + {path: "a/b", wild: true}, + }, + shouldNotIgnore: []string{ + "", + }, + }, + { + name: "single wildcard", + inputs: []string{ + "a/b*", + }, + wantInTree: tfixm{ + {path: "a/b", wild: true}, + }, + shouldIgnore: []string{ + "a/b/c", + }, + }, + } + + for _, c := range cases { + igm := NewIgnoredRuleset(c.inputs) + f := func(t *testing.T) { + + if c.wantEmptyTree { + if igm.Len() != 0 { + t.Fatalf("wanted empty tree, but had %v elements", igm.Len()) + } + } + + // Check if the wildcard suffix ignores are in the tree. + for _, p := range c.wantInTree { + wildi, has := igm.t.Get(p.path) + if !has { + t.Fatalf("expected %q to be in the tree", p.path) + } else if wildi.(bool) != p.wild { + if p.wild { + t.Fatalf("expected %q to be a wildcard matcher, but it was not", p.path) + } else { + t.Fatalf("expected %q not to be a wildcard matcher, but it was", p.path) + } + } + } + + for _, p := range c.shouldIgnore { + if !igm.IsIgnored(p) { + t.Fatalf("%q should be ignored, but it was not", p) + } + } + for _, p := range c.shouldNotIgnore { + if igm.IsIgnored(p) { + t.Fatalf("%q should not be ignored, but it was", p) + } + } + } + t.Run(c.name, f) + + igm = NewIgnoredRuleset(igm.ToSlice()) + t.Run(c.name+"/inandout", f) + } +} diff --git a/vendor/github.com/golang/dep/gps/pkgtree/pkgtree.go b/vendor/github.com/golang/dep/gps/pkgtree/pkgtree.go new file mode 100644 index 00000000..7938b890 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/pkgtree/pkgtree.go @@ -0,0 +1,1108 @@ +// Copyright 2017 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 pkgtree + +import ( + "bytes" + "fmt" + "go/ast" + "go/build" + "go/parser" + gscan "go/scanner" + "go/token" + "os" + "path/filepath" + "reflect" + "sort" + "strconv" + "strings" + "unicode" +) + +// Package represents a Go package. It contains a subset of the information +// go/build.Package does. +type Package struct { + Name string // Package name, as declared in the package statement + ImportPath string // Full import path, including the prefix provided to ListPackages() + CommentPath string // Import path given in the comment on the package statement + Imports []string // Imports from all go and cgo files + TestImports []string // Imports from all go test files (in go/build parlance: both TestImports and XTestImports) +} + +// vcsRoots is a set of directories we should not descend into in ListPackages when +// searching for Go packages +var vcsRoots = map[string]struct{}{ + ".git": {}, + ".bzr": {}, + ".svn": {}, + ".hg": {}, +} + +// ListPackages reports Go package information about all directories in the tree +// at or below the provided fileRoot. +// +// The importRoot parameter is prepended to the relative path when determining +// the import path for each package. The obvious case is for something typical, +// like: +// +// fileRoot = "/home/user/go/src/github.com/foo/bar" +// importRoot = "github.com/foo/bar" +// +// where the fileRoot and importRoot align. However, if you provide: +// +// fileRoot = "/home/user/workspace/path/to/repo" +// importRoot = "github.com/foo/bar" +// +// then the root package at path/to/repo will be ascribed import path +// "github.com/foo/bar", and the package at +// "/home/user/workspace/path/to/repo/baz" will be "github.com/foo/bar/baz". +// +// A PackageTree is returned, which contains the ImportRoot and map of import path +// to PackageOrErr - each path under the root that exists will have either a +// Package, or an error describing why the directory is not a valid package. +func ListPackages(fileRoot, importRoot string) (PackageTree, error) { + ptree := PackageTree{ + ImportRoot: importRoot, + Packages: make(map[string]PackageOrErr), + } + + var err error + fileRoot, err = filepath.Abs(fileRoot) + if err != nil { + return PackageTree{}, err + } + + err = filepath.Walk(fileRoot, func(wp string, fi os.FileInfo, err error) error { + if err != nil && err != filepath.SkipDir { + if os.IsPermission(err) { + return filepath.SkipDir + } + return err + } + if !fi.IsDir() { + return nil + } + + // Skip dirs that are known to hold non-local/dependency code. + // + // We don't skip _*, or testdata dirs because, while it may be poor + // form, importing them is not a compilation error. + switch fi.Name() { + case "vendor", "Godeps": + return filepath.SkipDir + } + + // Skip dirs that are known to be VCS roots. + // + // Note that there are some pathological edge cases this doesn't cover, + // such as a user using Git for version control, but having a package + // named "svn" in a directory named ".svn". + if _, ok := vcsRoots[fi.Name()]; ok { + return filepath.SkipDir + } + + { + // For Go 1.9 and earlier: + // + // The entry error is nil when visiting a directory that itself is + // untraversable, as it's still governed by the parent directory's + // perms. We have to check readability of the dir here, because + // otherwise we'll have an empty package entry when we fail to read any + // of the dir's contents. + // + // If we didn't check here, then the next time this closure is called it + // would have an err with the same path as is called this time, as only + // then will filepath.Walk have attempted to descend into the directory + // and encountered an error. + var f *os.File + f, err = os.Open(wp) + if err != nil { + if os.IsPermission(err) { + return filepath.SkipDir + } + return err + } + f.Close() + } + + // Compute the import path. Run the result through ToSlash(), so that + // windows file paths are normalized to slashes, as is expected of + // import paths. + ip := filepath.ToSlash(filepath.Join(importRoot, strings.TrimPrefix(wp, fileRoot))) + + // Find all the imports, across all os/arch combos + p := &build.Package{ + Dir: wp, + ImportPath: ip, + } + err = fillPackage(p) + + if err != nil { + switch err.(type) { + case gscan.ErrorList, *gscan.Error, *build.NoGoError, *ConflictingImportComments: + // Assorted cases in which we've encounter malformed or + // nonexistent Go source code. + ptree.Packages[ip] = PackageOrErr{ + Err: err, + } + return nil + default: + return err + } + } + + pkg := Package{ + ImportPath: ip, + CommentPath: p.ImportComment, + Name: p.Name, + Imports: p.Imports, + TestImports: dedupeStrings(p.TestImports, p.XTestImports), + } + + if pkg.CommentPath != "" && !strings.HasPrefix(pkg.CommentPath, importRoot) { + ptree.Packages[ip] = PackageOrErr{ + Err: &NonCanonicalImportRoot{ + ImportRoot: importRoot, + Canonical: pkg.CommentPath, + }, + } + return nil + } + + // This area has some...fuzzy rules, but check all the imports for + // local/relative/dot-ness, and record an error for the package if we + // see any. + var lim []string + for _, imp := range append(pkg.Imports, pkg.TestImports...) { + if build.IsLocalImport(imp) { + // Do allow the single-dot, at least for now + if imp == "." { + continue + } + lim = append(lim, imp) + } + } + + if len(lim) > 0 { + ptree.Packages[ip] = PackageOrErr{ + Err: &LocalImportsError{ + Dir: wp, + ImportPath: ip, + LocalImports: lim, + }, + } + } else { + ptree.Packages[ip] = PackageOrErr{ + P: pkg, + } + } + + return nil + }) + + if err != nil { + return PackageTree{}, err + } + + return ptree, nil +} + +// fillPackage full of info. Assumes p.Dir is set at a minimum +func fillPackage(p *build.Package) error { + var buildPrefix = "// +build " + var buildFieldSplit = func(r rune) bool { + return unicode.IsSpace(r) || r == ',' + } + + gofiles, err := filepath.Glob(filepath.Join(p.Dir, "*.go")) + if err != nil { + return err + } + + if len(gofiles) == 0 { + return &build.NoGoError{Dir: p.Dir} + } + + var testImports []string + var imports []string + var importComments []string + for _, file := range gofiles { + // Skip underscore-led or dot-led files, in keeping with the rest of the toolchain. + bPrefix := filepath.Base(file)[0] + if bPrefix == '_' || bPrefix == '.' { + continue + } + + // Skip any directories that happened to get caught by glob + if stat, err := os.Stat(file); err == nil && stat.IsDir() { + continue + } + + pf, err := parser.ParseFile(token.NewFileSet(), file, nil, parser.ImportsOnly|parser.ParseComments) + if err != nil { + if os.IsPermission(err) { + continue + } + return err + } + testFile := strings.HasSuffix(file, "_test.go") + fname := filepath.Base(file) + + var ignored bool + for _, c := range pf.Comments { + ic := findImportComment(pf.Name, c) + if ic != "" { + importComments = append(importComments, ic) + } + if c.Pos() > pf.Package { // +build comment must come before package + continue + } + + var ct string + for _, cl := range c.List { + if strings.HasPrefix(cl.Text, buildPrefix) { + ct = cl.Text + break + } + } + if ct == "" { + continue + } + + for _, t := range strings.FieldsFunc(ct[len(buildPrefix):], buildFieldSplit) { + // hardcoded (for now) handling for the "ignore" build tag + // We "soft" ignore the files tagged with ignore so that we pull in their imports. + if t == "ignore" { + ignored = true + } + } + } + + if testFile { + p.TestGoFiles = append(p.TestGoFiles, fname) + if p.Name == "" && !ignored { + p.Name = strings.TrimSuffix(pf.Name.Name, "_test") + } + } else { + if p.Name == "" && !ignored { + p.Name = pf.Name.Name + } + p.GoFiles = append(p.GoFiles, fname) + } + + for _, is := range pf.Imports { + name, err := strconv.Unquote(is.Path.Value) + if err != nil { + return err // can't happen? + } + if testFile { + testImports = append(testImports, name) + } else { + imports = append(imports, name) + } + } + } + importComments = uniq(importComments) + if len(importComments) > 1 { + return &ConflictingImportComments{ + ImportPath: p.ImportPath, + ConflictingImportComments: importComments, + } + } + if len(importComments) > 0 { + p.ImportComment = importComments[0] + } + imports = uniq(imports) + testImports = uniq(testImports) + p.Imports = imports + p.TestImports = testImports + return nil +} + +var ( + slashSlash = []byte("//") + slashStar = []byte("/*") + starSlash = []byte("*/") + importKwd = []byte("import ") +) + +func findImportComment(pkgName *ast.Ident, c *ast.CommentGroup) string { + afterPkg := pkgName.NamePos + token.Pos(len(pkgName.Name)) + 1 + commentSlash := c.List[0].Slash + if afterPkg != commentSlash { + return "" + } + text := []byte(c.List[0].Text) + switch { + case bytes.HasPrefix(text, slashSlash): + eol := bytes.IndexByte(text, '\n') + if eol < 0 { + eol = len(text) + } + text = text[2:eol] + case bytes.HasPrefix(text, slashStar): + text = text[2:] + end := bytes.Index(text, starSlash) + if end < 0 { + // malformed comment + return "" + } + text = text[:end] + if bytes.IndexByte(text, '\n') > 0 { + // multiline comment, can't be an import comment + return "" + } + } + text = bytes.TrimSpace(text) + if !bytes.HasPrefix(text, importKwd) { + return "" + } + quotedPath := bytes.TrimSpace(text[len(importKwd):]) + return string(bytes.Trim(quotedPath, `"`)) +} + +// ConflictingImportComments indicates that the package declares more than one +// different canonical path. +type ConflictingImportComments struct { + ImportPath string // An import path referring to this package + ConflictingImportComments []string // All distinct "canonical" paths encountered in the package files +} + +func (e *ConflictingImportComments) Error() string { + return fmt.Sprintf("import path %s had conflicting import comments: %s", + e.ImportPath, quotedPaths(e.ConflictingImportComments)) +} + +// NonCanonicalImportRoot reports the situation when the dependee imports a +// package via something other than the package's declared canonical path. +type NonCanonicalImportRoot struct { + ImportRoot string // A root path that is being used to import a package + Canonical string // A canonical path declared by the package being imported +} + +func (e *NonCanonicalImportRoot) Error() string { + return fmt.Sprintf("import root %q is not a prefix for the package's declared canonical path %q", + e.ImportRoot, e.Canonical) +} + +func quotedPaths(ps []string) string { + quoted := make([]string, 0, len(ps)) + for _, p := range ps { + quoted = append(quoted, fmt.Sprintf("%q", p)) + } + return strings.Join(quoted, ", ") +} + +// LocalImportsError indicates that a package contains at least one relative +// import that will prevent it from compiling. +// +// TODO(sdboyer) add a Files property once we're doing our own per-file parsing +type LocalImportsError struct { + ImportPath string + Dir string + LocalImports []string +} + +func (e *LocalImportsError) Error() string { + switch len(e.LocalImports) { + case 0: + // shouldn't be possible, but just cover the case + return fmt.Sprintf("import path %s had bad local imports", e.ImportPath) + case 1: + return fmt.Sprintf("import path %s had a local import: %q", e.ImportPath, e.LocalImports[0]) + default: + return fmt.Sprintf("import path %s had local imports: %s", e.ImportPath, quotedPaths(e.LocalImports)) + } +} + +type wm struct { + err error + ex map[string]bool + in map[string]bool +} + +// PackageOrErr stores the results of attempting to parse a single directory for +// Go source code. +type PackageOrErr struct { + P Package + Err error +} + +// ProblemImportError describes the reason that a particular import path is +// not safely importable. +type ProblemImportError struct { + // The import path of the package with some problem rendering it + // unimportable. + ImportPath string + // The path to the internal package the problem package imports that is the + // original cause of this issue. If empty, the package itself is the + // problem. + Cause []string + // The actual error from ListPackages that is undermining importability for + // this package. + Err error +} + +// Error formats the ProblemImportError as a string, reflecting whether the +// error represents a direct or transitive problem. +func (e *ProblemImportError) Error() string { + switch len(e.Cause) { + case 0: + return fmt.Sprintf("%q contains malformed code: %s", e.ImportPath, e.Err.Error()) + case 1: + return fmt.Sprintf("%q imports %q, which contains malformed code: %s", e.ImportPath, e.Cause[0], e.Err.Error()) + default: + return fmt.Sprintf("%q transitively (through %v packages) imports %q, which contains malformed code: %s", e.ImportPath, len(e.Cause)-1, e.Cause[len(e.Cause)-1], e.Err.Error()) + } +} + +// Helper func to create an error when a package is missing. +func missingPkgErr(pkg string) error { + return fmt.Errorf("no package exists at %q", pkg) +} + +// A PackageTree represents the results of recursively parsing a tree of +// packages, starting at the ImportRoot. The results of parsing the files in the +// directory identified by each import path - a Package or an error - are stored +// in the Packages map, keyed by that import path. +type PackageTree struct { + ImportRoot string + Packages map[string]PackageOrErr +} + +// ToReachMap looks through a PackageTree and computes the list of external +// import statements (that is, import statements pointing to packages that are +// not logical children of PackageTree.ImportRoot) that are transitively +// imported by the internal packages in the tree. +// +// main indicates whether (true) or not (false) to include main packages in the +// analysis. When utilized by gps' solver, main packages are generally excluded +// from analyzing anything other than the root project, as they necessarily can't +// be imported. +// +// tests indicates whether (true) or not (false) to include imports from test +// files in packages when computing the reach map. +// +// backprop indicates whether errors (an actual PackageOrErr.Err, or an import +// to a nonexistent internal package) should be backpropagated, transitively +// "poisoning" all corresponding importers to all importers. +// +// ignore is a map of import paths that, if encountered, should be excluded from +// analysis. This exclusion applies to both internal and external packages. If +// an external import path is ignored, it is simply omitted from the results. +// +// If an internal path is ignored, then it not only does not appear in the final +// map, but it is also excluded from the transitive calculations of other +// internal packages. That is, if you ignore A/foo, then the external package +// list for all internal packages that import A/foo will not include external +// packages that are only reachable through A/foo. +// +// Visually, this means that, given a PackageTree with root A and packages at A, +// A/foo, and A/bar, and the following import chain: +// +// A -> A/foo -> A/bar -> B/baz +// +// In this configuration, all of A's packages transitively import B/baz, so the +// returned map would be: +// +// map[string][]string{ +// "A": []string{"B/baz"}, +// "A/foo": []string{"B/baz"} +// "A/bar": []string{"B/baz"}, +// } +// +// However, if you ignore A/foo, then A's path to B/baz is broken, and A/foo is +// omitted entirely. Thus, the returned map would be: +// +// map[string][]string{ +// "A": []string{}, +// "A/bar": []string{"B/baz"}, +// } +// +// If there are no packages to ignore, it is safe to pass a nil map. +// +// Finally, if an internal PackageOrErr contains an error, it is always omitted +// from the result set. If backprop is true, then the error from that internal +// package will be transitively propagated back to any other internal +// PackageOrErrs that import it, causing them to also be omitted. So, with the +// same import chain: +// +// A -> A/foo -> A/bar -> B/baz +// +// If A/foo has an error, then it would backpropagate to A, causing both to be +// omitted, and the returned map to contain only A/bar: +// +// map[string][]string{ +// "A/bar": []string{"B/baz"}, +// } +// +// If backprop is false, then errors will not backpropagate to internal +// importers. So, with an error in A/foo, this would be the result map: +// +// map[string][]string{ +// "A": []string{}, +// "A/bar": []string{"B/baz"}, +// } +func (t PackageTree) ToReachMap(main, tests, backprop bool, ignore *IgnoredRuleset) (ReachMap, map[string]*ProblemImportError) { + // world's simplest adjacency list + workmap := make(map[string]wm) + + var imps []string + for ip, perr := range t.Packages { + if perr.Err != nil { + workmap[ip] = wm{ + err: perr.Err, + } + continue + } + p := perr.P + + // Skip main packages, unless param says otherwise + if p.Name == "main" && !main { + continue + } + // Skip ignored packages + if ignore.IsIgnored(ip) { + continue + } + + // TODO (kris-nova) Disable to get staticcheck passing + //imps = imps[:0] + + if tests { + imps = dedupeStrings(p.Imports, p.TestImports) + } else { + imps = p.Imports + } + + w := wm{ + ex: make(map[string]bool), + in: make(map[string]bool), + } + + // For each import, decide whether it should be ignored, or if it + // belongs in the external or internal imports list. + for _, imp := range imps { + if ignore.IsIgnored(imp) || imp == "." { + continue + } + + if !eqOrSlashedPrefix(imp, t.ImportRoot) { + w.ex[imp] = true + } else { + w.in[imp] = true + } + } + + workmap[ip] = w + } + + return wmToReach(workmap, backprop) +} + +// Copy copies the PackageTree. +// +// This is really only useful as a defensive measure to prevent external state +// mutations. +func (t PackageTree) Copy() PackageTree { + t2 := PackageTree{ + ImportRoot: t.ImportRoot, + Packages: make(map[string]PackageOrErr, len(t.Packages)), + } + + // Walk through and count up the total number of string slice elements we'll + // need, then allocate them all at once. + strcount := 0 + for _, poe := range t.Packages { + strcount = strcount + len(poe.P.Imports) + len(poe.P.TestImports) + } + pool := make([]string, strcount) + + for path, poe := range t.Packages { + var poe2 PackageOrErr + + if poe.Err != nil { + refl := reflect.ValueOf(poe.Err) + switch refl.Kind() { + case reflect.Ptr: + poe2.Err = reflect.New(refl.Elem().Type()).Interface().(error) + case reflect.Slice: + err2 := reflect.MakeSlice(refl.Type(), refl.Len(), refl.Len()) + reflect.Copy(err2, refl) + poe2.Err = err2.Interface().(error) + default: + // This shouldn't be too onerous to maintain - the set of errors + // we can get here is restricted by what ListPackages() allows. + // So just panic if one is outside the expected kinds of ptr or + // slice, as that would mean we've missed something notable. + panic(fmt.Sprintf("unrecognized PackgeOrErr error type, %T", poe.Err)) + } + } else { + poe2.P = poe.P + il, til := len(poe.P.Imports), len(poe.P.TestImports) + if il > 0 { + poe2.P.Imports, pool = pool[:il], pool[il:] + copy(poe2.P.Imports, poe.P.Imports) + } + if til > 0 { + poe2.P.TestImports, pool = pool[:til], pool[til:] + copy(poe2.P.TestImports, poe.P.TestImports) + } + } + + t2.Packages[path] = poe2 + } + + return t2 +} + +// TrimHiddenPackages returns a new PackageTree where packages that are ignored, +// or both hidden and unreachable, have been removed. +// +// The package list is partitioned into two sets: visible, and hidden, where +// packages are considered hidden if they are within or beneath directories +// with: +// +// * leading dots +// * leading underscores +// * the exact name "testdata" +// +// Packages in the hidden set are dropped from the returned PackageTree, unless +// they are transitively reachable from imports in the visible set. +// +// The "main", "tests" and "ignored" parameters have the same behavior as with +// PackageTree.ToReachMap(): the first two determine, respectively, whether +// imports from main packages, and imports from tests, should be considered for +// reachability checks. Setting 'main' to true will additionally result in main +// packages being trimmed. +// +// "ignored" designates import paths, or patterns of import paths, where the +// corresponding packages should be excluded from reachability checks, if +// encountered. Ignored packages are also removed from the final set. +// +// Note that it is not recommended to call this method if the goal is to obtain +// a set of tree-external imports; calling ToReachMap and FlattenFn will achieve +// the same effect. +func (t PackageTree) TrimHiddenPackages(main, tests bool, ignore *IgnoredRuleset) PackageTree { + rm, pie := t.ToReachMap(main, tests, false, ignore) + t2 := t.Copy() + preserve := make(map[string]bool) + + for pkg, ie := range rm { + if pkgFilter(pkg) && !ignore.IsIgnored(pkg) { + preserve[pkg] = true + for _, in := range ie.Internal { + preserve[in] = true + } + } + } + + // Also process the problem map, as packages in the visible set with errors + // need to be included in the return values. + for pkg := range pie { + if pkgFilter(pkg) && !ignore.IsIgnored(pkg) { + preserve[pkg] = true + } + } + + for ip := range t.Packages { + if !preserve[ip] { + delete(t2.Packages, ip) + } + } + + return t2 +} + +// wmToReach takes an internal "workmap" constructed by +// PackageTree.ExternalReach(), transitively walks (via depth-first traversal) +// all internal imports until they reach an external path or terminate, then +// translates the results into a slice of external imports for each internal +// pkg. +// +// It drops any packages with errors, and - if backprop is true - backpropagates +// those errors, causing internal packages that (transitively) import other +// internal packages having errors to also be dropped. +func wmToReach(workmap map[string]wm, backprop bool) (ReachMap, map[string]*ProblemImportError) { + // Uses depth-first exploration to compute reachability into external + // packages, dropping any internal packages on "poisoned paths" - a path + // containing a package with an error, or with a dep on an internal package + // that's missing. + + const ( + white uint8 = iota + grey + black + ) + + colors := make(map[string]uint8) + exrsets := make(map[string]map[string]struct{}) + inrsets := make(map[string]map[string]struct{}) + errmap := make(map[string]*ProblemImportError) + + // poison is a helper func to eliminate specific reachsets from exrsets and + // inrsets, and populate error information along the way. + poison := func(path []string, err *ProblemImportError) { + for k, ppkg := range path { + delete(exrsets, ppkg) + delete(inrsets, ppkg) + + // Duplicate the err for this package + kerr := &ProblemImportError{ + ImportPath: ppkg, + Err: err.Err, + } + + // Shift the slice bounds on the incoming err.Cause. + // + // This check will only be false on the final path element when + // entering via poisonWhite, where the last pkg is the underlying + // cause of the problem, and is thus expected to have an empty Cause + // slice. + if k+1 < len(err.Cause) { + // reuse the slice + kerr.Cause = err.Cause[k+1:] + } + + // Both black and white cases can have the final element be a + // package that doesn't exist. If that's the case, don't write it + // directly to the errmap, as presence in the errmap indicates the + // package was present in the input PackageTree. + if k == len(path)-1 { + if _, exists := workmap[path[len(path)-1]]; !exists { + continue + } + } + + // Direct writing to the errmap means that if multiple errors affect + // a given package, only the last error visited will be reported. + // But that should be sufficient; presumably, the user can + // iteratively resolve the errors. + errmap[ppkg] = kerr + } + } + + // poisonWhite wraps poison for error recording in the white-poisoning case, + // where we're constructing a new poison path. + poisonWhite := func(path []string) { + err := &ProblemImportError{ + Cause: make([]string, len(path)), + } + copy(err.Cause, path) + + // find the tail err + tail := path[len(path)-1] + if w, exists := workmap[tail]; exists { + // If we make it to here, the dfe guarantees that the workmap + // will contain an error for this pkg. + err.Err = w.err + } else { + err.Err = missingPkgErr(tail) + } + + poison(path, err) + } + // poisonBlack wraps poison for error recording in the black-poisoning case, + // where we're connecting to an existing poison path. + poisonBlack := func(path []string, from string) { + // Because the outer dfe loop ensures we never directly re-visit a pkg + // that was already completed (black), we don't have to defend against + // an empty path here. + + fromErr, exists := errmap[from] + // FIXME: It should not be possible for fromErr to not exist, + // See issue https://github.com/golang/dep/issues/351 + // This is a temporary solution to avoid a panic. + if !exists { + fromErr = &ProblemImportError{ + Err: fmt.Errorf("unknown error for %q, if you get this error see https://github.com/golang/dep/issues/351", from), + } + } + err := &ProblemImportError{ + Err: fromErr.Err, + Cause: make([]string, 0, len(path)+len(fromErr.Cause)+1), + } + err.Cause = append(err.Cause, path...) + err.Cause = append(err.Cause, from) + err.Cause = append(err.Cause, fromErr.Cause...) + + poison(path, err) + } + + var dfe func(string, []string) bool + + // dfe is the depth-first-explorer that computes a safe, error-free external + // reach map. + // + // pkg is the import path of the pkg currently being visited; path is the + // stack of parent packages we've visited to get to pkg. The return value + // indicates whether the level completed successfully (true) or if it was + // poisoned (false). + dfe = func(pkg string, path []string) bool { + // white is the zero value of uint8, which is what we want if the pkg + // isn't in the colors map, so this works fine + switch colors[pkg] { + case white: + // first visit to this pkg; mark it as in-process (grey) + colors[pkg] = grey + + // make sure it's present and w/out errs + w, exists := workmap[pkg] + + // Push current visitee onto the path slice. Passing path through + // recursion levels as a value has the effect of auto-popping the + // slice, while also giving us safe memory reuse. + path = append(path, pkg) + + if !exists || w.err != nil { + if backprop { + // Does not exist or has an err; poison self and all parents + poisonWhite(path) + } else if exists { + // Only record something in the errmap if there's actually a + // package there, per the semantics of the errmap + errmap[pkg] = &ProblemImportError{ + ImportPath: pkg, + Err: w.err, + } + } + + // we know we're done here, so mark it black + colors[pkg] = black + return false + } + // pkg exists with no errs; start internal and external reachsets for it. + rs := make(map[string]struct{}) + irs := make(map[string]struct{}) + + // Dump this package's external pkgs into its own reachset. Separate + // loop from the parent dump to avoid nested map loop lookups. + for ex := range w.ex { + rs[ex] = struct{}{} + } + exrsets[pkg] = rs + // Same deal for internal imports + for in := range w.in { + irs[in] = struct{}{} + } + inrsets[pkg] = irs + + // Push this pkg's imports into all parent reachsets. Not all + // parents will necessarily have a reachset; none, some, or all + // could have been poisoned by a different path than what we're on + // right now. + for _, ppkg := range path { + if prs, exists := exrsets[ppkg]; exists { + for ex := range w.ex { + prs[ex] = struct{}{} + } + } + + if prs, exists := inrsets[ppkg]; exists { + for in := range w.in { + prs[in] = struct{}{} + } + } + } + + // Now, recurse until done, or a false bubbles up, indicating the + // path is poisoned. + for in := range w.in { + // It's possible, albeit weird, for a package to import itself. + // If we try to visit self, though, then it erroneously poisons + // the path, as it would be interpreted as grey. In practice, + // self-imports are a no-op, so we can just skip it. + if in == pkg { + continue + } + + clean := dfe(in, path) + if !clean && backprop { + // Path is poisoned. If we're backpropagating errors, then + // the reachmap for the visitee was already deleted by the + // path we're returning from; mark the visitee black, then + // return false to bubble up the poison. This is OK to do + // early, before exploring all internal imports, because the + // outer loop visits all internal packages anyway. + // + // In fact, stopping early is preferable - white subpackages + // won't have to iterate pointlessly through a parent path + // with no reachset. + colors[pkg] = black + return false + } + } + + // Fully done with this pkg; no transitive problems. + colors[pkg] = black + return true + + case grey: + // Import cycles can arise in healthy situations through xtests, so + // allow them for now. + // + // FIXME(sdboyer) we need an improved model that allows us to + // accurately reject real import cycles. + return true + // grey means an import cycle; guaranteed badness right here. You'd + // hope we never encounter it in a dependency (really? you published + // that code?), but we have to defend against it. + //colors[pkg] = black + //poison(append(path, pkg)) // poison self and parents + + case black: + // black means we're revisiting a package that was already + // completely explored. If it has an entry in exrsets, it completed + // successfully. If not, it was poisoned, and we need to bubble the + // poison back up. + rs, exists := exrsets[pkg] + if !exists { + if backprop { + // just poison parents; self was necessarily already poisoned + poisonBlack(path, pkg) + } + return false + } + // If external reachset existed, internal must (even if empty) + irs := inrsets[pkg] + + // It's good; pull over the imports from its reachset into all + // non-poisoned parent reachsets + for _, ppkg := range path { + if prs, exists := exrsets[ppkg]; exists { + for ex := range rs { + prs[ex] = struct{}{} + } + } + + if prs, exists := inrsets[ppkg]; exists { + for in := range irs { + prs[in] = struct{}{} + } + } + } + return true + + default: + panic(fmt.Sprintf("invalid color marker %v for %s", colors[pkg], pkg)) + } + } + + // Run the depth-first exploration. + // + // Don't bother computing graph sources, this straightforward loop works + // comparably well, and fits nicely with an escape hatch in the dfe. + var path []string + for pkg := range workmap { + // However, at least check that the package isn't already fully visited; + // this saves a bit of time and implementation complexity inside the + // closures. + if colors[pkg] != black { + dfe(pkg, path) + } + } + + type ie struct { + Internal, External []string + } + + // Flatten exrsets into reachmap + rm := make(ReachMap) + for pkg, rs := range exrsets { + rlen := len(rs) + if rlen == 0 { + rm[pkg] = ie{} + continue + } + + edeps := make([]string, 0, rlen) + for opkg := range rs { + edeps = append(edeps, opkg) + } + + sort.Strings(edeps) + + sets := rm[pkg] + sets.External = edeps + rm[pkg] = sets + } + + // Flatten inrsets into reachmap + for pkg, rs := range inrsets { + rlen := len(rs) + if rlen == 0 { + continue + } + + ideps := make([]string, 0, rlen) + for opkg := range rs { + ideps = append(ideps, opkg) + } + + sort.Strings(ideps) + + sets := rm[pkg] + sets.Internal = ideps + rm[pkg] = sets + } + + return rm, errmap +} + +// eqOrSlashedPrefix checks to see if the prefix is either equal to the string, +// or that it is a prefix and the next char in the string is "/". +func eqOrSlashedPrefix(s, prefix string) bool { + if !strings.HasPrefix(s, prefix) { + return false + } + + prflen, pathlen := len(prefix), len(s) + return prflen == pathlen || strings.Index(s[prflen:], "/") == 0 +} + +// helper func to merge, dedupe, and sort strings +func dedupeStrings(s1, s2 []string) (r []string) { + dedupe := make(map[string]bool) + + if len(s1) > 0 && len(s2) > 0 { + for _, i := range s1 { + dedupe[i] = true + } + for _, i := range s2 { + dedupe[i] = true + } + + for i := range dedupe { + r = append(r, i) + } + // And then re-sort them + sort.Strings(r) + } else if len(s1) > 0 { + r = s1 + } else if len(s2) > 0 { + r = s2 + } + + return +} + +func uniq(a []string) []string { + if a == nil { + return make([]string, 0) + } + var s string + var i int + if !sort.StringsAreSorted(a) { + sort.Strings(a) + } + for _, t := range a { + if t != s { + a[i] = t + i++ + s = t + } + } + return a[:i] +} diff --git a/vendor/github.com/golang/dep/gps/pkgtree/pkgtree_test.go b/vendor/github.com/golang/dep/gps/pkgtree/pkgtree_test.go new file mode 100644 index 00000000..16b0ddc7 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/pkgtree/pkgtree_test.go @@ -0,0 +1,2273 @@ +// Copyright 2017 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 pkgtree + +import ( + "fmt" + "go/build" + "go/scanner" + "go/token" + "io/ioutil" + "os" + "path" + "path/filepath" + "reflect" + "runtime" + "strings" + "testing" + + "github.com/golang/dep/gps/paths" + "github.com/golang/dep/internal/fs" + _ "github.com/golang/dep/internal/test" // DO NOT REMOVE, allows go test ./... -update to work +) + +// PackageTree.ToReachMap() uses an easily separable algorithm, wmToReach(), +// to turn a discovered set of packages and their imports into a proper pair of +// internal and external reach maps. +// +// That algorithm is purely symbolic (no filesystem interaction), and thus is +// easy to test. This is that test. +func TestWorkmapToReach(t *testing.T) { + empty := func() map[string]bool { + return make(map[string]bool) + } + + table := map[string]struct { + workmap map[string]wm + rm ReachMap + em map[string]*ProblemImportError + backprop bool + }{ + "single": { + workmap: map[string]wm{ + "foo": { + ex: empty(), + in: empty(), + }, + }, + rm: ReachMap{ + "foo": {}, + }, + }, + "no external": { + workmap: map[string]wm{ + "foo": { + ex: empty(), + in: empty(), + }, + "foo/bar": { + ex: empty(), + in: empty(), + }, + }, + rm: ReachMap{ + "foo": {}, + "foo/bar": {}, + }, + }, + "no external with subpkg": { + workmap: map[string]wm{ + "foo": { + ex: empty(), + in: map[string]bool{ + "foo/bar": true, + }, + }, + "foo/bar": { + ex: empty(), + in: empty(), + }, + }, + rm: ReachMap{ + "foo": { + Internal: []string{"foo/bar"}, + }, + "foo/bar": {}, + }, + }, + "simple base transitive": { + workmap: map[string]wm{ + "foo": { + ex: empty(), + in: map[string]bool{ + "foo/bar": true, + }, + }, + "foo/bar": { + ex: map[string]bool{ + "baz": true, + }, + in: empty(), + }, + }, + rm: ReachMap{ + "foo": { + External: []string{"baz"}, + Internal: []string{"foo/bar"}, + }, + "foo/bar": { + External: []string{"baz"}, + }, + }, + }, + "missing package is poison": { + workmap: map[string]wm{ + "A": { + ex: map[string]bool{ + "B/foo": true, + }, + in: map[string]bool{ + "A/foo": true, // missing + "A/bar": true, + }, + }, + "A/bar": { + ex: map[string]bool{ + "B/baz": true, + }, + in: empty(), + }, + }, + rm: ReachMap{ + "A/bar": { + External: []string{"B/baz"}, + }, + }, + em: map[string]*ProblemImportError{ + "A": { + ImportPath: "A", + Cause: []string{"A/foo"}, + Err: missingPkgErr("A/foo"), + }, + }, + backprop: true, + }, + "transitive missing package is poison": { + workmap: map[string]wm{ + "A": { + ex: map[string]bool{ + "B/foo": true, + }, + in: map[string]bool{ + "A/foo": true, // transitively missing + "A/quux": true, + }, + }, + "A/foo": { + ex: map[string]bool{ + "C/flugle": true, + }, + in: map[string]bool{ + "A/bar": true, // missing + }, + }, + "A/quux": { + ex: map[string]bool{ + "B/baz": true, + }, + in: empty(), + }, + }, + rm: ReachMap{ + "A/quux": { + External: []string{"B/baz"}, + }, + }, + em: map[string]*ProblemImportError{ + "A": { + ImportPath: "A", + Cause: []string{"A/foo", "A/bar"}, + Err: missingPkgErr("A/bar"), + }, + "A/foo": { + ImportPath: "A/foo", + Cause: []string{"A/bar"}, + Err: missingPkgErr("A/bar"), + }, + }, + backprop: true, + }, + "err'd package is poison": { + workmap: map[string]wm{ + "A": { + ex: map[string]bool{ + "B/foo": true, + }, + in: map[string]bool{ + "A/foo": true, // err'd + "A/bar": true, + }, + }, + "A/foo": { + err: fmt.Errorf("err pkg"), + }, + "A/bar": { + ex: map[string]bool{ + "B/baz": true, + }, + in: empty(), + }, + }, + rm: ReachMap{ + "A/bar": { + External: []string{"B/baz"}, + }, + }, + em: map[string]*ProblemImportError{ + "A": { + ImportPath: "A", + Cause: []string{"A/foo"}, + Err: fmt.Errorf("err pkg"), + }, + "A/foo": { + ImportPath: "A/foo", + Err: fmt.Errorf("err pkg"), + }, + }, + backprop: true, + }, + "transitive err'd package is poison": { + workmap: map[string]wm{ + "A": { + ex: map[string]bool{ + "B/foo": true, + }, + in: map[string]bool{ + "A/foo": true, // transitively err'd + "A/quux": true, + }, + }, + "A/foo": { + ex: map[string]bool{ + "C/flugle": true, + }, + in: map[string]bool{ + "A/bar": true, // err'd + }, + }, + "A/bar": { + err: fmt.Errorf("err pkg"), + }, + "A/quux": { + ex: map[string]bool{ + "B/baz": true, + }, + in: empty(), + }, + }, + rm: ReachMap{ + "A/quux": { + External: []string{"B/baz"}, + }, + }, + em: map[string]*ProblemImportError{ + "A": { + ImportPath: "A", + Cause: []string{"A/foo", "A/bar"}, + Err: fmt.Errorf("err pkg"), + }, + "A/foo": { + ImportPath: "A/foo", + Cause: []string{"A/bar"}, + Err: fmt.Errorf("err pkg"), + }, + "A/bar": { + ImportPath: "A/bar", + Err: fmt.Errorf("err pkg"), + }, + }, + backprop: true, + }, + "transitive err'd package no backprop": { + workmap: map[string]wm{ + "A": { + ex: map[string]bool{ + "B/foo": true, + }, + in: map[string]bool{ + "A/foo": true, // transitively err'd + "A/quux": true, + }, + }, + "A/foo": { + ex: map[string]bool{ + "C/flugle": true, + }, + in: map[string]bool{ + "A/bar": true, // err'd + }, + }, + "A/bar": { + err: fmt.Errorf("err pkg"), + }, + "A/quux": { + ex: map[string]bool{ + "B/baz": true, + }, + in: empty(), + }, + }, + rm: ReachMap{ + "A": { + Internal: []string{"A/bar", "A/foo", "A/quux"}, + //Internal: []string{"A/foo", "A/quux"}, + External: []string{"B/baz", "B/foo", "C/flugle"}, + }, + "A/foo": { + Internal: []string{"A/bar"}, + External: []string{"C/flugle"}, + }, + "A/quux": { + External: []string{"B/baz"}, + }, + }, + em: map[string]*ProblemImportError{ + "A/bar": { + ImportPath: "A/bar", + Err: fmt.Errorf("err pkg"), + }, + }, + }, + // The following tests are mostly about regressions and weeding out + // weird assumptions + "internal diamond": { + workmap: map[string]wm{ + "A": { + ex: map[string]bool{ + "B/foo": true, + }, + in: map[string]bool{ + "A/foo": true, + "A/bar": true, + }, + }, + "A/foo": { + ex: map[string]bool{ + "C": true, + }, + in: map[string]bool{ + "A/quux": true, + }, + }, + "A/bar": { + ex: map[string]bool{ + "D": true, + }, + in: map[string]bool{ + "A/quux": true, + }, + }, + "A/quux": { + ex: map[string]bool{ + "B/baz": true, + }, + in: empty(), + }, + }, + rm: ReachMap{ + "A": { + External: []string{ + "B/baz", + "B/foo", + "C", + "D", + }, + Internal: []string{ + "A/bar", + "A/foo", + "A/quux", + }, + }, + "A/foo": { + External: []string{ + "B/baz", + "C", + }, + Internal: []string{ + "A/quux", + }, + }, + "A/bar": { + External: []string{ + "B/baz", + "D", + }, + Internal: []string{ + "A/quux", + }, + }, + "A/quux": { + External: []string{"B/baz"}, + }, + }, + }, + "rootmost gets imported": { + workmap: map[string]wm{ + "A": { + ex: map[string]bool{ + "B": true, + }, + in: empty(), + }, + "A/foo": { + ex: map[string]bool{ + "C": true, + }, + in: map[string]bool{ + "A": true, + }, + }, + }, + rm: ReachMap{ + "A": { + External: []string{"B"}, + }, + "A/foo": { + External: []string{ + "B", + "C", + }, + Internal: []string{ + "A", + }, + }, + }, + }, + } + + for name, fix := range table { + name, fix := name, fix + t.Run(name, func(t *testing.T) { + t.Parallel() + + // Avoid erroneous errors by initializing the fixture's error map if + // needed + if fix.em == nil { + fix.em = make(map[string]*ProblemImportError) + } + + rm, em := wmToReach(fix.workmap, fix.backprop) + if !reflect.DeepEqual(rm, fix.rm) { + //t.Error(pretty.Sprintf("wmToReach(%q): Did not get expected reach map:\n\t(GOT): %s\n\t(WNT): %s", name, rm, fix.rm)) + t.Errorf("Did not get expected reach map:\n\t(GOT): %s\n\t(WNT): %s", rm, fix.rm) + } + if !reflect.DeepEqual(em, fix.em) { + //t.Error(pretty.Sprintf("wmToReach(%q): Did not get expected error map:\n\t(GOT): %# v\n\t(WNT): %# v", name, em, fix.em)) + t.Errorf("Did not get expected error map:\n\t(GOT): %v\n\t(WNT): %v", em, fix.em) + } + }) + } +} + +func TestListPackagesNoDir(t *testing.T) { + out, err := ListPackages(filepath.Join(getTestdataRootDir(t), "notexist"), "notexist") + if err == nil { + t.Error("ListPackages should have errored on pointing to a nonexistent dir") + } + if !reflect.DeepEqual(PackageTree{}, out) { + t.Error("should've gotten back an empty PackageTree") + } +} + +func TestListPackages(t *testing.T) { + srcdir := filepath.Join(getTestdataRootDir(t), "src") + j := func(s ...string) string { + return filepath.Join(srcdir, filepath.Join(s...)) + } + + table := map[string]struct { + fileRoot string + importRoot string + out PackageTree + err error + }{ + "empty": { + fileRoot: j("empty"), + importRoot: "empty", + out: PackageTree{ + ImportRoot: "empty", + Packages: map[string]PackageOrErr{ + "empty": { + Err: &build.NoGoError{ + Dir: j("empty"), + }, + }, + }, + }, + }, + "code only": { + fileRoot: j("simple"), + importRoot: "simple", + out: PackageTree{ + ImportRoot: "simple", + Packages: map[string]PackageOrErr{ + "simple": { + P: Package{ + ImportPath: "simple", + CommentPath: "", + Name: "simple", + Imports: []string{ + "github.com/golang/dep/gps", + "sort", + }, + }, + }, + }, + }, + }, + "impose import path": { + fileRoot: j("simple"), + importRoot: "arbitrary", + out: PackageTree{ + ImportRoot: "arbitrary", + Packages: map[string]PackageOrErr{ + "arbitrary": { + P: Package{ + ImportPath: "arbitrary", + CommentPath: "", + Name: "simple", + Imports: []string{ + "github.com/golang/dep/gps", + "sort", + }, + }, + }, + }, + }, + }, + "test only": { + fileRoot: j("t"), + importRoot: "simple", + out: PackageTree{ + ImportRoot: "simple", + Packages: map[string]PackageOrErr{ + "simple": { + P: Package{ + ImportPath: "simple", + CommentPath: "", + Name: "simple", + Imports: []string{}, + TestImports: []string{ + "math/rand", + "strconv", + }, + }, + }, + }, + }, + }, + "xtest only": { + fileRoot: j("xt"), + importRoot: "simple", + out: PackageTree{ + ImportRoot: "simple", + Packages: map[string]PackageOrErr{ + "simple": { + P: Package{ + ImportPath: "simple", + CommentPath: "", + Name: "simple", + Imports: []string{}, + TestImports: []string{ + "sort", + "strconv", + }, + }, + }, + }, + }, + }, + "code and test": { + fileRoot: j("simplet"), + importRoot: "simple", + out: PackageTree{ + ImportRoot: "simple", + Packages: map[string]PackageOrErr{ + "simple": { + P: Package{ + ImportPath: "simple", + CommentPath: "", + Name: "simple", + Imports: []string{ + "github.com/golang/dep/gps", + "sort", + }, + TestImports: []string{ + "math/rand", + "strconv", + }, + }, + }, + }, + }, + }, + "code and xtest": { + fileRoot: j("simplext"), + importRoot: "simple", + out: PackageTree{ + ImportRoot: "simple", + Packages: map[string]PackageOrErr{ + "simple": { + P: Package{ + ImportPath: "simple", + CommentPath: "", + Name: "simple", + Imports: []string{ + "github.com/golang/dep/gps", + "sort", + }, + TestImports: []string{ + "sort", + "strconv", + }, + }, + }, + }, + }, + }, + "code, test, xtest": { + fileRoot: j("simpleallt"), + importRoot: "simple", + out: PackageTree{ + ImportRoot: "simple", + Packages: map[string]PackageOrErr{ + "simple": { + P: Package{ + ImportPath: "simple", + CommentPath: "", + Name: "simple", + Imports: []string{ + "github.com/golang/dep/gps", + "sort", + }, + TestImports: []string{ + "math/rand", + "sort", + "strconv", + }, + }, + }, + }, + }, + }, + "one pkg multifile": { + fileRoot: j("m1p"), + importRoot: "m1p", + out: PackageTree{ + ImportRoot: "m1p", + Packages: map[string]PackageOrErr{ + "m1p": { + P: Package{ + ImportPath: "m1p", + CommentPath: "", + Name: "m1p", + Imports: []string{ + "github.com/golang/dep/gps", + "os", + "sort", + }, + }, + }, + }, + }, + }, + "one nested below": { + fileRoot: j("nest"), + importRoot: "nest", + out: PackageTree{ + ImportRoot: "nest", + Packages: map[string]PackageOrErr{ + "nest": { + P: Package{ + ImportPath: "nest", + CommentPath: "", + Name: "simple", + Imports: []string{ + "github.com/golang/dep/gps", + "sort", + }, + }, + }, + "nest/m1p": { + P: Package{ + ImportPath: "nest/m1p", + CommentPath: "", + Name: "m1p", + Imports: []string{ + "github.com/golang/dep/gps", + "os", + "sort", + }, + }, + }, + }, + }, + }, + "malformed go file": { + fileRoot: j("bad"), + importRoot: "bad", + out: PackageTree{ + ImportRoot: "bad", + Packages: map[string]PackageOrErr{ + "bad": { + Err: scanner.ErrorList{ + &scanner.Error{ + Pos: token.Position{ + Filename: j("bad", "bad.go"), + Offset: 273, + Line: 6, + Column: 43, + }, + Msg: "expected 'package', found 'EOF'", + }, + }, + }, + }, + }, + }, + "two nested under empty root": { + fileRoot: j("ren"), + importRoot: "ren", + out: PackageTree{ + ImportRoot: "ren", + Packages: map[string]PackageOrErr{ + "ren": { + Err: &build.NoGoError{ + Dir: j("ren"), + }, + }, + "ren/m1p": { + P: Package{ + ImportPath: "ren/m1p", + CommentPath: "", + Name: "m1p", + Imports: []string{ + "github.com/golang/dep/gps", + "os", + "sort", + }, + }, + }, + "ren/simple": { + P: Package{ + ImportPath: "ren/simple", + CommentPath: "", + Name: "simple", + Imports: []string{ + "github.com/golang/dep/gps", + "sort", + }, + }, + }, + }, + }, + }, + "internal name mismatch": { + fileRoot: j("doublenest"), + importRoot: "doublenest", + out: PackageTree{ + ImportRoot: "doublenest", + Packages: map[string]PackageOrErr{ + "doublenest": { + P: Package{ + ImportPath: "doublenest", + CommentPath: "", + Name: "base", + Imports: []string{ + "github.com/golang/dep/gps", + "go/parser", + }, + }, + }, + "doublenest/namemismatch": { + P: Package{ + ImportPath: "doublenest/namemismatch", + CommentPath: "", + Name: "nm", + Imports: []string{ + "github.com/Masterminds/semver", + "os", + }, + }, + }, + "doublenest/namemismatch/m1p": { + P: Package{ + ImportPath: "doublenest/namemismatch/m1p", + CommentPath: "", + Name: "m1p", + Imports: []string{ + "github.com/golang/dep/gps", + "os", + "sort", + }, + }, + }, + }, + }, + }, + "file and importroot mismatch": { + fileRoot: j("doublenest"), + importRoot: "other", + out: PackageTree{ + ImportRoot: "other", + Packages: map[string]PackageOrErr{ + "other": { + P: Package{ + ImportPath: "other", + CommentPath: "", + Name: "base", + Imports: []string{ + "github.com/golang/dep/gps", + "go/parser", + }, + }, + }, + "other/namemismatch": { + P: Package{ + ImportPath: "other/namemismatch", + CommentPath: "", + Name: "nm", + Imports: []string{ + "github.com/Masterminds/semver", + "os", + }, + }, + }, + "other/namemismatch/m1p": { + P: Package{ + ImportPath: "other/namemismatch/m1p", + CommentPath: "", + Name: "m1p", + Imports: []string{ + "github.com/golang/dep/gps", + "os", + "sort", + }, + }, + }, + }, + }, + }, + "code and ignored main": { + fileRoot: j("igmain"), + importRoot: "simple", + out: PackageTree{ + ImportRoot: "simple", + Packages: map[string]PackageOrErr{ + "simple": { + P: Package{ + ImportPath: "simple", + CommentPath: "", + Name: "simple", + Imports: []string{ + "github.com/golang/dep/gps", + "sort", + "unicode", + }, + }, + }, + }, + }, + }, + "code and ignored main, order check": { + fileRoot: j("igmainfirst"), + importRoot: "simple", + out: PackageTree{ + ImportRoot: "simple", + Packages: map[string]PackageOrErr{ + "simple": { + P: Package{ + ImportPath: "simple", + CommentPath: "", + Name: "simple", + Imports: []string{ + "github.com/golang/dep/gps", + "sort", + "unicode", + }, + }, + }, + }, + }, + }, + "code and ignored main with comment leader": { + fileRoot: j("igmainlong"), + importRoot: "simple", + out: PackageTree{ + ImportRoot: "simple", + Packages: map[string]PackageOrErr{ + "simple": { + P: Package{ + ImportPath: "simple", + CommentPath: "", + Name: "simple", + Imports: []string{ + "github.com/golang/dep/gps", + "sort", + "unicode", + }, + }, + }, + }, + }, + }, + "code, tests, and ignored main": { + fileRoot: j("igmaint"), + importRoot: "simple", + out: PackageTree{ + ImportRoot: "simple", + Packages: map[string]PackageOrErr{ + "simple": { + P: Package{ + ImportPath: "simple", + CommentPath: "", + Name: "simple", + Imports: []string{ + "github.com/golang/dep/gps", + "sort", + "unicode", + }, + TestImports: []string{ + "math/rand", + "strconv", + }, + }, + }, + }, + }, + }, + // imports a missing pkg + "missing import": { + fileRoot: j("missing"), + importRoot: "missing", + out: PackageTree{ + ImportRoot: "missing", + Packages: map[string]PackageOrErr{ + "missing": { + P: Package{ + ImportPath: "missing", + CommentPath: "", + Name: "simple", + Imports: []string{ + "github.com/golang/dep/gps", + "missing/missing", + "sort", + }, + }, + }, + "missing/m1p": { + P: Package{ + ImportPath: "missing/m1p", + CommentPath: "", + Name: "m1p", + Imports: []string{ + "github.com/golang/dep/gps", + "os", + "sort", + }, + }, + }, + }, + }, + }, + // import cycle of three packages. ListPackages doesn't do anything + // special with cycles - that's the reach calculator's job - so this is + // error-free + "import cycle, len 3": { + fileRoot: j("cycle"), + importRoot: "cycle", + out: PackageTree{ + ImportRoot: "cycle", + Packages: map[string]PackageOrErr{ + "cycle": { + P: Package{ + ImportPath: "cycle", + CommentPath: "", + Name: "cycle", + Imports: []string{ + "cycle/one", + "github.com/golang/dep/gps", + }, + }, + }, + "cycle/one": { + P: Package{ + ImportPath: "cycle/one", + CommentPath: "", + Name: "one", + Imports: []string{ + "cycle/two", + "github.com/golang/dep/gps", + }, + }, + }, + "cycle/two": { + P: Package{ + ImportPath: "cycle/two", + CommentPath: "", + Name: "two", + Imports: []string{ + "cycle", + "github.com/golang/dep/gps", + }, + }, + }, + }, + }, + }, + // has disallowed dir names + "disallowed dirs": { + fileRoot: j("disallow"), + importRoot: "disallow", + out: PackageTree{ + ImportRoot: "disallow", + Packages: map[string]PackageOrErr{ + "disallow": { + P: Package{ + ImportPath: "disallow", + CommentPath: "", + Name: "disallow", + Imports: []string{ + "disallow/testdata", + "github.com/golang/dep/gps", + "sort", + }, + }, + }, + "disallow/testdata": { + P: Package{ + ImportPath: "disallow/testdata", + CommentPath: "", + Name: "testdata", + Imports: []string{ + "hash", + }, + }, + }, + }, + }, + }, + "relative imports": { + fileRoot: j("relimport"), + importRoot: "relimport", + out: PackageTree{ + ImportRoot: "relimport", + Packages: map[string]PackageOrErr{ + "relimport": { + P: Package{ + ImportPath: "relimport", + CommentPath: "", + Name: "relimport", + Imports: []string{ + "sort", + }, + }, + }, + "relimport/dot": { + P: Package{ + ImportPath: "relimport/dot", + CommentPath: "", + Name: "dot", + Imports: []string{ + ".", + "sort", + }, + }, + }, + "relimport/dotdot": { + Err: &LocalImportsError{ + Dir: j("relimport/dotdot"), + ImportPath: "relimport/dotdot", + LocalImports: []string{ + "..", + }, + }, + }, + "relimport/dotslash": { + Err: &LocalImportsError{ + Dir: j("relimport/dotslash"), + ImportPath: "relimport/dotslash", + LocalImports: []string{ + "./simple", + }, + }, + }, + "relimport/dotdotslash": { + Err: &LocalImportsError{ + Dir: j("relimport/dotdotslash"), + ImportPath: "relimport/dotdotslash", + LocalImports: []string{ + "../github.com/golang/dep/gps", + }, + }, + }, + }, + }, + }, + "skip underscore": { + fileRoot: j("skip_"), + importRoot: "skip_", + out: PackageTree{ + ImportRoot: "skip_", + Packages: map[string]PackageOrErr{ + "skip_": { + P: Package{ + ImportPath: "skip_", + CommentPath: "", + Name: "skip", + Imports: []string{ + "github.com/golang/dep/gps", + "sort", + }, + }, + }, + }, + }, + }, + // This case mostly exists for the PackageTree methods, but it does + // cover a bit of range + "varied": { + fileRoot: j("varied"), + importRoot: "varied", + out: PackageTree{ + ImportRoot: "varied", + Packages: map[string]PackageOrErr{ + "varied": { + P: Package{ + ImportPath: "varied", + CommentPath: "", + Name: "main", + Imports: []string{ + "net/http", + "varied/namemismatch", + "varied/otherpath", + "varied/simple", + }, + }, + }, + "varied/otherpath": { + P: Package{ + ImportPath: "varied/otherpath", + CommentPath: "", + Name: "otherpath", + Imports: []string{}, + TestImports: []string{ + "varied/m1p", + }, + }, + }, + "varied/simple": { + P: Package{ + ImportPath: "varied/simple", + CommentPath: "", + Name: "simple", + Imports: []string{ + "github.com/golang/dep/gps", + "go/parser", + "varied/simple/another", + }, + }, + }, + "varied/simple/another": { + P: Package{ + ImportPath: "varied/simple/another", + CommentPath: "", + Name: "another", + Imports: []string{ + "hash", + "varied/m1p", + }, + TestImports: []string{ + "encoding/binary", + }, + }, + }, + "varied/namemismatch": { + P: Package{ + ImportPath: "varied/namemismatch", + CommentPath: "", + Name: "nm", + Imports: []string{ + "github.com/Masterminds/semver", + "os", + }, + }, + }, + "varied/m1p": { + P: Package{ + ImportPath: "varied/m1p", + CommentPath: "", + Name: "m1p", + Imports: []string{ + "github.com/golang/dep/gps", + "os", + "sort", + }, + }, + }, + }, + }, + }, + "varied with hidden dirs": { + fileRoot: j("varied_hidden"), + importRoot: "varied", + out: PackageTree{ + ImportRoot: "varied", + Packages: map[string]PackageOrErr{ + "varied": { + P: Package{ + ImportPath: "varied", + CommentPath: "", + Name: "main", + Imports: []string{ + "net/http", + "varied/_frommain", + "varied/simple", + }, + }, + }, + "varied/always": { + P: Package{ + ImportPath: "varied/always", + CommentPath: "", + Name: "always", + Imports: []string{}, + TestImports: []string{ + "varied/.onlyfromtests", + }, + }, + }, + "varied/.onlyfromtests": { + P: Package{ + ImportPath: "varied/.onlyfromtests", + CommentPath: "", + Name: "onlyfromtests", + Imports: []string{ + "github.com/golang/dep/gps", + "os", + "sort", + "varied/_secondorder", + }, + }, + }, + "varied/simple": { + P: Package{ + ImportPath: "varied/simple", + CommentPath: "", + Name: "simple", + Imports: []string{ + "github.com/golang/dep/gps", + "go/parser", + "varied/simple/testdata", + }, + }, + }, + "varied/simple/testdata": { + P: Package{ + ImportPath: "varied/simple/testdata", + CommentPath: "", + Name: "testdata", + Imports: []string{ + "varied/dotdotslash", + }, + }, + }, + "varied/_secondorder": { + P: Package{ + ImportPath: "varied/_secondorder", + CommentPath: "", + Name: "secondorder", + Imports: []string{ + "hash", + }, + }, + }, + "varied/_never": { + P: Package{ + ImportPath: "varied/_never", + CommentPath: "", + Name: "never", + Imports: []string{ + "github.com/golang/dep/gps", + "sort", + }, + }, + }, + "varied/_frommain": { + P: Package{ + ImportPath: "varied/_frommain", + CommentPath: "", + Name: "frommain", + Imports: []string{ + "github.com/golang/dep/gps", + "sort", + }, + }, + }, + "varied/dotdotslash": { + Err: &LocalImportsError{ + Dir: j("varied_hidden/dotdotslash"), + ImportPath: "varied/dotdotslash", + LocalImports: []string{ + "../github.com/golang/dep/gps", + }, + }, + }, + }, + }, + }, + "invalid buildtag like comments should be ignored": { + fileRoot: j("buildtag"), + importRoot: "buildtag", + out: PackageTree{ + ImportRoot: "buildtag", + Packages: map[string]PackageOrErr{ + "buildtag": { + P: Package{ + ImportPath: "buildtag", + CommentPath: "", + Name: "buildtag", + Imports: []string{ + "sort", + }, + }, + }, + }, + }, + }, + "does not skip directories starting with '.'": { + fileRoot: j("dotgodir"), + importRoot: "dotgodir", + out: PackageTree{ + ImportRoot: "dotgodir", + Packages: map[string]PackageOrErr{ + "dotgodir": { + P: Package{ + ImportPath: "dotgodir", + Imports: []string{}, + }, + }, + "dotgodir/.go": { + P: Package{ + ImportPath: "dotgodir/.go", + Name: "dot", + Imports: []string{}, + }, + }, + "dotgodir/foo.go": { + P: Package{ + ImportPath: "dotgodir/foo.go", + Name: "foo", + Imports: []string{"sort"}, + }, + }, + "dotgodir/.m1p": { + P: Package{ + ImportPath: "dotgodir/.m1p", + CommentPath: "", + Name: "m1p", + Imports: []string{ + "github.com/golang/dep/gps", + "os", + "sort", + }, + }, + }, + }, + }, + }, + "canonical": { + fileRoot: j("canonical"), + importRoot: "canonical", + out: PackageTree{ + ImportRoot: "canonical", + Packages: map[string]PackageOrErr{ + "canonical": { + P: Package{ + ImportPath: "canonical", + CommentPath: "canonical", + Name: "pkg", + Imports: []string{}, + }, + }, + "canonical/sub": { + P: Package{ + ImportPath: "canonical/sub", + CommentPath: "canonical/subpackage", + Name: "sub", + Imports: []string{}, + }, + }, + }, + }, + }, + "conflicting canonical comments": { + fileRoot: j("canon_confl"), + importRoot: "canon_confl", + out: PackageTree{ + ImportRoot: "canon_confl", + Packages: map[string]PackageOrErr{ + "canon_confl": { + Err: &ConflictingImportComments{ + ImportPath: "canon_confl", + ConflictingImportComments: []string{ + "vanity1", + "vanity2", + }, + }, + }, + }, + }, + }, + "non-canonical": { + fileRoot: j("canonical"), + importRoot: "noncanonical", + out: PackageTree{ + ImportRoot: "noncanonical", + Packages: map[string]PackageOrErr{ + "noncanonical": { + Err: &NonCanonicalImportRoot{ + ImportRoot: "noncanonical", + Canonical: "canonical", + }, + }, + "noncanonical/sub": { + Err: &NonCanonicalImportRoot{ + ImportRoot: "noncanonical", + Canonical: "canonical/subpackage", + }, + }, + }, + }, + }, + } + + for name, fix := range table { + t.Run(name, func(t *testing.T) { + if _, err := os.Stat(fix.fileRoot); err != nil { + t.Errorf("error on fileRoot %s: %s", fix.fileRoot, err) + } + + out, err := ListPackages(fix.fileRoot, fix.importRoot) + + if err != nil && fix.err == nil { + t.Errorf("Received error but none expected: %s", err) + } else if fix.err != nil && err == nil { + t.Errorf("Error expected but none received") + } else if fix.err != nil && err != nil { + if !reflect.DeepEqual(fix.err, err) { + t.Errorf("Did not receive expected error:\n\t(GOT): %s\n\t(WNT): %s", err, fix.err) + } + } + + if fix.out.ImportRoot != "" && fix.out.Packages != nil { + if !reflect.DeepEqual(out, fix.out) { + if fix.out.ImportRoot != out.ImportRoot { + t.Errorf("Expected ImportRoot %s, got %s", fix.out.ImportRoot, out.ImportRoot) + } + + // overwrite the out one to see if we still have a real problem + out.ImportRoot = fix.out.ImportRoot + + if !reflect.DeepEqual(out, fix.out) { + // TODO (kris-nova) We need to disable this bypass here, and in the .travis.yml + // as soon as dep#501 is fixed + bypass := os.Getenv("DEPTESTBYPASS501") + if bypass != "" { + t.Log("bypassing fix.out.Packages check < 2") + } else { + if len(fix.out.Packages) < 2 { + t.Errorf("Did not get expected PackageOrErrs:\n\t(GOT): %#v\n\t(WNT): %#v", out, fix.out) + } else { + seen := make(map[string]bool) + for path, perr := range fix.out.Packages { + seen[path] = true + if operr, exists := out.Packages[path]; !exists { + t.Errorf("Expected PackageOrErr for path %s was missing from output:\n\t%s", path, perr) + } else { + if !reflect.DeepEqual(perr, operr) { + t.Errorf("PkgOrErr for path %s was not as expected:\n\t(GOT): %#v\n\t(WNT): %#v", path, operr, perr) + } + } + } + + for path, operr := range out.Packages { + if seen[path] { + continue + } + + t.Errorf("Got PackageOrErr for path %s, but none was expected:\n\t%s", path, operr) + } + } + } + } + } + } + }) + } +} + +// Transform Table Test that operates solely on the varied_hidden fixture. +func TestTrimHiddenPackages(t *testing.T) { + base, err := ListPackages(filepath.Join(getTestdataRootDir(t), "src", "varied_hidden"), "varied") + if err != nil { + panic(err) + } + + table := map[string]struct { + main, tests bool // literal params to TrimHiddenPackages + ignore []string // transformed into IgnoredRuleset param to TrimHiddenPackages + trimmed []string // list of packages that should be trimmed in result PackageTree + }{ + // All of these implicitly verify that the varied/_never pkg is always + // trimmed, and that the varied/dotdotslash pkg is not trimmed even + // though it has errors. + "minimal trim": { + main: true, + tests: true, + }, + "ignore simple, lose testdata": { + main: true, + tests: true, + ignore: []string{"simple"}, + trimmed: []string{"simple", "simple/testdata"}, + }, + "no tests": { + main: true, + tests: false, + trimmed: []string{".onlyfromtests", "_secondorder"}, + }, + "ignore a reachable hidden": { + main: true, + tests: true, + ignore: []string{"_secondorder"}, + trimmed: []string{"_secondorder"}, + }, + "ignore a reachable hidden with another hidden solely reachable through it": { + main: true, + tests: true, + ignore: []string{".onlyfromtests"}, + trimmed: []string{".onlyfromtests", "_secondorder"}, + }, + "no main": { + main: false, + tests: true, + trimmed: []string{"", "_frommain"}, + }, + "no main or tests": { + main: false, + tests: false, + trimmed: []string{"", "_frommain", ".onlyfromtests", "_secondorder"}, + }, + "no main or tests and ignore simple": { + main: false, + tests: false, + ignore: []string{"simple"}, + trimmed: []string{"", "_frommain", ".onlyfromtests", "_secondorder", "simple", "simple/testdata"}, + }, + } + + for name, fix := range table { + t.Run(name, func(t *testing.T) { + want := base.Copy() + + var ig []string + for _, v := range fix.ignore { + ig = append(ig, path.Join("varied", v)) + } + got := base.TrimHiddenPackages(fix.main, fix.tests, NewIgnoredRuleset(ig)) + + for _, ip := range append(fix.trimmed, "_never") { + ip = path.Join("varied", ip) + if _, has := want.Packages[ip]; !has { + panic(fmt.Sprintf("bad input, %s does not exist in fixture ptree", ip)) + } + delete(want.Packages, ip) + } + + if !reflect.DeepEqual(want, got) { + if len(want.Packages) < 2 { + t.Errorf("Did not get expected PackageOrErrs:\n\t(GOT): %#v\n\t(WNT): %#v", got, want) + } else { + seen := make(map[string]bool) + for path, perr := range want.Packages { + seen[path] = true + if operr, exists := got.Packages[path]; !exists { + t.Errorf("Expected PackageOrErr for path %s was missing from output:\n\t%s", path, perr) + } else { + if !reflect.DeepEqual(perr, operr) { + t.Errorf("PkgOrErr for path %s was not as expected:\n\t(GOT): %#v\n\t(WNT): %#v", path, operr, perr) + } + } + } + + for path, operr := range got.Packages { + if seen[path] { + continue + } + + t.Errorf("Got PackageOrErr for path %s, but none was expected:\n\t%s", path, operr) + } + } + } + }) + } +} + +// Test that ListPackages skips directories for which it lacks permissions to +// enter and files it lacks permissions to read. +func TestListPackagesNoPerms(t *testing.T) { + if runtime.GOOS == "windows" { + // TODO This test doesn't work on windows because I wasn't able to easily + // figure out how to chmod a dir in a way that made it untraversable. + // + // It's not a big deal, though, because the os.IsPermission() call we + // use in the real code is effectively what's being tested here, and + // that's designed to be cross-platform. So, if the unix tests pass, we + // have every reason to believe windows tests would too, if the situation + // arises. + t.Skip() + } + tmp, err := ioutil.TempDir("", "listpkgsnp") + if err != nil { + t.Fatalf("Failed to create temp dir: %s", err) + } + defer os.RemoveAll(tmp) + + srcdir := filepath.Join(getTestdataRootDir(t), "src", "ren") + workdir := filepath.Join(tmp, "ren") + fs.CopyDir(srcdir, workdir) + + // chmod the simple dir and m1p/b.go file so they can't be read + err = os.Chmod(filepath.Join(workdir, "simple"), 0) + if err != nil { + t.Fatalf("Error while chmodding simple dir: %s", err) + } + os.Chmod(filepath.Join(workdir, "m1p", "b.go"), 0) + if err != nil { + t.Fatalf("Error while chmodding b.go file: %s", err) + } + + want := PackageTree{ + ImportRoot: "ren", + Packages: map[string]PackageOrErr{ + "ren": { + Err: &build.NoGoError{ + Dir: workdir, + }, + }, + "ren/m1p": { + P: Package{ + ImportPath: "ren/m1p", + CommentPath: "", + Name: "m1p", + Imports: []string{ + "github.com/golang/dep/gps", + "sort", + }, + }, + }, + }, + } + + got, err := ListPackages(workdir, "ren") + + if err != nil { + t.Fatalf("Unexpected err from ListPackages: %s", err) + } + if want.ImportRoot != got.ImportRoot { + t.Fatalf("Expected ImportRoot %s, got %s", want.ImportRoot, got.ImportRoot) + } + + if !reflect.DeepEqual(got, want) { + t.Errorf("Did not get expected PackageOrErrs:\n\t(GOT): %#v\n\t(WNT): %#v", got, want) + if len(got.Packages) != 2 { + if len(got.Packages) == 3 { + t.Error("Wrong number of PackageOrErrs - did 'simple' subpackage make it into results somehow?") + } else { + t.Error("Wrong number of PackageOrErrs") + } + } + + if got.Packages["ren"].Err == nil { + t.Error("Should have gotten error on empty root directory") + } + + if !reflect.DeepEqual(got.Packages["ren/m1p"].P.Imports, want.Packages["ren/m1p"].P.Imports) { + t.Error("Mismatch between imports in m1p") + } + } +} + +func TestToReachMap(t *testing.T) { + // There's enough in the 'varied' test case to test most of what matters + vptree, err := ListPackages(filepath.Join(getTestdataRootDir(t), "src", "github.com", "example", "varied"), "github.com/example/varied") + if err != nil { + t.Fatalf("ListPackages failed on varied test case: %s", err) + } + + // Helper to add github.com/varied/example prefix + b := func(s string) string { + if s == "" { + return "github.com/example/varied" + } + return "github.com/example/varied/" + s + } + bl := func(parts ...string) string { + for k, s := range parts { + parts[k] = b(s) + } + return strings.Join(parts, " ") + } + + // Set up vars for validate closure + var want ReachMap + var name string + var main, tests bool + var ignore []string + + validate := func() { + got, em := vptree.ToReachMap(main, tests, true, NewIgnoredRuleset(ignore)) + if len(em) != 0 { + t.Errorf("Should not have any error packages from ToReachMap, got %s", em) + } + if !reflect.DeepEqual(want, got) { + seen := make(map[string]bool) + for ip, wantie := range want { + seen[ip] = true + if gotie, exists := got[ip]; !exists { + t.Errorf("ver(%q): expected import path %s was not present in result", name, ip) + } else { + if !reflect.DeepEqual(wantie, gotie) { + t.Errorf("ver(%q): did not get expected import set for pkg %s:\n\t(GOT): %#v\n\t(WNT): %#v", name, ip, gotie, wantie) + } + } + } + + for ip, ie := range got { + if seen[ip] { + continue + } + t.Errorf("ver(%q): Got packages for import path %s, but none were expected:\n\t%s", name, ip, ie) + } + } + } + + // maps of each internal package, and their expected external and internal + // imports in the maximal case. + allex := map[string][]string{ + b(""): {"encoding/binary", "github.com/Masterminds/semver", "github.com/golang/dep/gps", "go/parser", "hash", "net/http", "os", "sort"}, + b("m1p"): {"github.com/golang/dep/gps", "os", "sort"}, + b("namemismatch"): {"github.com/Masterminds/semver", "os"}, + b("otherpath"): {"github.com/golang/dep/gps", "os", "sort"}, + b("simple"): {"encoding/binary", "github.com/golang/dep/gps", "go/parser", "hash", "os", "sort"}, + b("simple/another"): {"encoding/binary", "github.com/golang/dep/gps", "hash", "os", "sort"}, + } + + allin := map[string][]string{ + b(""): {b("m1p"), b("namemismatch"), b("otherpath"), b("simple"), b("simple/another")}, + b("m1p"): {}, + b("namemismatch"): {}, + b("otherpath"): {b("m1p")}, + b("simple"): {b("m1p"), b("simple/another")}, + b("simple/another"): {b("m1p")}, + } + + // build a map to validate the exception inputs. do this because shit is + // hard enough to keep track of that it's preferable not to have silent + // success if a typo creeps in and we're trying to except an import that + // isn't in a pkg in the first place + valid := make(map[string]map[string]bool) + for ip, expkgs := range allex { + m := make(map[string]bool) + for _, pkg := range expkgs { + m[pkg] = true + } + valid[ip] = m + } + validin := make(map[string]map[string]bool) + for ip, inpkgs := range allin { + m := make(map[string]bool) + for _, pkg := range inpkgs { + m[pkg] = true + } + validin[ip] = m + } + + // helper to compose want, excepting specific packages + // + // this makes it easier to see what we're taking out on each test + except := func(pkgig ...string) { + // reinit expect with everything from all + want = make(ReachMap) + for ip, expkgs := range allex { + var ie struct{ Internal, External []string } + + inpkgs := allin[ip] + lenex, lenin := len(expkgs), len(inpkgs) + if lenex > 0 { + ie.External = make([]string, len(expkgs)) + copy(ie.External, expkgs) + } + + if lenin > 0 { + ie.Internal = make([]string, len(inpkgs)) + copy(ie.Internal, inpkgs) + } + + want[ip] = ie + } + + // now build the dropmap + drop := make(map[string]map[string]bool) + for _, igstr := range pkgig { + // split on space; first elem is import path to pkg, the rest are + // the imports to drop. + not := strings.Split(igstr, " ") + var ip string + ip, not = not[0], not[1:] + if _, exists := valid[ip]; !exists { + t.Fatalf("%s is not a package name we're working with, doofus", ip) + } + + // if only a single elem was passed, though, drop the whole thing + if len(not) == 0 { + delete(want, ip) + continue + } + + m := make(map[string]bool) + for _, imp := range not { + if strings.HasPrefix(imp, "github.com/example/varied") { + if !validin[ip][imp] { + t.Fatalf("%s is not a reachable import of %s, even in the all case", imp, ip) + } + } else { + if !valid[ip][imp] { + t.Fatalf("%s is not a reachable import of %s, even in the all case", imp, ip) + } + } + m[imp] = true + } + + drop[ip] = m + } + + for ip, ie := range want { + var nie struct{ Internal, External []string } + for _, imp := range ie.Internal { + if !drop[ip][imp] { + nie.Internal = append(nie.Internal, imp) + } + } + + for _, imp := range ie.External { + if !drop[ip][imp] { + nie.External = append(nie.External, imp) + } + } + + want[ip] = nie + } + } + + /* PREP IS DONE, BEGIN ACTUAL TESTING */ + + // first, validate all + name = "all" + main, tests = true, true + except() + validate() + + // turn off main pkgs, which necessarily doesn't affect anything else + name = "no main" + main = false + except(b("")) + validate() + + // ignoring the "varied" pkg has same effect as disabling main pkgs + name = "ignore root" + ignore = []string{b("")} + main = true + validate() + + // when we drop tests, varied/otherpath loses its link to varied/m1p and + // varied/simple/another loses its test import, which has a fairly big + // cascade + name = "no tests" + tests = false + ignore = nil + except( + b("")+" encoding/binary", + b("simple")+" encoding/binary", + b("simple/another")+" encoding/binary", + b("otherpath")+" github.com/golang/dep/gps os sort", + ) + + // almost the same as previous, but varied just goes away completely + name = "no main or tests" + main = false + except( + b(""), + b("simple")+" encoding/binary", + b("simple/another")+" encoding/binary", + bl("otherpath", "m1p")+" github.com/golang/dep/gps os sort", + ) + validate() + + // focus on ignores now, so reset main and tests + main, tests = true, true + + // now, the fun stuff. punch a hole in the middle by cutting out + // varied/simple + name = "ignore varied/simple" + ignore = []string{b("simple")} + except( + // root pkg loses on everything in varied/simple/another + // FIXME this is a bit odd, but should probably exclude m1p as well, + // because it actually shouldn't be valid to import a package that only + // has tests. This whole model misses that nuance right now, though. + bl("", "simple", "simple/another")+" hash encoding/binary go/parser", + b("simple"), + ) + validate() + + // widen the hole by excluding otherpath + name = "ignore varied/{otherpath,simple}" + ignore = []string{ + b("otherpath"), + b("simple"), + } + except( + // root pkg loses on everything in varied/simple/another and varied/m1p + bl("", "simple", "simple/another", "m1p", "otherpath")+" hash encoding/binary go/parser github.com/golang/dep/gps sort", + b("otherpath"), + b("simple"), + ) + validate() + + // remove namemismatch, though we're mostly beating a dead horse now + name = "ignore varied/{otherpath,simple,namemismatch}" + ignore = append(ignore, b("namemismatch")) + except( + // root pkg loses on everything in varied/simple/another and varied/m1p + bl("", "simple", "simple/another", "m1p", "otherpath", "namemismatch")+" hash encoding/binary go/parser github.com/golang/dep/gps sort os github.com/Masterminds/semver", + b("otherpath"), + b("simple"), + b("namemismatch"), + ) + validate() +} + +func TestFlattenReachMap(t *testing.T) { + // There's enough in the 'varied' test case to test most of what matters + vptree, err := ListPackages(filepath.Join(getTestdataRootDir(t), "src", "github.com", "example", "varied"), "github.com/example/varied") + if err != nil { + t.Fatalf("listPackages failed on varied test case: %s", err) + } + + all := []string{ + "encoding/binary", + "github.com/Masterminds/semver", + "github.com/golang/dep/gps", + "go/parser", + "hash", + "net/http", + "os", + "sort", + } + + // helper to generate testCase.expect as: all, except for a couple packages + // + // this makes it easier to see what we're taking out on each test + except := func(not ...string) []string { + expect := make([]string, len(all)-len(not)) + + drop := make(map[string]bool) + for _, npath := range not { + drop[npath] = true + } + + k := 0 + for _, path := range all { + if !drop[path] { + expect[k] = path + k++ + } + } + return expect + } + + for _, testCase := range []*flattenReachMapCase{ + // everything on + { + name: "simple", + expect: except(), + isStdLibFn: nil, + main: true, + tests: true, + }, + // no stdlib + { + name: "no stdlib", + expect: except("encoding/binary", "go/parser", "hash", "net/http", "os", "sort"), + isStdLibFn: paths.IsStandardImportPath, + main: true, + tests: true, + }, + // stdlib back in; now exclude tests, which should just cut one + { + name: "no tests", + expect: except("encoding/binary"), + isStdLibFn: nil, + main: true, + tests: false, + }, + // Now skip main, which still just cuts out one + { + name: "no main", + expect: except("net/http"), + isStdLibFn: nil, + main: false, + tests: true, + }, + // No test and no main, which should be additive + { + name: "no tests, no main", + expect: except("net/http", "encoding/binary"), + isStdLibFn: nil, + main: false, + tests: false, + }, + // now, the ignore tests. turn main and tests back on + // start with non-matching + { + name: "non-matching ignore", + expect: except(), + isStdLibFn: nil, + main: true, + tests: true, + ignore: NewIgnoredRuleset([]string{ + "nomatch", + }), + }, + // should have the same effect as ignoring main + { + name: "ignore the root", + expect: except("net/http"), + isStdLibFn: nil, + main: true, + tests: true, + ignore: NewIgnoredRuleset([]string{ + "github.com/example/varied", + }), + }, + // now drop a more interesting one + // we get github.com/golang/dep/gps from m1p, too, so it should still be there + { + name: "ignore simple", + expect: except("go/parser"), + isStdLibFn: nil, + main: true, + tests: true, + ignore: NewIgnoredRuleset([]string{ + "github.com/example/varied/simple", + }), + }, + // now drop two + { + name: "ignore simple and nameismatch", + expect: except("go/parser", "github.com/Masterminds/semver"), + isStdLibFn: nil, + main: true, + tests: true, + ignore: NewIgnoredRuleset([]string{ + "github.com/example/varied/simple", + "github.com/example/varied/namemismatch", + }), + }, + // make sure tests and main play nice with ignore + { + name: "ignore simple and nameismatch, and no tests", + expect: except("go/parser", "github.com/Masterminds/semver", "encoding/binary"), + isStdLibFn: nil, + main: true, + tests: false, + ignore: NewIgnoredRuleset([]string{ + "github.com/example/varied/simple", + "github.com/example/varied/namemismatch", + }), + }, + { + name: "ignore simple and namemismatch, and no main", + expect: except("go/parser", "github.com/Masterminds/semver", "net/http"), + isStdLibFn: nil, + main: false, + tests: true, + ignore: NewIgnoredRuleset([]string{ + "github.com/example/varied/simple", + "github.com/example/varied/namemismatch", + }), + }, + { + name: "ignore simple and namemismatch, and no main or tests", + expect: except("go/parser", "github.com/Masterminds/semver", "net/http", "encoding/binary"), + isStdLibFn: nil, + main: false, + tests: false, + ignore: NewIgnoredRuleset([]string{ + "github.com/example/varied/simple", + "github.com/example/varied/namemismatch", + }), + }, + // ignore two that should knock out gps + { + name: "ignore both importers", + expect: except("sort", "github.com/golang/dep/gps", "go/parser"), + isStdLibFn: nil, + main: true, + tests: true, + ignore: NewIgnoredRuleset([]string{ + "github.com/example/varied/simple", + "github.com/example/varied/m1p", + }), + }, + // finally, directly ignore some external packages + { + name: "ignore external", + expect: except("sort", "github.com/golang/dep/gps", "go/parser"), + isStdLibFn: nil, + main: true, + tests: true, + ignore: NewIgnoredRuleset([]string{ + "github.com/golang/dep/gps", + "go/parser", + "sort", + }), + }, + } { + t.Run(testCase.name, testFlattenReachMap(&vptree, testCase)) + } + + // The only thing varied *doesn't* cover is disallowed path patterns + ptree, err := ListPackages(filepath.Join(getTestdataRootDir(t), "src", "disallow"), "disallow") + if err != nil { + t.Fatalf("ListPackages failed on disallow test case: %s", err) + } + + t.Run("disallowed", testFlattenReachMap(&ptree, &flattenReachMapCase{ + name: "disallowed", + expect: []string{"github.com/golang/dep/gps", "hash", "sort"}, + isStdLibFn: nil, + main: false, + tests: false, + })) +} + +type flattenReachMapCase struct { + expect []string + name string + ignore *IgnoredRuleset + main, tests bool + isStdLibFn func(string) bool +} + +func testFlattenReachMap(ptree *PackageTree, testCase *flattenReachMapCase) func(*testing.T) { + return func(t *testing.T) { + t.Parallel() + rm, em := ptree.ToReachMap(testCase.main, testCase.tests, true, testCase.ignore) + if len(em) != 0 { + t.Errorf("Should not have any error pkgs from ToReachMap, got %s", em) + } + result := rm.FlattenFn(testCase.isStdLibFn) + if !reflect.DeepEqual(testCase.expect, result) { + t.Errorf("Wrong imports in %q case:\n\t(GOT): %s\n\t(WNT): %s", testCase.name, result, testCase.expect) + } + } +} + +// Verify that we handle import cycles correctly - drop em all +func TestToReachMapCycle(t *testing.T) { + ptree, err := ListPackages(filepath.Join(getTestdataRootDir(t), "src", "cycle"), "cycle") + if err != nil { + t.Fatalf("ListPackages failed on cycle test case: %s", err) + } + + rm, em := ptree.ToReachMap(true, true, false, nil) + if len(em) != 0 { + t.Errorf("Should not have any error packages from ToReachMap, got %s", em) + } + + // FIXME TEMPORARILY COMMENTED UNTIL WE CREATE A BETTER LISTPACKAGES MODEL - + //if len(rm) > 0 { + //t.Errorf("should be empty reachmap when all packages are in a cycle, got %v", rm) + //} + + if len(rm) == 0 { + t.Error("TEMPORARY: should ignore import cycles, but cycle was eliminated") + } +} + +func TestToReachMapFilterDot(t *testing.T) { + ptree, err := ListPackages(filepath.Join(getTestdataRootDir(t), "src", "relimport"), "relimport") + if err != nil { + t.Fatalf("ListPackages failed on relimport test case: %s", err) + } + + rm, _ := ptree.ToReachMap(true, true, false, nil) + if _, has := rm["relimport/dot"]; !has { + t.Fatal("relimport/dot should not have had errors") + } + + imports := dedupeStrings(rm["relimport/dot"].External, rm["relimport/dot"].Internal) + for _, imp := range imports { + if imp == "." { + t.Fatal("dot import should have been filtered by ToReachMap") + } + } +} + +func getTestdataRootDir(t *testing.T) string { + cwd, err := os.Getwd() + if err != nil { + t.Fatal(err) + } + return filepath.Join(cwd, "..", "_testdata") +} + +// Canary regression test to make sure that if PackageTree ever gains new +// fields, we update the Copy method accordingly. +func TestCanaryPackageTreeCopy(t *testing.T) { + ptreeFields := []string{ + "ImportRoot", + "Packages", + } + packageFields := []string{ + "Name", + "ImportPath", + "CommentPath", + "Imports", + "TestImports", + } + + fieldNames := func(typ reflect.Type) []string { + var names []string + for i := 0; i < typ.NumField(); i++ { + names = append(names, typ.Field(i).Name) + } + return names + } + + ptreeRefl := fieldNames(reflect.TypeOf(PackageTree{})) + packageRefl := fieldNames(reflect.TypeOf(Package{})) + + if !reflect.DeepEqual(ptreeFields, ptreeRefl) { + t.Errorf("PackageTree.Copy is designed to work with an exact set of fields in the PackageTree struct - make sure it (and this test) have been updated!\n\t(GOT):%s\n\t(WNT):%s", ptreeFields, ptreeRefl) + } + + if !reflect.DeepEqual(packageFields, packageRefl) { + t.Errorf("PackageTree.Copy is designed to work with an exact set of fields in the Package struct - make sure it (and this test) have been updated!\n\t(GOT):%s\n\t(WNT):%s", packageFields, packageRefl) + } +} diff --git a/vendor/github.com/golang/dep/gps/pkgtree/reachmap.go b/vendor/github.com/golang/dep/gps/pkgtree/reachmap.go new file mode 100644 index 00000000..27af5e90 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/pkgtree/reachmap.go @@ -0,0 +1,65 @@ +// Copyright 2017 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 pkgtree + +import ( + "sort" + "strings" +) + +// ReachMap maps a set of import paths (keys) to the sets of transitively +// reachable tree-internal packages, and all the tree-external packages +// reachable through those internal packages. +// +// See PackageTree.ToReachMap() for more information. +type ReachMap map[string]struct { + Internal, External []string +} + +// Eliminate import paths with any elements having leading dots, leading +// underscores, or testdata. If these are internally reachable (which is +// a no-no, but possible), any external imports will have already been +// pulled up through ExternalReach. The key here is that we don't want +// to treat such packages as themselves being sources. +func pkgFilter(pkg string) bool { + for _, elem := range strings.Split(pkg, "/") { + if strings.HasPrefix(elem, ".") || strings.HasPrefix(elem, "_") || elem == "testdata" { + return false + } + } + return true +} + +// FlattenFn flattens a reachmap into a sorted, deduplicated list of all the +// external imports named by its contained packages, but excludes imports coming +// from packages with disallowed patterns in their names: any path element with +// a leading dot, a leading underscore, with the name "testdata". +// +// Imports for which exclude returns true will be left out. +func (rm ReachMap) FlattenFn(exclude func(string) bool) []string { + exm := make(map[string]struct{}) + for pkg, ie := range rm { + if pkgFilter(pkg) { + for _, ex := range ie.External { + if exclude != nil && exclude(ex) { + continue + } + exm[ex] = struct{}{} + } + } + } + + if len(exm) == 0 { + return []string{} + } + + ex := make([]string, 0, len(exm)) + for p := range exm { + ex = append(ex, p) + } + + sort.Strings(ex) + return ex +} diff --git a/vendor/github.com/golang/dep/gps/prune.go b/vendor/github.com/golang/dep/gps/prune.go new file mode 100644 index 00000000..aa8671c4 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/prune.go @@ -0,0 +1,382 @@ +// Copyright 2017 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 gps + +import ( + "log" + "os" + "path/filepath" + "sort" + "strings" + + "github.com/golang/dep/internal/fs" + "github.com/pkg/errors" +) + +// PruneOptions represents the pruning options used to write the dependecy tree. +type PruneOptions uint8 + +const ( + // PruneNestedVendorDirs indicates if nested vendor directories should be pruned. + PruneNestedVendorDirs PruneOptions = 1 << iota + // PruneUnusedPackages indicates if unused Go packages should be pruned. + PruneUnusedPackages + // PruneNonGoFiles indicates if non-Go files should be pruned. + // Files matching licenseFilePrefixes and legalFileSubstrings are kept in + // an attempt to comply with legal requirements. + PruneNonGoFiles + // PruneGoTestFiles indicates if Go test files should be pruned. + PruneGoTestFiles +) + +// PruneOptionSet represents trinary distinctions for each of the types of +// prune rules (as expressed via PruneOptions): nested vendor directories, +// unused packages, non-go files, and go test files. +// +// The three-way distinction is between "none", "true", and "false", represented +// by uint8 values of 0, 1, and 2, respectively. +// +// This trinary distinction is necessary in order to record, with full fidelity, +// a cascading tree of pruning values, as expressed in CascadingPruneOptions; a +// simple boolean cannot delineate between "false" and "none". +type PruneOptionSet struct { + NestedVendor uint8 + UnusedPackages uint8 + NonGoFiles uint8 + GoTests uint8 +} + +// CascadingPruneOptions is a set of rules for pruning a dependency tree. +// +// The DefaultOptions are the global default pruning rules, expressed as a +// single PruneOptions bitfield. These global rules will cascade down to +// individual project rules, unless superseded. +type CascadingPruneOptions struct { + DefaultOptions PruneOptions + PerProjectOptions map[ProjectRoot]PruneOptionSet +} + +// PruneOptionsFor returns the PruneOptions bits for the given project, +// indicating which pruning rules should be applied to the project's code. +// +// It computes the cascade from default to project-specific options (if any) on +// the fly. +func (o CascadingPruneOptions) PruneOptionsFor(pr ProjectRoot) PruneOptions { + po, has := o.PerProjectOptions[pr] + if !has { + return o.DefaultOptions + } + + ops := o.DefaultOptions + if po.NestedVendor != 0 { + if po.NestedVendor == 1 { + ops |= PruneNestedVendorDirs + } else { + ops &^= PruneNestedVendorDirs + } + } + + if po.UnusedPackages != 0 { + if po.UnusedPackages == 1 { + ops |= PruneUnusedPackages + } else { + ops &^= PruneUnusedPackages + } + } + + if po.NonGoFiles != 0 { + if po.NonGoFiles == 1 { + ops |= PruneNonGoFiles + } else { + ops &^= PruneNonGoFiles + } + } + + if po.GoTests != 0 { + if po.GoTests == 1 { + ops |= PruneGoTestFiles + } else { + ops &^= PruneGoTestFiles + } + } + + return ops +} + +func defaultCascadingPruneOptions() CascadingPruneOptions { + return CascadingPruneOptions{ + DefaultOptions: PruneNestedVendorDirs, + PerProjectOptions: map[ProjectRoot]PruneOptionSet{}, + } +} + +var ( + // licenseFilePrefixes is a list of name prefixes for license files. + licenseFilePrefixes = []string{ + "license", + "licence", + "copying", + "unlicense", + "copyright", + "copyleft", + } + // legalFileSubstrings contains substrings that are likey part of a legal + // declaration file. + legalFileSubstrings = []string{ + "authors", + "contributors", + "legal", + "notice", + "disclaimer", + "patent", + "third-party", + "thirdparty", + } +) + +// PruneProject remove excess files according to the options passed, from +// the lp directory in baseDir. +func PruneProject(baseDir string, lp LockedProject, options PruneOptions, logger *log.Logger) error { + fsState, err := deriveFilesystemState(baseDir) + + if err != nil { + return errors.Wrap(err, "could not derive filesystem state") + } + + if (options & PruneNestedVendorDirs) != 0 { + if err := pruneVendorDirs(fsState); err != nil { + return errors.Wrapf(err, "failed to prune nested vendor directories") + } + } + + if (options & PruneUnusedPackages) != 0 { + if _, err := pruneUnusedPackages(lp, fsState); err != nil { + return errors.Wrap(err, "failed to prune unused packages") + } + } + + if (options & PruneNonGoFiles) != 0 { + if err := pruneNonGoFiles(fsState); err != nil { + return errors.Wrap(err, "failed to prune non-Go files") + } + } + + if (options & PruneGoTestFiles) != 0 { + if err := pruneGoTestFiles(fsState); err != nil { + return errors.Wrap(err, "failed to prune Go test files") + } + } + + if err := deleteEmptyDirs(fsState); err != nil { + return errors.Wrap(err, "could not delete empty dirs") + } + + return nil +} + +// pruneVendorDirs deletes all nested vendor directories within baseDir. +func pruneVendorDirs(fsState filesystemState) error { + for _, dir := range fsState.dirs { + if filepath.Base(dir) == "vendor" { + err := os.RemoveAll(filepath.Join(fsState.root, dir)) + if err != nil && !os.IsNotExist(err) { + return err + } + } + } + + for _, link := range fsState.links { + if filepath.Base(link.path) == "vendor" { + err := os.Remove(filepath.Join(fsState.root, link.path)) + if err != nil && !os.IsNotExist(err) { + return err + } + } + } + + return nil +} + +// pruneUnusedPackages deletes unimported packages found in fsState. +// Determining whether packages are imported or not is based on the passed LockedProject. +func pruneUnusedPackages(lp LockedProject, fsState filesystemState) (map[string]interface{}, error) { + unusedPackages := calculateUnusedPackages(lp, fsState) + toDelete := collectUnusedPackagesFiles(fsState, unusedPackages) + + for _, path := range toDelete { + if err := os.Remove(path); err != nil && !os.IsNotExist(err) { + return nil, err + } + } + + return unusedPackages, nil +} + +// calculateUnusedPackages generates a list of unused packages in lp. +func calculateUnusedPackages(lp LockedProject, fsState filesystemState) map[string]interface{} { + unused := make(map[string]interface{}) + imported := make(map[string]interface{}) + + for _, pkg := range lp.Packages() { + imported[pkg] = nil + } + + // Add the root package if it's not imported. + if _, ok := imported["."]; !ok { + unused["."] = nil + } + + for _, dirPath := range fsState.dirs { + pkg := filepath.ToSlash(dirPath) + + if _, ok := imported[pkg]; !ok { + unused[pkg] = nil + } + } + + return unused +} + +// collectUnusedPackagesFiles returns a slice of all files in the unused +// packages based on fsState. +func collectUnusedPackagesFiles(fsState filesystemState, unusedPackages map[string]interface{}) []string { + // TODO(ibrasho): is this useful? + files := make([]string, 0, len(unusedPackages)) + + for _, path := range fsState.files { + // Keep perserved files. + if isPreservedFile(filepath.Base(path)) { + continue + } + + pkg := filepath.ToSlash(filepath.Dir(path)) + + if _, ok := unusedPackages[pkg]; ok { + files = append(files, filepath.Join(fsState.root, path)) + } + } + + return files +} + +// pruneNonGoFiles delete all non-Go files existing in fsState. +// +// Files matching licenseFilePrefixes and legalFileSubstrings are not pruned. +func pruneNonGoFiles(fsState filesystemState) error { + toDelete := make([]string, 0, len(fsState.files)/4) + + for _, path := range fsState.files { + ext := fileExt(path) + + // Refer to: https://github.com/golang/go/blob/release-branch.go1.9/src/go/build/build.go#L750 + switch ext { + case ".go": + continue + case ".c": + continue + case ".cc", ".cpp", ".cxx": + continue + case ".m": + continue + case ".h", ".hh", ".hpp", ".hxx": + continue + case ".f", ".F", ".for", ".f90": + continue + case ".s": + continue + case ".S": + continue + case ".swig": + continue + case ".swigcxx": + continue + case ".syso": + continue + } + + // Ignore perserved files. + if isPreservedFile(filepath.Base(path)) { + continue + } + + toDelete = append(toDelete, filepath.Join(fsState.root, path)) + } + + for _, path := range toDelete { + if err := os.Remove(path); err != nil && !os.IsNotExist(err) { + return err + } + } + + return nil +} + +// isPreservedFile checks if the file name indicates that the file should be +// preserved based on licenseFilePrefixes or legalFileSubstrings. +func isPreservedFile(name string) bool { + name = strings.ToLower(name) + + for _, prefix := range licenseFilePrefixes { + if strings.HasPrefix(name, prefix) { + return true + } + } + + for _, substring := range legalFileSubstrings { + if strings.Contains(name, substring) { + return true + } + } + + return false +} + +// pruneGoTestFiles deletes all Go test files (*_test.go) in fsState. +func pruneGoTestFiles(fsState filesystemState) error { + toDelete := make([]string, 0, len(fsState.files)/2) + + for _, path := range fsState.files { + if strings.HasSuffix(path, "_test.go") { + toDelete = append(toDelete, filepath.Join(fsState.root, path)) + } + } + + for _, path := range toDelete { + if err := os.Remove(path); err != nil && !os.IsNotExist(err) { + return err + } + } + + return nil +} + +func deleteEmptyDirs(fsState filesystemState) error { + sort.Sort(sort.Reverse(sort.StringSlice(fsState.dirs))) + + for _, dir := range fsState.dirs { + path := filepath.Join(fsState.root, dir) + + notEmpty, err := fs.IsNonEmptyDir(path) + if err != nil { + return err + } + + if !notEmpty { + if err := os.Remove(path); err != nil && !os.IsNotExist(err) { + return err + } + } + } + + return nil +} + +func fileExt(name string) string { + i := strings.LastIndex(name, ".") + if i < 0 { + return "" + } + return name[i:] +} diff --git a/vendor/github.com/golang/dep/gps/prune_test.go b/vendor/github.com/golang/dep/gps/prune_test.go new file mode 100644 index 00000000..0d202a8c --- /dev/null +++ b/vendor/github.com/golang/dep/gps/prune_test.go @@ -0,0 +1,790 @@ +// Copyright 2017 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 gps + +import ( + "io/ioutil" + "log" + "os" + "testing" + + "github.com/golang/dep/internal/test" +) + +func TestCascadingPruneOptions(t *testing.T) { + cases := []struct { + name string + co CascadingPruneOptions + results map[ProjectRoot]PruneOptions + }{ + { + name: "all empty values", + co: CascadingPruneOptions{ + DefaultOptions: PruneNestedVendorDirs, + PerProjectOptions: map[ProjectRoot]PruneOptionSet{ + ProjectRoot("github.com/golang/dep"): {}, + }, + }, + results: map[ProjectRoot]PruneOptions{ + ProjectRoot("github.com/golang/dep"): PruneNestedVendorDirs, + }, + }, + { + name: "all overriden", + co: CascadingPruneOptions{ + DefaultOptions: PruneNestedVendorDirs, + PerProjectOptions: map[ProjectRoot]PruneOptionSet{ + ProjectRoot("github.com/golang/dep"): { + NestedVendor: 2, + UnusedPackages: 1, + NonGoFiles: 1, + GoTests: 1, + }, + }, + }, + results: map[ProjectRoot]PruneOptions{ + ProjectRoot("github.com/golang/dep"): PruneUnusedPackages | PruneNonGoFiles | PruneGoTestFiles, + }, + }, + { + name: "all redundant", + co: CascadingPruneOptions{ + DefaultOptions: PruneNestedVendorDirs, + PerProjectOptions: map[ProjectRoot]PruneOptionSet{ + ProjectRoot("github.com/golang/dep"): { + NestedVendor: 1, + UnusedPackages: 2, + NonGoFiles: 2, + GoTests: 2, + }, + }, + }, + results: map[ProjectRoot]PruneOptions{ + ProjectRoot("github.com/golang/dep"): PruneNestedVendorDirs, + }, + }, + { + name: "multiple projects, all combos", + co: CascadingPruneOptions{ + DefaultOptions: PruneNestedVendorDirs, + PerProjectOptions: map[ProjectRoot]PruneOptionSet{ + ProjectRoot("github.com/golang/dep"): { + NestedVendor: 1, + UnusedPackages: 2, + NonGoFiles: 2, + GoTests: 2, + }, + ProjectRoot("github.com/other/one"): { + NestedVendor: 2, + UnusedPackages: 1, + NonGoFiles: 1, + GoTests: 1, + }, + }, + }, + results: map[ProjectRoot]PruneOptions{ + ProjectRoot("github.com/golang/dep"): PruneNestedVendorDirs, + ProjectRoot("github.com/other/one"): PruneUnusedPackages | PruneNonGoFiles | PruneGoTestFiles, + ProjectRoot("not/there"): PruneNestedVendorDirs, + }, + }, + } + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + for pr, wanted := range c.results { + if c.co.PruneOptionsFor(pr) != wanted { + t.Fatalf("did not get expected final PruneOptions value from cascade:\n\t(GOT): %d\n\t(WNT): %d", c.co.PruneOptionsFor(pr), wanted) + } + + } + }) + } +} + +func TestPruneProject(t *testing.T) { + h := test.NewHelper(t) + defer h.Cleanup() + + pr := "github.com/project/repository" + h.TempDir(pr) + + baseDir := h.Path(".") + lp := LockedProject{ + pi: ProjectIdentifier{ + ProjectRoot: ProjectRoot(pr), + }, + pkgs: []string{}, + } + + options := PruneNestedVendorDirs | PruneNonGoFiles | PruneGoTestFiles | PruneUnusedPackages + logger := log.New(ioutil.Discard, "", 0) + + err := PruneProject(baseDir, lp, options, logger) + if err != nil { + t.Fatal(err) + } +} + +func TestPruneUnusedPackages(t *testing.T) { + h := test.NewHelper(t) + defer h.Cleanup() + + h.TempDir(".") + + pr := "github.com/sample/repository" + pi := ProjectIdentifier{ProjectRoot: ProjectRoot(pr)} + + testcases := []struct { + name string + lp LockedProject + fs fsTestCase + err bool + }{ + { + "one-package", + LockedProject{ + pi: pi, + pkgs: []string{ + ".", + }, + }, + fsTestCase{ + before: filesystemState{ + files: []string{ + "main.go", + }, + }, + after: filesystemState{ + files: []string{ + "main.go", + }, + }, + }, + false, + }, + { + "nested-package", + LockedProject{ + pi: pi, + pkgs: []string{ + "pkg", + }, + }, + fsTestCase{ + before: filesystemState{ + dirs: []string{ + "pkg", + }, + files: []string{ + "main.go", + "pkg/main.go", + }, + }, + after: filesystemState{ + dirs: []string{ + "pkg", + }, + files: []string{ + "pkg/main.go", + }, + }, + }, + false, + }, + { + "complex-project", + LockedProject{ + pi: pi, + pkgs: []string{ + "pkg", + "pkg/nestedpkg/otherpkg", + }, + }, + fsTestCase{ + before: filesystemState{ + dirs: []string{ + "pkg", + "pkg/nestedpkg", + "pkg/nestedpkg/otherpkg", + }, + files: []string{ + "main.go", + "COPYING", + "pkg/main.go", + "pkg/nestedpkg/main.go", + "pkg/nestedpkg/PATENT.md", + "pkg/nestedpkg/otherpkg/main.go", + }, + }, + after: filesystemState{ + dirs: []string{ + "pkg", + "pkg/nestedpkg", + "pkg/nestedpkg/otherpkg", + }, + files: []string{ + "COPYING", + "pkg/main.go", + "pkg/nestedpkg/PATENT.md", + "pkg/nestedpkg/otherpkg/main.go", + }, + }, + }, + false, + }, + } + + for _, tc := range testcases { + t.Run(tc.name, func(t *testing.T) { + h.TempDir(pr) + baseDir := h.Path(pr) + tc.fs.before.root = baseDir + tc.fs.after.root = baseDir + tc.fs.setup(t) + + fs, err := deriveFilesystemState(baseDir) + if err != nil { + t.Fatal(err) + } + + _, err = pruneUnusedPackages(tc.lp, fs) + if tc.err && err == nil { + t.Fatalf("expected an error, got nil") + } else if !tc.err && err != nil { + t.Fatalf("unexpected error: %s", err) + } + + tc.fs.assert(t) + }) + } +} + +func TestPruneNonGoFiles(t *testing.T) { + h := test.NewHelper(t) + defer h.Cleanup() + + h.TempDir(".") + + testcases := []struct { + name string + fs fsTestCase + err bool + }{ + { + "one-file", + fsTestCase{ + before: filesystemState{ + files: []string{ + "README.md", + }, + }, + after: filesystemState{}, + }, + false, + }, + { + "multiple-files", + fsTestCase{ + before: filesystemState{ + files: []string{ + "main.go", + "main_test.go", + "README", + }, + }, + after: filesystemState{ + files: []string{ + "main.go", + "main_test.go", + }, + }, + }, + false, + }, + { + "mixed-files", + fsTestCase{ + before: filesystemState{ + dirs: []string{ + "dir", + }, + files: []string{ + "dir/main.go", + "dir/main_test.go", + "dir/db.sqlite", + }, + }, + after: filesystemState{ + dirs: []string{ + "dir", + }, + files: []string{ + "dir/main.go", + "dir/main_test.go", + }, + }, + }, + false, + }, + } + + for _, tc := range testcases { + t.Run(tc.name, func(t *testing.T) { + h.TempDir(tc.name) + baseDir := h.Path(tc.name) + tc.fs.before.root = baseDir + tc.fs.after.root = baseDir + + tc.fs.setup(t) + + fs, err := deriveFilesystemState(baseDir) + if err != nil { + t.Fatal(err) + } + + err = pruneNonGoFiles(fs) + if tc.err && err == nil { + t.Errorf("expected an error, got nil") + } else if !tc.err && err != nil { + t.Errorf("unexpected error: %s", err) + } + + tc.fs.assert(t) + }) + } +} + +func TestPruneGoTestFiles(t *testing.T) { + h := test.NewHelper(t) + defer h.Cleanup() + + h.TempDir(".") + + testcases := []struct { + name string + fs fsTestCase + err bool + }{ + { + "one-test-file", + fsTestCase{ + before: filesystemState{ + files: []string{ + "main_test.go", + }, + }, + after: filesystemState{}, + }, + false, + }, + { + "multiple-files", + fsTestCase{ + before: filesystemState{ + dirs: []string{ + "dir", + }, + files: []string{ + "dir/main_test.go", + "dir/main2_test.go", + }, + }, + after: filesystemState{ + dirs: []string{ + "dir", + }, + }, + }, + false, + }, + { + "mixed-files", + fsTestCase{ + before: filesystemState{ + dirs: []string{ + "dir", + }, + files: []string{ + "dir/main.go", + "dir/main2.go", + "dir/main_test.go", + "dir/main2_test.go", + }, + }, + after: filesystemState{ + dirs: []string{ + "dir", + }, + files: []string{ + "dir/main.go", + "dir/main2.go", + }, + }, + }, + false, + }, + } + + for _, tc := range testcases { + t.Run(tc.name, func(t *testing.T) { + h.TempDir(tc.name) + baseDir := h.Path(tc.name) + tc.fs.before.root = baseDir + tc.fs.after.root = baseDir + + tc.fs.setup(t) + + fs, err := deriveFilesystemState(baseDir) + if err != nil { + t.Fatal(err) + } + + err = pruneGoTestFiles(fs) + if tc.err && err == nil { + t.Fatalf("expected an error, got nil") + } else if !tc.err && err != nil { + t.Fatalf("unexpected error: %s", err) + } + + tc.fs.assert(t) + }) + } +} + +func TestPruneVendorDirs(t *testing.T) { + tests := []struct { + name string + test fsTestCase + }{ + { + name: "vendor directory", + test: fsTestCase{ + before: filesystemState{ + dirs: []string{ + "package", + "package/vendor", + }, + }, + after: filesystemState{ + dirs: []string{ + "package", + }, + }, + }, + }, + { + name: "vendor file", + test: fsTestCase{ + before: filesystemState{ + dirs: []string{ + "package", + }, + files: []string{ + "package/vendor", + }, + }, + after: filesystemState{ + dirs: []string{ + "package", + }, + files: []string{ + "package/vendor", + }, + }, + }, + }, + { + name: "vendor symlink", + test: fsTestCase{ + before: filesystemState{ + dirs: []string{ + "package", + "package/_vendor", + }, + links: []fsLink{ + { + path: "package/vendor", + to: "_vendor", + }, + }, + }, + after: filesystemState{ + dirs: []string{ + "package", + "package/_vendor", + }, + }, + }, + }, + { + name: "nonvendor symlink", + test: fsTestCase{ + before: filesystemState{ + dirs: []string{ + "package", + "package/_vendor", + }, + links: []fsLink{ + { + path: "package/link", + to: "_vendor", + }, + }, + }, + after: filesystemState{ + dirs: []string{ + "package", + "package/_vendor", + }, + links: []fsLink{ + { + path: "package/link", + to: "_vendor", + }, + }, + }, + }, + }, + { + name: "vendor symlink to file", + test: fsTestCase{ + before: filesystemState{ + files: []string{ + "file", + }, + links: []fsLink{ + { + path: "vendor", + to: "file", + }, + }, + }, + after: filesystemState{ + files: []string{ + "file", + }, + }, + }, + }, + { + name: "broken vendor symlink", + test: fsTestCase{ + before: filesystemState{ + dirs: []string{ + "package", + }, + links: []fsLink{ + { + path: "package/vendor", + to: "nonexistence", + }, + }, + }, + after: filesystemState{ + dirs: []string{ + "package", + }, + links: []fsLink{}, + }, + }, + }, + { + name: "chained symlinks", + test: fsTestCase{ + before: filesystemState{ + dirs: []string{ + "_vendor", + }, + links: []fsLink{ + { + path: "vendor", + to: "vendor2", + }, + { + path: "vendor2", + to: "_vendor", + }, + }, + }, + after: filesystemState{ + dirs: []string{ + "_vendor", + }, + links: []fsLink{ + { + path: "vendor2", + to: "_vendor", + }, + }, + }, + }, + }, + { + name: "circular symlinks", + test: fsTestCase{ + before: filesystemState{ + dirs: []string{ + "package", + }, + links: []fsLink{ + { + path: "package/link1", + to: "link2", + }, + { + path: "package/link2", + to: "link1", + }, + }, + }, + after: filesystemState{ + dirs: []string{ + "package", + }, + links: []fsLink{ + { + path: "package/link1", + to: "link2", + }, + { + path: "package/link2", + to: "link1", + }, + }, + }, + }, + }, + } + + for _, test := range tests { + t.Run(test.name, pruneVendorDirsTestCase(test.test)) + } +} + +func pruneVendorDirsTestCase(tc fsTestCase) func(*testing.T) { + return func(t *testing.T) { + tempDir, err := ioutil.TempDir("", "pruneVendorDirsTestCase") + if err != nil { + t.Fatalf("ioutil.TempDir err=%q", err) + } + defer func() { + if err := os.RemoveAll(tempDir); err != nil { + t.Errorf("os.RemoveAll(%q) err=%q", tempDir, err) + } + }() + + tc.before.root = tempDir + tc.after.root = tempDir + + tc.setup(t) + + fs, err := deriveFilesystemState(tempDir) + if err != nil { + t.Fatalf("deriveFilesystemState failed: %s", err) + } + + if err := pruneVendorDirs(fs); err != nil { + t.Errorf("pruneVendorDirs err=%q", err) + } + + tc.assert(t) + } +} + +func TestDeleteEmptyDirs(t *testing.T) { + testcases := []struct { + name string + fs fsTestCase + }{ + { + name: "empty-dir", + fs: fsTestCase{ + before: filesystemState{ + dirs: []string{ + "pkg1", + }, + }, + after: filesystemState{}, + }, + }, + { + name: "nested-empty-dirs", + fs: fsTestCase{ + before: filesystemState{ + dirs: []string{ + "pkg1", + "pkg1/pkg2", + }, + }, + after: filesystemState{}, + }, + }, + { + name: "non-empty-dir", + fs: fsTestCase{ + before: filesystemState{ + dirs: []string{ + "pkg1", + }, + files: []string{ + "pkg1/file1", + }, + }, + after: filesystemState{ + dirs: []string{ + "pkg1", + }, + files: []string{ + "pkg1/file1", + }, + }, + }, + }, + { + name: "mixed-dirs", + fs: fsTestCase{ + before: filesystemState{ + dirs: []string{ + "pkg1", + "pkg1/pkg2", + }, + files: []string{ + "pkg1/file1", + }, + }, + after: filesystemState{ + dirs: []string{ + "pkg1", + }, + files: []string{ + "pkg1/file1", + }, + }, + }, + }, + } + + for _, tc := range testcases { + t.Run(tc.name, func(t *testing.T) { + h := test.NewHelper(t) + h.Cleanup() + h.TempDir(".") + + tc.fs.before.root = h.Path(".") + tc.fs.after.root = h.Path(".") + + if err := tc.fs.before.setup(); err != nil { + t.Fatal("unexpected error in fs setup: ", err) + } + + if err := deleteEmptyDirs(tc.fs.before); err != nil { + t.Fatal("unexpected error in deleteEmptyDirs: ", err) + } + + tc.fs.assert(t) + }) + } +} diff --git a/vendor/github.com/golang/dep/gps/rootdata.go b/vendor/github.com/golang/dep/gps/rootdata.go new file mode 100644 index 00000000..ee78bdf2 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/rootdata.go @@ -0,0 +1,204 @@ +// Copyright 2017 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 gps + +import ( + "sort" + + "github.com/armon/go-radix" + "github.com/golang/dep/gps/pkgtree" +) + +// rootdata holds static data and constraining rules from the root project for +// use in solving. +type rootdata struct { + // Path to the root of the project on which gps is operating. + dir string + + // Ruleset for ignored import paths. + ir *pkgtree.IgnoredRuleset + + // Map of packages to require. + req map[string]bool + + // A ProjectConstraints map containing the validated (guaranteed non-empty) + // overrides declared by the root manifest. + ovr ProjectConstraints + + // A map of the ProjectRoot (local names) that should be allowed to change + chng map[ProjectRoot]struct{} + + // Flag indicating all projects should be allowed to change, without regard + // for lock. + chngall bool + + // A map of the project names listed in the root's lock. + rlm map[ProjectRoot]LockedProject + + // A defensively copied instance of the root manifest. + rm SimpleManifest + + // A defensively copied instance of the root lock. + rl safeLock + + // A defensively copied instance of params.RootPackageTree + rpt pkgtree.PackageTree + + // The ProjectAnalyzer to use for all GetManifestAndLock calls. + an ProjectAnalyzer +} + +// externalImportList returns a list of the unique imports from the root data. +// Ignores and requires are taken into consideration, stdlib is excluded, and +// errors within the local set of package are not backpropagated. +func (rd rootdata) externalImportList(stdLibFn func(string) bool) []string { + rm, _ := rd.rpt.ToReachMap(true, true, false, rd.ir) + reach := rm.FlattenFn(stdLibFn) + + // If there are any requires, slide them into the reach list, as well. + if len(rd.req) > 0 { + // Make a map of imports that are both in the import path list and the + // required list to avoid duplication. + skip := make(map[string]bool, len(rd.req)) + for _, r := range reach { + if rd.req[r] { + skip[r] = true + } + } + + for r := range rd.req { + if !skip[r] { + reach = append(reach, r) + } + } + } + + sort.Strings(reach) + return reach +} + +func (rd rootdata) getApplicableConstraints(stdLibFn func(string) bool) []workingConstraint { + pc := rd.rm.DependencyConstraints() + + // Ensure that overrides which aren't in the combined pc map already make it + // in. Doing so makes input hashes equal in more useful cases. + for pr, pp := range rd.ovr { + if _, has := pc[pr]; !has { + cpp := ProjectProperties{ + Constraint: pp.Constraint, + Source: pp.Source, + } + if cpp.Constraint == nil { + cpp.Constraint = anyConstraint{} + } + + pc[pr] = cpp + } + } + + // Now override them all to produce a consolidated workingConstraint slice + combined := rd.ovr.overrideAll(pc) + + type wccount struct { + count int + wc workingConstraint + } + xt := radix.New() + for _, wc := range combined { + xt.Insert(string(wc.Ident.ProjectRoot), wccount{wc: wc}) + } + + // Walk all dep import paths we have to consider and mark the corresponding + // wc entry in the trie, if any + for _, im := range rd.externalImportList(stdLibFn) { + if stdLibFn(im) { + continue + } + + if pre, v, match := xt.LongestPrefix(im); match && isPathPrefixOrEqual(pre, im) { + wcc := v.(wccount) + wcc.count++ + xt.Insert(pre, wcc) + } + } + + var ret []workingConstraint + + xt.Walk(func(s string, v interface{}) bool { + wcc := v.(wccount) + if wcc.count > 0 { + ret = append(ret, wcc.wc) + } + return false + }) + + return ret +} + +func (rd rootdata) combineConstraints() []workingConstraint { + return rd.ovr.overrideAll(rd.rm.DependencyConstraints()) +} + +// needVersionListFor indicates whether we need a version list for a given +// project root, based solely on general solver inputs (no constraint checking +// required). Assuming the argument is not the root project itself, this will be +// true if any of the following conditions hold: +// +// - ChangeAll is on +// - The project is not in the lock +// - The project is in the lock, but is also in the list of projects to change +func (rd rootdata) needVersionsFor(pr ProjectRoot) bool { + if rd.isRoot(pr) { + return false + } + + if rd.chngall { + return true + } + + if _, has := rd.rlm[pr]; !has { + // not in the lock + return true + } + + if _, has := rd.chng[pr]; has { + // in the lock, but marked for change + return true + } + // in the lock, not marked for change + return false + +} + +func (rd rootdata) isRoot(pr ProjectRoot) bool { + return pr == ProjectRoot(rd.rpt.ImportRoot) +} + +// rootAtom creates an atomWithPackages that represents the root project. +func (rd rootdata) rootAtom() atomWithPackages { + a := atom{ + id: ProjectIdentifier{ + ProjectRoot: ProjectRoot(rd.rpt.ImportRoot), + }, + // This is a hack so that the root project doesn't have a nil version. + // It's sort of OK because the root never makes it out into the results. + // We may need a more elegant solution if we discover other side + // effects, though. + v: rootRev, + } + + list := make([]string, 0, len(rd.rpt.Packages)) + for path, pkg := range rd.rpt.Packages { + if pkg.Err != nil && !rd.ir.IsIgnored(path) { + list = append(list, path) + } + } + sort.Strings(list) + + return atomWithPackages{ + a: a, + pl: list, + } +} diff --git a/vendor/github.com/golang/dep/gps/rootdata_test.go b/vendor/github.com/golang/dep/gps/rootdata_test.go new file mode 100644 index 00000000..381fe8c4 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/rootdata_test.go @@ -0,0 +1,226 @@ +// Copyright 2017 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 gps + +import ( + "reflect" + "testing" + + "github.com/golang/dep/gps/pkgtree" +) + +func TestRootdataExternalImports(t *testing.T) { + fix := basicFixtures["shared dependency with overlapping constraints"] + + params := SolveParameters{ + RootDir: string(fix.ds[0].n), + RootPackageTree: fix.rootTree(), + Manifest: fix.rootmanifest(), + ProjectAnalyzer: naiveAnalyzer{}, + stdLibFn: func(string) bool { return false }, + mkBridgeFn: overrideMkBridge, + } + + is, err := Prepare(params, newdepspecSM(fix.ds, nil)) + if err != nil { + t.Fatalf("Unexpected error while prepping solver: %s", err) + } + rd := is.(*solver).rd + + want := []string{"a", "b"} + got := rd.externalImportList(params.stdLibFn) + if !reflect.DeepEqual(want, got) { + t.Errorf("Unexpected return from rootdata.externalImportList:\n\t(GOT): %s\n\t(WNT): %s", got, want) + } + + // Add a require + rd.req["c"] = true + + want = []string{"a", "b", "c"} + got = rd.externalImportList(params.stdLibFn) + if !reflect.DeepEqual(want, got) { + t.Errorf("Unexpected return from rootdata.externalImportList:\n\t(GOT): %s\n\t(WNT): %s", got, want) + } + + // Add same path as import + poe := rd.rpt.Packages["root"] + poe.P.Imports = []string{"a", "b", "c"} + rd.rpt.Packages["root"] = poe + + // should still be the same + got = rd.externalImportList(params.stdLibFn) + if !reflect.DeepEqual(want, got) { + t.Errorf("Unexpected return from rootdata.externalImportList:\n\t(GOT): %s\n\t(WNT): %s", got, want) + } + + // Add an ignore, but not on the required path (Prepare makes that + // combination impossible) + + rd.ir = pkgtree.NewIgnoredRuleset([]string{"b"}) + want = []string{"a", "c"} + got = rd.externalImportList(params.stdLibFn) + if !reflect.DeepEqual(want, got) { + t.Errorf("Unexpected return from rootdata.externalImportList:\n\t(GOT): %s\n\t(WNT): %s", got, want) + } +} + +func TestGetApplicableConstraints(t *testing.T) { + fix := basicFixtures["shared dependency with overlapping constraints"] + + params := SolveParameters{ + RootDir: string(fix.ds[0].n), + RootPackageTree: fix.rootTree(), + Manifest: fix.rootmanifest(), + ProjectAnalyzer: naiveAnalyzer{}, + stdLibFn: func(string) bool { return false }, + mkBridgeFn: overrideMkBridge, + } + + is, err := Prepare(params, newdepspecSM(fix.ds, nil)) + if err != nil { + t.Fatalf("Unexpected error while prepping solver: %s", err) + } + rd := is.(*solver).rd + + table := []struct { + name string + mut func() + result []workingConstraint + }{ + { + name: "base case, two constraints", + mut: func() {}, + result: []workingConstraint{ + { + Ident: mkPI("a"), + Constraint: mkSVC("1.0.0"), + }, + { + Ident: mkPI("b"), + Constraint: mkSVC("1.0.0"), + }, + }, + }, + { + name: "with unconstrained require", + mut: func() { + // No constraint means it doesn't show up + rd.req["c"] = true + }, + result: []workingConstraint{ + { + Ident: mkPI("a"), + Constraint: mkSVC("1.0.0"), + }, + { + Ident: mkPI("b"), + Constraint: mkSVC("1.0.0"), + }, + }, + }, + { + name: "with unconstrained import", + mut: func() { + // Again, no constraint means it doesn't show up + poe := rd.rpt.Packages["root"] + poe.P.Imports = []string{"a", "b", "d"} + rd.rpt.Packages["root"] = poe + }, + result: []workingConstraint{ + { + Ident: mkPI("a"), + Constraint: mkSVC("1.0.0"), + }, + { + Ident: mkPI("b"), + Constraint: mkSVC("1.0.0"), + }, + }, + }, + { + name: "constraint on required", + mut: func() { + rd.rm.Deps["c"] = ProjectProperties{ + Constraint: NewBranch("foo"), + } + }, + result: []workingConstraint{ + { + Ident: mkPI("a"), + Constraint: mkSVC("1.0.0"), + }, + { + Ident: mkPI("b"), + Constraint: mkSVC("1.0.0"), + }, + { + Ident: mkPI("c"), + Constraint: NewBranch("foo"), + }, + }, + }, + { + name: "override on imported", + mut: func() { + rd.ovr["d"] = ProjectProperties{ + Constraint: NewBranch("bar"), + } + }, + result: []workingConstraint{ + { + Ident: mkPI("a"), + Constraint: mkSVC("1.0.0"), + }, + { + Ident: mkPI("b"), + Constraint: mkSVC("1.0.0"), + }, + { + Ident: mkPI("c"), + Constraint: NewBranch("foo"), + }, + { + Ident: mkPI("d"), + Constraint: NewBranch("bar"), + overrConstraint: true, + }, + }, + }, + { + // It is certainly the simplest and most rule-abiding solution to + // drop the constraint in this case, but is there a chance it would + // violate the principle of least surprise? + name: "ignore imported and overridden pkg", + mut: func() { + rd.ir = pkgtree.NewIgnoredRuleset([]string{"d"}) + }, + result: []workingConstraint{ + { + Ident: mkPI("a"), + Constraint: mkSVC("1.0.0"), + }, + { + Ident: mkPI("b"), + Constraint: mkSVC("1.0.0"), + }, + { + Ident: mkPI("c"), + Constraint: NewBranch("foo"), + }, + }, + }, + } + + for _, fix := range table { + t.Run(fix.name, func(t *testing.T) { + fix.mut() + + got := rd.getApplicableConstraints(params.stdLibFn) + if !reflect.DeepEqual(fix.result, got) { + t.Errorf("unexpected applicable constraint set:\n\t(GOT): %+v\n\t(WNT): %+v", got, fix.result) + } + }) + } +} diff --git a/vendor/github.com/golang/dep/gps/satisfy.go b/vendor/github.com/golang/dep/gps/satisfy.go new file mode 100644 index 00000000..abac0ea7 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/satisfy.go @@ -0,0 +1,337 @@ +// Copyright 2017 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 gps + +// check performs constraint checks on the provided atom. The set of checks +// differ slightly depending on whether the atom is pkgonly, or if it's the +// entire project being added for the first time. +// +// The goal is to determine whether selecting the atom would result in a state +// where all the solver requirements are still satisfied. +func (s *solver) check(a atomWithPackages, pkgonly bool) error { + pa := a.a + if nilpa == pa { + // This shouldn't be able to happen, but if it does, it unequivocally + // indicates a logical bug somewhere, so blowing up is preferable + panic("canary - checking version of empty ProjectAtom") + } + + s.mtr.push("satisfy") + var err error + defer func() { + if err != nil { + s.traceInfo(err) + } + s.mtr.pop() + }() + + // If we're pkgonly, then base atom was already determined to be allowable, + // so we can skip the checkAtomAllowable step. + if !pkgonly { + if err = s.checkAtomAllowable(pa); err != nil { + return err + } + } + + if err = s.checkRequiredPackagesExist(a); err != nil { + return err + } + + var deps []completeDep + _, deps, err = s.getImportsAndConstraintsOf(a) + if err != nil { + // An err here would be from the package fetcher; pass it straight back + return err + } + + // TODO(sdboyer) this deps list contains only packages not already selected + // from the target atom (assuming one is selected at all). It's fine for + // now, but won't be good enough when we get around to doing static + // analysis. + for _, dep := range deps { + if err = s.checkIdentMatches(a, dep); err != nil { + return err + } + if err = s.checkRootCaseConflicts(a, dep); err != nil { + return err + } + if err = s.checkDepsConstraintsAllowable(a, dep); err != nil { + return err + } + if err = s.checkDepsDisallowsSelected(a, dep); err != nil { + return err + } + if err = s.checkRevisionExists(a, dep); err != nil { + return err + } + if err = s.checkPackageImportsFromDepExist(a, dep); err != nil { + return err + } + + // TODO(sdboyer) add check that fails if adding this atom would create a loop + } + + return nil +} + +// checkAtomAllowable ensures that an atom itself is acceptable with respect to +// the constraints established by the current solution. +func (s *solver) checkAtomAllowable(pa atom) error { + constraint := s.sel.getConstraint(pa.id) + if s.vUnify.matches(pa.id, constraint, pa.v) { + return nil + } + // TODO(sdboyer) collect constraint failure reason (wait...aren't we, below?) + + deps := s.sel.getDependenciesOn(pa.id) + var failparent []dependency + for _, dep := range deps { + if !s.vUnify.matches(pa.id, dep.dep.Constraint, pa.v) { + s.fail(dep.depender.id) + failparent = append(failparent, dep) + } + } + + err := &versionNotAllowedFailure{ + goal: pa, + failparent: failparent, + c: constraint, + } + + return err +} + +// checkRequiredPackagesExist ensures that all required packages enumerated by +// existing dependencies on this atom are actually present in the atom. +func (s *solver) checkRequiredPackagesExist(a atomWithPackages) error { + ptree, err := s.b.ListPackages(a.a.id, a.a.v) + if err != nil { + // TODO(sdboyer) handle this more gracefully + return err + } + + deps := s.sel.getDependenciesOn(a.a.id) + fp := make(map[string]errDeppers) + // We inspect these in a bit of a roundabout way, in order to incrementally + // build up the failure we'd return if there is, indeed, a missing package. + // TODO(sdboyer) rechecking all of these every time is wasteful. Is there a shortcut? + for _, dep := range deps { + for _, pkg := range dep.dep.pl { + if errdep, seen := fp[pkg]; seen { + errdep.deppers = append(errdep.deppers, dep.depender) + fp[pkg] = errdep + } else { + perr, has := ptree.Packages[pkg] + if !has || perr.Err != nil { + fp[pkg] = errDeppers{ + err: perr.Err, + deppers: []atom{dep.depender}, + } + } + } + } + } + + if len(fp) > 0 { + return &checkeeHasProblemPackagesFailure{ + goal: a.a, + failpkg: fp, + } + } + return nil +} + +// checkDepsConstraintsAllowable checks that the constraints of an atom on a +// given dep are valid with respect to existing constraints. +func (s *solver) checkDepsConstraintsAllowable(a atomWithPackages, cdep completeDep) error { + dep := cdep.workingConstraint + constraint := s.sel.getConstraint(dep.Ident) + // Ensure the constraint expressed by the dep has at least some possible + // intersection with the intersection of existing constraints. + if s.vUnify.matchesAny(dep.Ident, constraint, dep.Constraint) { + return nil + } + + siblings := s.sel.getDependenciesOn(dep.Ident) + // No admissible versions - visit all siblings and identify the disagreement(s) + var failsib []dependency + var nofailsib []dependency + for _, sibling := range siblings { + if !s.vUnify.matchesAny(dep.Ident, sibling.dep.Constraint, dep.Constraint) { + s.fail(sibling.depender.id) + failsib = append(failsib, sibling) + } else { + nofailsib = append(nofailsib, sibling) + } + } + + return &disjointConstraintFailure{ + goal: dependency{depender: a.a, dep: cdep}, + failsib: failsib, + nofailsib: nofailsib, + c: constraint, + } +} + +// checkDepsDisallowsSelected ensures that an atom's constraints on a particular +// dep are not incompatible with the version of that dep that's already been +// selected. +func (s *solver) checkDepsDisallowsSelected(a atomWithPackages, cdep completeDep) error { + dep := cdep.workingConstraint + selected, exists := s.sel.selected(dep.Ident) + if exists && !s.vUnify.matches(dep.Ident, dep.Constraint, selected.a.v) { + s.fail(dep.Ident) + + return &constraintNotAllowedFailure{ + goal: dependency{depender: a.a, dep: cdep}, + v: selected.a.v, + } + } + return nil +} + +// checkIdentMatches ensures that the LocalName of a dep introduced by an atom, +// has the same Source as what's already been selected (assuming anything's been +// selected). +// +// In other words, this ensures that the solver never simultaneously selects two +// identifiers with the same local name, but that disagree about where their +// network source is. +func (s *solver) checkIdentMatches(a atomWithPackages, cdep completeDep) error { + dep := cdep.workingConstraint + if curid, has := s.sel.getIdentFor(dep.Ident.ProjectRoot); has && !curid.equiv(dep.Ident) { + deps := s.sel.getDependenciesOn(a.a.id) + // Fail all the other deps, as there's no way atom can ever be + // compatible with them + for _, d := range deps { + s.fail(d.depender.id) + } + + return &sourceMismatchFailure{ + shared: dep.Ident.ProjectRoot, + sel: deps, + current: curid.normalizedSource(), + mismatch: dep.Ident.normalizedSource(), + prob: a.a, + } + } + + return nil +} + +// checkRootCaseConflicts ensures that the ProjectRoot specified in the completeDep +// does not have case conflicts with any existing dependencies. +// +// We only need to check the ProjectRoot, rather than any packages therein, as +// the later check for package existence is case-sensitive. +func (s *solver) checkRootCaseConflicts(a atomWithPackages, cdep completeDep) error { + pr := cdep.workingConstraint.Ident.ProjectRoot + hasConflict, current := s.sel.findCaseConflicts(pr) + if !hasConflict { + return nil + } + + curid, _ := s.sel.getIdentFor(current) + deps := s.sel.getDependenciesOn(curid) + for _, d := range deps { + s.fail(d.depender.id) + } + + // If a project has multiple packages that import each other, we treat that + // as establishing a canonical case variant for the ProjectRoot. It's possible, + // however, that that canonical variant is not the same one that others + // imported it under. If that's the situation, then we'll have arrived here + // when visiting the project, not its dependers, having misclassified its + // internal imports as external. That means the atomWithPackages will + // be the wrong case variant induced by the importers, and the cdep will be + // a link pointing back at the canonical case variant. + // + // If this is the case, use a special failure, wrongCaseFailure, that + // makes a stronger statement as to the correctness of case variants. + // + // TODO(sdboyer) This approach to marking failure is less than great, as + // this will mark the current atom as failed, as well, causing the + // backtracker to work through it. While that could prove fruitful, it's + // quite likely just to be wasted effort. Addressing this - if that's a good + // idea - would entail creating another path back out of checking to enable + // backjumping directly to the incorrect importers. + if current == a.a.id.ProjectRoot { + return &wrongCaseFailure{ + correct: pr, + goal: dependency{depender: a.a, dep: cdep}, + badcase: deps, + } + } + + return &caseMismatchFailure{ + goal: dependency{depender: a.a, dep: cdep}, + current: current, + failsib: deps, + } +} + +// checkPackageImportsFromDepExist ensures that, if the dep is already selected, +// the newly-required set of packages being placed on it exist and are valid. +func (s *solver) checkPackageImportsFromDepExist(a atomWithPackages, cdep completeDep) error { + sel, is := s.sel.selected(cdep.workingConstraint.Ident) + if !is { + // dep is not already selected; nothing to do + return nil + } + + ptree, err := s.b.ListPackages(sel.a.id, sel.a.v) + if err != nil { + // TODO(sdboyer) handle this more gracefully + return err + } + + e := &depHasProblemPackagesFailure{ + goal: dependency{ + depender: a.a, + dep: cdep, + }, + v: sel.a.v, + prob: make(map[string]error), + } + + for _, pkg := range cdep.pl { + perr, has := ptree.Packages[pkg] + if !has || perr.Err != nil { + if has { + e.prob[pkg] = perr.Err + } else { + e.prob[pkg] = nil + } + } + } + + if len(e.prob) > 0 { + return e + } + return nil +} + +// checkRevisionExists ensures that if a dependency is constrained by a +// revision, that that revision actually exists. +func (s *solver) checkRevisionExists(a atomWithPackages, cdep completeDep) error { + r, isrev := cdep.Constraint.(Revision) + if !isrev { + // Constraint is not a revision; nothing to do + return nil + } + + present, _ := s.b.RevisionPresentIn(cdep.Ident, r) + if present { + return nil + } + + return &nonexistentRevisionFailure{ + goal: dependency{ + depender: a.a, + dep: cdep, + }, + r: r, + } +} diff --git a/vendor/github.com/golang/dep/gps/selection.go b/vendor/github.com/golang/dep/gps/selection.go new file mode 100644 index 00000000..a74c60ae --- /dev/null +++ b/vendor/github.com/golang/dep/gps/selection.go @@ -0,0 +1,242 @@ +// Copyright 2017 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 gps + +type selection struct { + // projects is a stack of the atoms that have currently been selected by the + // solver. It can also be thought of as the vertex set of the current + // selection graph. + projects []selected + // deps records the set of dependers on a given ProjectRoot. It is + // essentially an adjacency list of *inbound* edges. + deps map[ProjectRoot][]dependency + // foldRoots records a mapping from a canonical, case-folded form of + // ProjectRoots to the particular case variant that has currently been + // selected. + foldRoots map[string]ProjectRoot + // The versoinUnifier in use for this solve run. + vu *versionUnifier +} + +type selected struct { + a atomWithPackages + first bool +} + +func (s *selection) getDependenciesOn(id ProjectIdentifier) []dependency { + if deps, exists := s.deps[id.ProjectRoot]; exists { + return deps + } + + return nil +} + +// getIdentFor returns the ProjectIdentifier (so, the network name) currently in +// use for the provided ProjectRoot. +// +// If no dependencies are present yet that designate a network name for +// the provided root, this will return an empty ProjectIdentifier and false. +func (s *selection) getIdentFor(pr ProjectRoot) (ProjectIdentifier, bool) { + deps := s.getDependenciesOn(ProjectIdentifier{ProjectRoot: pr}) + if len(deps) == 0 { + return ProjectIdentifier{}, false + } + + // For now, at least, the solver maintains (assumes?) the invariant that + // whatever is first in the deps list decides the net name to be used. + return deps[0].dep.Ident, true +} + +// pushSelection pushes a new atomWithPackages onto the selection stack, along +// with an indicator as to whether this selection indicates a new project *and* +// packages, or merely some new packages on a project that was already selected. +func (s *selection) pushSelection(a atomWithPackages, pkgonly bool) { + s.projects = append(s.projects, selected{ + a: a, + first: !pkgonly, + }) +} + +// popSelection removes and returns the last atomWithPackages from the selection +// stack, along with an indication of whether that element was the first from +// that project - that is, if it represented an addition of both a project and +// one or more packages to the overall selection. +func (s *selection) popSelection() (atomWithPackages, bool) { + var sel selected + sel, s.projects = s.projects[len(s.projects)-1], s.projects[:len(s.projects)-1] + return sel.a, sel.first +} + +// findCaseConflicts checks to see if the given ProjectRoot has a +// case-insensitive overlap with another, different ProjectRoot that's already +// been picked. +func (s *selection) findCaseConflicts(pr ProjectRoot) (bool, ProjectRoot) { + if current, has := s.foldRoots[toFold(string(pr))]; has && pr != current { + return true, current + } + + return false, "" +} + +func (s *selection) pushDep(dep dependency) { + pr := dep.dep.Ident.ProjectRoot + deps := s.deps[pr] + if len(deps) == 0 { + s.foldRoots[toFold(string(pr))] = pr + } + + s.deps[pr] = append(deps, dep) +} + +func (s *selection) popDep(id ProjectIdentifier) (dep dependency) { + deps := s.deps[id.ProjectRoot] + dlen := len(deps) + if dlen == 1 { + delete(s.foldRoots, toFold(string(id.ProjectRoot))) + } + + dep, s.deps[id.ProjectRoot] = deps[dlen-1], deps[:dlen-1] + return dep +} + +func (s *selection) depperCount(id ProjectIdentifier) int { + return len(s.deps[id.ProjectRoot]) +} + +// Compute a list of the unique packages within the given ProjectIdentifier that +// have dependers, and the number of dependers they have. +func (s *selection) getRequiredPackagesIn(id ProjectIdentifier) map[string]int { + // TODO(sdboyer) this is horribly inefficient to do on the fly; we need a method to + // precompute it on pushing a new dep, and preferably with an immut + // structure so that we can pop with zero cost. + uniq := make(map[string]int) + for _, dep := range s.deps[id.ProjectRoot] { + for _, pkg := range dep.dep.pl { + uniq[pkg] = uniq[pkg] + 1 + } + } + + return uniq +} + +// Suppress unused warning. +var _ = (*selection)(nil).getSelectedPackagesIn + +// Compute a list of the unique packages within the given ProjectIdentifier that +// are currently selected, and the number of times each package has been +// independently selected. +func (s *selection) getSelectedPackagesIn(id ProjectIdentifier) map[string]int { + // TODO(sdboyer) this is horribly inefficient to do on the fly; we need a method to + // precompute it on pushing a new dep, and preferably with an immut + // structure so that we can pop with zero cost. + uniq := make(map[string]int) + for _, p := range s.projects { + if p.a.a.id.eq(id) { + for _, pkg := range p.a.pl { + uniq[pkg] = uniq[pkg] + 1 + } + } + } + + return uniq +} + +func (s *selection) getConstraint(id ProjectIdentifier) Constraint { + deps, exists := s.deps[id.ProjectRoot] + if !exists || len(deps) == 0 { + return any + } + + // TODO(sdboyer) recomputing this sucks and is quite wasteful. Precompute/cache it + // on changes to the constraint set, instead. + + // The solver itself is expected to maintain the invariant that all the + // constraints kept here collectively admit a non-empty set of versions. We + // assume this is the case here while assembling a composite constraint. + + // Start with the open set + var ret Constraint = any + for _, dep := range deps { + ret = s.vu.intersect(id, ret, dep.dep.Constraint) + } + + return ret +} + +// selected checks to see if the given ProjectIdentifier has been selected, and +// if so, returns the corresponding atomWithPackages. +// +// It walks the projects selection list from front to back and returns the first +// match it finds, which means it will always and only return the base selection +// of the project, without any additional package selections that may or may not +// have happened later. +func (s *selection) selected(id ProjectIdentifier) (atomWithPackages, bool) { + for _, p := range s.projects { + if p.a.a.id.ProjectRoot == id.ProjectRoot { + return p.a, true + } + } + + return atomWithPackages{a: nilpa}, false +} + +type unselected struct { + sl []bimodalIdentifier + cmp func(i, j int) bool +} + +func (u unselected) Len() int { + return len(u.sl) +} + +func (u unselected) Less(i, j int) bool { + return u.cmp(i, j) +} + +func (u unselected) Swap(i, j int) { + u.sl[i], u.sl[j] = u.sl[j], u.sl[i] +} + +func (u *unselected) Push(x interface{}) { + u.sl = append(u.sl, x.(bimodalIdentifier)) +} + +func (u *unselected) Pop() (v interface{}) { + v, u.sl = u.sl[len(u.sl)-1], u.sl[:len(u.sl)-1] + return v +} + +// remove takes a bimodalIdentifier out of the priority queue, if present. Only +// the first matching bmi will be removed. +// +// There are two events that cause this to be called: bmi selection, when the +// bmi at the front of the queue is removed, and backtracking, when a bmi +// becomes unnecessary because the dependency that induced it was backtracked +// and popped off. +// +// The worst case for both of these is O(n), but in practice the first case is +// O(1), as we iterate the queue from front to back. +func (u *unselected) remove(bmi bimodalIdentifier) { + plen := len(bmi.pl) +outer: + for i, pi := range u.sl { + if pi.id.eq(bmi.id) && len(pi.pl) == plen { + // Simple slice comparison - assume they're both sorted the same + for i2, pkg := range pi.pl { + if bmi.pl[i2] != pkg { + continue outer + } + } + + if i == len(u.sl)-1 { + // if we're on the last element, just pop, no splice + u.sl = u.sl[:len(u.sl)-1] + } else { + u.sl = append(u.sl[:i], u.sl[i+1:]...) + } + break + } + } +} diff --git a/vendor/github.com/golang/dep/gps/selection_test.go b/vendor/github.com/golang/dep/gps/selection_test.go new file mode 100644 index 00000000..13c4aabf --- /dev/null +++ b/vendor/github.com/golang/dep/gps/selection_test.go @@ -0,0 +1,63 @@ +// Copyright 2017 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 gps + +import ( + "reflect" + "testing" +) + +// Regression test for https://github.com/sdboyer/gps/issues/174 +func TestUnselectedRemoval(t *testing.T) { + // We don't need a comparison function for this test + bmi1 := bimodalIdentifier{ + id: mkPI("foo"), + pl: []string{"foo", "bar"}, + } + bmi2 := bimodalIdentifier{ + id: mkPI("foo"), + pl: []string{"foo", "bar", "baz"}, + } + bmi3 := bimodalIdentifier{ + id: mkPI("foo"), + pl: []string{"foo"}, + } + + u := &unselected{ + sl: []bimodalIdentifier{bmi1, bmi2, bmi3}, + } + + u.remove(bimodalIdentifier{ + id: mkPI("other"), + pl: []string{"other"}, + }) + + if len(u.sl) != 3 { + t.Fatalf("len of unselected slice should have been 2 after no-op removal, got %v", len(u.sl)) + } + + u.remove(bmi3) + want := []bimodalIdentifier{bmi1, bmi2} + if len(u.sl) != 2 { + t.Fatalf("removal of matching bmi did not work, slice should have 2 items but has %v", len(u.sl)) + } + if !reflect.DeepEqual(u.sl, want) { + t.Fatalf("wrong item removed from slice:\n\t(GOT): %v\n\t(WNT): %v", u.sl, want) + } + + u.remove(bmi3) + if len(u.sl) != 2 { + t.Fatalf("removal of bmi w/non-matching packages should be a no-op but wasn't; slice should have 2 items but has %v", len(u.sl)) + } + + u.remove(bmi2) + want = []bimodalIdentifier{bmi1} + if len(u.sl) != 1 { + t.Fatalf("removal of matching bmi did not work, slice should have 1 items but has %v", len(u.sl)) + } + if !reflect.DeepEqual(u.sl, want) { + t.Fatalf("wrong item removed from slice:\n\t(GOT): %v\n\t(WNT): %v", u.sl, want) + } +} diff --git a/vendor/github.com/golang/dep/gps/solution.go b/vendor/github.com/golang/dep/gps/solution.go new file mode 100644 index 00000000..7eb419e4 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/solution.go @@ -0,0 +1,159 @@ +// Copyright 2017 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 gps + +import ( + "context" + "fmt" + "log" + "os" + "path/filepath" + "sync" + + "github.com/pkg/errors" + "golang.org/x/sync/errgroup" +) + +// A Solution is returned by a solver run. It is mostly just a Lock, with some +// additional methods that report information about the solve run. +type Solution interface { + Lock + // The name of the ProjectAnalyzer used in generating this solution. + AnalyzerName() string + // The version of the ProjectAnalyzer used in generating this solution. + AnalyzerVersion() int + // The name of the Solver used in generating this solution. + SolverName() string + // The version of the Solver used in generating this solution. + SolverVersion() int + Attempts() int +} + +type solution struct { + // A list of the projects selected by the solver. + p []LockedProject + + // The number of solutions that were attempted + att int + + // The hash digest of the input opts + hd []byte + + // The analyzer info + analyzerInfo ProjectAnalyzerInfo + + // The solver used in producing this solution + solv Solver +} + +const concurrentWriters = 16 + +// WriteDepTree takes a basedir, a Lock and a RootPruneOptions and exports all +// the projects listed in the lock to the appropriate target location within basedir. +// +// If the goal is to populate a vendor directory, basedir should be the absolute +// path to that vendor directory, not its parent (a project root, typically). +// +// It requires a SourceManager to do the work. Prune options are read from the +// passed manifest. +func WriteDepTree(basedir string, l Lock, sm SourceManager, co CascadingPruneOptions, logger *log.Logger) error { + if l == nil { + return fmt.Errorf("must provide non-nil Lock to WriteDepTree") + } + + if err := os.MkdirAll(basedir, 0777); err != nil { + return err + } + + g, ctx := errgroup.WithContext(context.TODO()) + lps := l.Projects() + sem := make(chan struct{}, concurrentWriters) + var cnt struct { + sync.Mutex + i int + } + + for i := range lps { + p := lps[i] // per-iteration copy + + g.Go(func() error { + err := func() error { + select { + case sem <- struct{}{}: + defer func() { <-sem }() + case <-ctx.Done(): + return ctx.Err() + } + + ident := p.Ident() + projectRoot := string(ident.ProjectRoot) + to := filepath.FromSlash(filepath.Join(basedir, projectRoot)) + + if err := sm.ExportProject(ctx, ident, p.Version(), to); err != nil { + return errors.Wrapf(err, "failed to export %s", projectRoot) + } + + err := PruneProject(to, p, co.PruneOptionsFor(ident.ProjectRoot), logger) + if err != nil { + return errors.Wrapf(err, "failed to prune %s", projectRoot) + } + + return ctx.Err() + }() + + switch err { + case context.Canceled, context.DeadlineExceeded: + // Don't log "secondary" errors. + default: + msg := "Wrote" + if err != nil { + msg = "Failed to write" + } + + // Log and increment atomically to prevent re-ordering. + cnt.Lock() + cnt.i++ + logger.Printf("(%d/%d) %s %s@%s\n", cnt.i, len(lps), msg, p.Ident(), p.Version()) + cnt.Unlock() + } + + return err + }) + } + + err := g.Wait() + if err != nil { + os.RemoveAll(basedir) + } + return errors.Wrap(err, "failed to write dep tree") +} + +func (r solution) Projects() []LockedProject { + return r.p +} + +func (r solution) Attempts() int { + return r.att +} + +func (r solution) InputsDigest() []byte { + return r.hd +} + +func (r solution) AnalyzerName() string { + return r.analyzerInfo.Name +} + +func (r solution) AnalyzerVersion() int { + return r.analyzerInfo.Version +} + +func (r solution) SolverName() string { + return r.solv.Name() +} + +func (r solution) SolverVersion() int { + return r.solv.Version() +} diff --git a/vendor/github.com/golang/dep/gps/solution_test.go b/vendor/github.com/golang/dep/gps/solution_test.go new file mode 100644 index 00000000..2bb2ab42 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/solution_test.go @@ -0,0 +1,180 @@ +// Copyright 2017 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 gps + +import ( + "io/ioutil" + "log" + "os" + "path" + "path/filepath" + "runtime" + "testing" + + "github.com/golang/dep/internal/test" +) + +func discardLogger() *log.Logger { + return log.New(ioutil.Discard, "", 0) +} + +var basicResult solution + +func pi(n string) ProjectIdentifier { + return ProjectIdentifier{ + ProjectRoot: ProjectRoot(n), + } +} + +func init() { + basicResult = solution{ + att: 1, + p: []LockedProject{ + pa2lp(atom{ + id: pi("github.com/sdboyer/testrepo"), + v: NewBranch("master").Pair(Revision("4d59fb584b15a94d7401e356d2875c472d76ef45")), + }, nil), + pa2lp(atom{ + id: pi("github.com/Masterminds/VCSTestRepo"), + v: NewVersion("1.0.0").Pair(Revision("30605f6ac35fcb075ad0bfa9296f90a7d891523e")), + }, nil), + }, + } + basicResult.analyzerInfo = (naiveAnalyzer{}).Info() + + // Just in case something needs punishing, kubernetes offers a complex, + // real-world set of dependencies, and this revision is known to work. + /* + _ = atom{ + id: pi("github.com/kubernetes/kubernetes"), + v: NewVersion("1.0.0").Pair(Revision("528f879e7d3790ea4287687ef0ab3f2a01cc2718")), + } + */ +} + +func testWriteDepTree(t *testing.T) { + t.Parallel() + + // This test is a bit slow, skip it on -short + if testing.Short() { + t.Skip("Skipping dep tree writing test in short mode") + } + requiresBins(t, "git", "hg", "bzr") + + tmp, err := ioutil.TempDir("", "writetree") + if err != nil { + t.Fatalf("Failed to create temp dir: %s", err) + } + defer os.RemoveAll(tmp) + + // bzr appears to not be consistent across...versions? platforms? (who + // knows) with respect to its internal object identifiers. This has tanked + // our Windows tests, because it's sniffing for this one revision, but the + // rev is reported differently on some Windows versions, with some versions + // of bzr. It's especially vexing because these tests worked fine for years, + // then abruptly broke for no obvious reason. + var bzrv Version = NewVersion("1.0.0") + if runtime.GOOS != "windows" { + bzrv = bzrv.(semVersion).Pair(Revision("matt@mattfarina.com-20150731135137-pbphasfppmygpl68")) + } + + r := solution{ + att: 1, + p: []LockedProject{ + pa2lp(atom{ + id: pi("github.com/sdboyer/testrepo"), + v: NewBranch("master").Pair(Revision("4d59fb584b15a94d7401e356d2875c472d76ef45")), + }, nil), + pa2lp(atom{ + id: pi("launchpad.net/govcstestbzrrepo"), + v: bzrv, + }, nil), + pa2lp(atom{ + id: pi("bitbucket.org/sdboyer/withbm"), + v: NewVersion("v1.0.0").Pair(Revision("aa110802a0c64195d0a6c375c9f66668827c90b4")), + }, nil), + }, + } + + sm, clean := mkNaiveSM(t) + defer clean() + + // Trigger simultaneous fetch of all three to speed up test execution time + for _, p := range r.p { + go func(pi ProjectIdentifier) { + sm.SyncSourceFor(pi) + }(p.pi) + } + + // nil lock/result should err immediately + err = WriteDepTree(tmp, nil, sm, defaultCascadingPruneOptions(), discardLogger()) + if err == nil { + t.Errorf("Should error if nil lock is passed to WriteDepTree") + } + + err = WriteDepTree(tmp, r, sm, defaultCascadingPruneOptions(), discardLogger()) + if err != nil { + t.Errorf("Unexpected error while creating vendor tree: %s", err) + } + + if _, err = os.Stat(filepath.Join(tmp, "github.com", "sdboyer", "testrepo")); err != nil { + t.Errorf("Directory for github.com/sdboyer/testrepo does not exist") + } + if _, err = os.Stat(filepath.Join(tmp, "launchpad.net", "govcstestbzrrepo")); err != nil { + t.Errorf("Directory for launchpad.net/govcstestbzrrepo does not exist") + } + if _, err = os.Stat(filepath.Join(tmp, "bitbucket.org", "sdboyer", "withbm")); err != nil { + t.Errorf("Directory for bitbucket.org/sdboyer/withbm does not exist") + } +} + +func BenchmarkCreateVendorTree(b *testing.B) { + // We're fs-bound here, so restrict to single parallelism + b.SetParallelism(1) + + r := basicResult + tmp := path.Join(os.TempDir(), "vsolvtest") + + clean := true + sm, err := NewSourceManager(SourceManagerConfig{ + Cachedir: path.Join(tmp, "cache"), + Logger: log.New(test.Writer{TB: b}, "", 0), + }) + if err != nil { + b.Errorf("failed to create SourceManager: %q", err) + clean = false + } + + // Prefetch the projects before timer starts + for _, lp := range r.p { + err := sm.SyncSourceFor(lp.Ident()) + if err != nil { + b.Errorf("failed getting project info during prefetch: %s", err) + clean = false + } + } + + if clean { + logger := discardLogger() + b.ResetTimer() + b.StopTimer() + exp := path.Join(tmp, "export") + for i := 0; i < b.N; i++ { + // Order the loop this way to make it easy to disable final cleanup, to + // ease manual inspection + os.RemoveAll(exp) + b.StartTimer() + err = WriteDepTree(exp, r, sm, defaultCascadingPruneOptions(), logger) + b.StopTimer() + if err != nil { + b.Errorf("unexpected error after %v iterations: %s", i, err) + break + } + } + } + + sm.Release() + os.RemoveAll(tmp) // comment this to leave temp dir behind for inspection +} diff --git a/vendor/github.com/golang/dep/gps/solve_basic_test.go b/vendor/github.com/golang/dep/gps/solve_basic_test.go new file mode 100644 index 00000000..910b9d62 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/solve_basic_test.go @@ -0,0 +1,1596 @@ +// Copyright 2017 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 gps + +import ( + "context" + "fmt" + "net/url" + "regexp" + "strings" + + "github.com/Masterminds/semver" + "github.com/golang/dep/gps/pkgtree" +) + +var regfrom = regexp.MustCompile(`^(\w*) from (\w*) ([0-9\.\*]*)`) + +// nvSplit splits an "info" string on " " into the pair of name and +// version/constraint, and returns each individually. +// +// This is for narrow use - panics if there are less than two resulting items in +// the slice. +func nvSplit(info string) (id ProjectIdentifier, version string) { + if strings.Contains(info, " from ") { + parts := regfrom.FindStringSubmatch(info) + info = parts[1] + " " + parts[3] + id.Source = parts[2] + } + + s := strings.SplitN(info, " ", 2) + if len(s) < 2 { + panic(fmt.Sprintf("Malformed name/version info string '%s'", info)) + } + + id.ProjectRoot, version = ProjectRoot(s[0]), s[1] + return +} + +// nvrSplit splits an "info" string on " " into the triplet of name, +// version/constraint, and revision, and returns each individually. +// +// It will work fine if only name and version/constraint are provided. +// +// This is for narrow use - panics if there are less than two resulting items in +// the slice. +func nvrSplit(info string) (id ProjectIdentifier, version string, revision Revision) { + if strings.Contains(info, " from ") { + parts := regfrom.FindStringSubmatch(info) + info = fmt.Sprintf("%s %s", parts[1], parts[3]) + id.Source = parts[2] + } + + s := strings.SplitN(info, " ", 3) + if len(s) < 2 { + panic(fmt.Sprintf("Malformed name/version info string '%s'", info)) + } + + id.ProjectRoot, version = ProjectRoot(s[0]), s[1] + + if len(s) == 3 { + revision = Revision(s[2]) + } + return +} + +// mkAtom splits the input string on a space, and uses the first two elements as +// the project identifier and version, respectively. +// +// The version segment may have a leading character indicating the type of +// version to create: +// +// p: create a "plain" (non-semver) version. +// b: create a branch version. +// r: create a revision. +// +// No prefix is assumed to indicate a semver version. +// +// If a third space-delimited element is provided, it will be interepreted as a +// revision, and used as the underlying version in a PairedVersion. No prefix +// should be provided in this case. It is an error (and will panic) to try to +// pass a revision with an underlying revision. +func mkAtom(info string) atom { + // if info is "root", special case it to use the root "version" + if info == "root" { + return atom{ + id: ProjectIdentifier{ + ProjectRoot: ProjectRoot("root"), + }, + v: rootRev, + } + } + + id, ver, rev := nvrSplit(info) + + var v Version + switch ver[0] { + case 'r': + if rev != "" { + panic("Cannot pair a revision with a revision") + } + v = Revision(ver[1:]) + case 'p': + v = NewVersion(ver[1:]) + case 'b': + v = NewBranch(ver[1:]) + default: + _, err := semver.NewVersion(ver) + if err != nil { + // don't want to allow bad test data at this level, so just panic + panic(fmt.Sprintf("Error when converting '%s' into semver: %s", ver, err)) + } + v = NewVersion(ver) + } + + if rev != "" { + v = v.(UnpairedVersion).Pair(rev) + } + + return atom{ + id: id, + v: v, + } +} + +// mkPCstrnt splits the input string on a space, and uses the first two elements +// as the project identifier and constraint body, respectively. +// +// The constraint body may have a leading character indicating the type of +// version to create: +// +// p: create a "plain" (non-semver) version. +// b: create a branch version. +// r: create a revision. +// +// If no leading character is used, a semver constraint is assumed. +func mkPCstrnt(info string) ProjectConstraint { + id, ver, rev := nvrSplit(info) + + var c Constraint + switch ver[0] { + case 'r': + c = Revision(ver[1:]) + case 'p': + c = NewVersion(ver[1:]) + case 'b': + c = NewBranch(ver[1:]) + default: + // Without one of those leading characters, we know it's a proper semver + // expression, so use the other parser that doesn't look for a rev + rev = "" + id, ver = nvSplit(info) + var err error + c, err = NewSemverConstraint(ver) + if err != nil { + // don't want bad test data at this level, so just panic + panic(fmt.Sprintf("Error when converting '%s' into semver constraint: %s (full info: %s)", ver, err, info)) + } + } + + // There's no practical reason that a real tool would need to produce a + // constraint that's a PairedVersion, but it is a possibility admitted by the + // system, so we at least allow for it in our testing harness. + if rev != "" { + // Of course, this *will* panic if the predicate is a revision or a + // semver constraint, neither of which implement UnpairedVersion. This + // is as intended, to prevent bad data from entering the system. + c = c.(UnpairedVersion).Pair(rev) + } + + return ProjectConstraint{ + Ident: id, + Constraint: c, + } +} + +// mkCDep composes a completeDep struct from the inputs. +// +// The only real work here is passing the initial string to mkPDep. All the +// other args are taken as package names. +func mkCDep(pdep string, pl ...string) completeDep { + pc := mkPCstrnt(pdep) + return completeDep{ + workingConstraint: workingConstraint{ + Ident: pc.Ident, + Constraint: pc.Constraint, + }, + pl: pl, + } +} + +// A depspec is a fixture representing all the information a SourceManager would +// ordinarily glean directly from interrogating a repository. +type depspec struct { + n ProjectRoot + v Version + deps []ProjectConstraint + pkgs []tpkg +} + +// mkDepspec creates a depspec by processing a series of strings, each of which +// contains an identiifer and version information. +// +// The first string is broken out into the name and version of the package being +// described - see the docs on mkAtom for details. subsequent strings are +// interpreted as dep constraints of that dep at that version. See the docs on +// mkPDep for details. +func mkDepspec(pi string, deps ...string) depspec { + pa := mkAtom(pi) + if string(pa.id.ProjectRoot) != pa.id.Source && pa.id.Source != "" { + panic("alternate source on self makes no sense") + } + + ds := depspec{ + n: pa.id.ProjectRoot, + v: pa.v, + } + + for _, dep := range deps { + ds.deps = append(ds.deps, mkPCstrnt(dep)) + } + + return ds +} + +func mkDep(atom, pdep string, pl ...string) dependency { + return dependency{ + depender: mkAtom(atom), + dep: mkCDep(pdep, pl...), + } +} + +func mkADep(atom, pdep string, c Constraint, pl ...string) dependency { + return dependency{ + depender: mkAtom(atom), + dep: completeDep{ + workingConstraint: workingConstraint{ + Ident: ProjectIdentifier{ + ProjectRoot: ProjectRoot(pdep), + }, + Constraint: c, + }, + pl: pl, + }, + } +} + +// mkPI creates a ProjectIdentifier with the ProjectRoot as the provided +// string, and the Source unset. +// +// Call normalize() on the returned value if you need the Source to be be +// equal to the ProjectRoot. +func mkPI(root string) ProjectIdentifier { + return ProjectIdentifier{ + ProjectRoot: ProjectRoot(root), + } +} + +// mkSVC creates a new semver constraint, panicking if an error is returned. +func mkSVC(body string) Constraint { + c, err := NewSemverConstraint(body) + if err != nil { + panic(fmt.Sprintf("Error while trying to create semver constraint from %s: %s", body, err.Error())) + } + return c +} + +// mklock makes a fixLock, suitable to act as a lock file +func mklock(pairs ...string) fixLock { + l := make(fixLock, 0) + for _, s := range pairs { + pa := mkAtom(s) + l = append(l, NewLockedProject(pa.id, pa.v, nil)) + } + + return l +} + +// mkrevlock makes a fixLock, suitable to act as a lock file, with only a name +// and a rev +func mkrevlock(pairs ...string) fixLock { + l := make(fixLock, 0) + for _, s := range pairs { + pa := mkAtom(s) + l = append(l, NewLockedProject(pa.id, pa.v.(PairedVersion).Revision(), nil)) + } + + return l +} + +// mksolution creates a map of project identifiers to their LockedProject +// result, which is sufficient to act as a solution fixture for the purposes of +// most tests. +// +// Either strings or LockedProjects can be provided. If a string is provided, it +// is assumed that we're in the default, "basic" case where there is exactly one +// package in a project, and it is the root of the project - meaning that only +// the "." package should be listed. If a LockedProject is provided (e.g. as +// returned from mklp()), then it's incorporated directly. +// +// If any other type is provided, the func will panic. +func mksolution(inputs ...interface{}) map[ProjectIdentifier]LockedProject { + m := make(map[ProjectIdentifier]LockedProject) + for _, in := range inputs { + switch t := in.(type) { + case string: + a := mkAtom(t) + m[a.id] = NewLockedProject(a.id, a.v, []string{"."}) + case LockedProject: + m[t.pi] = t + default: + panic(fmt.Sprintf("unexpected input to mksolution: %T %s", in, in)) + } + } + + return m +} + +// mklp creates a LockedProject from string inputs +func mklp(pair string, pkgs ...string) LockedProject { + a := mkAtom(pair) + return NewLockedProject(a.id, a.v, pkgs) +} + +// computeBasicReachMap takes a depspec and computes a reach map which is +// identical to the explicit depgraph. +// +// Using a reachMap here is overkill for what the basic fixtures actually need, +// but we use it anyway for congruence with the more general cases. +func computeBasicReachMap(ds []depspec) reachMap { + rm := make(reachMap) + + for k, d := range ds { + n := string(d.n) + lm := map[string][]string{ + n: nil, + } + v := d.v + if k == 0 { + // Put the root in with a nil rev, to accommodate the solver + v = nil + } + rm[pident{n: d.n, v: v}] = lm + + for _, dep := range d.deps { + lm[n] = append(lm[n], string(dep.Ident.ProjectRoot)) + } + } + + return rm +} + +type pident struct { + n ProjectRoot + v Version +} + +type specfix interface { + name() string + rootmanifest() RootManifest + rootTree() pkgtree.PackageTree + specs() []depspec + maxTries() int + solution() map[ProjectIdentifier]LockedProject + failure() error +} + +// A basicFixture is a declarative test fixture that can cover a wide variety of +// solver cases. All cases, however, maintain one invariant: package == project. +// There are no subpackages, and so it is impossible for them to trigger or +// require bimodal solving. +// +// This type is separate from bimodalFixture in part for legacy reasons - many +// of these were adapted from similar tests in dart's pub lib, where there is no +// such thing as "bimodal solving". +// +// But it's also useful to keep them separate because bimodal solving involves +// considerably more complexity than simple solving, both in terms of fixture +// declaration and actual solving mechanics. Thus, we gain a lot of value for +// contributors and maintainers by keeping comprehension costs relatively low +// while still covering important cases. +type basicFixture struct { + // name of this fixture datum + n string + // depspecs. always treat first as root + ds []depspec + // results; map of name/atom pairs + r map[ProjectIdentifier]LockedProject + // max attempts the solver should need to find solution. 0 means no limit + maxAttempts int + // Use downgrade instead of default upgrade sorter + downgrade bool + // lock file simulator, if one's to be used at all + l fixLock + // solve failure expected, if any + fail error + // overrides, if any + ovr ProjectConstraints + // request up/downgrade to all projects + changeall bool + // individual projects to change + changelist []ProjectRoot + // if the fixture is currently broken/expected to fail, this has a message + // recording why + broken string +} + +func (f basicFixture) name() string { + return f.n +} + +func (f basicFixture) specs() []depspec { + return f.ds +} + +func (f basicFixture) maxTries() int { + return f.maxAttempts +} + +func (f basicFixture) solution() map[ProjectIdentifier]LockedProject { + return f.r +} + +func (f basicFixture) rootmanifest() RootManifest { + return simpleRootManifest{ + c: pcSliceToMap(f.ds[0].deps), + ovr: f.ovr, + } +} + +func (f basicFixture) rootTree() pkgtree.PackageTree { + var imp []string + for _, dep := range f.ds[0].deps { + imp = append(imp, string(dep.Ident.ProjectRoot)) + } + + n := string(f.ds[0].n) + pt := pkgtree.PackageTree{ + ImportRoot: n, + Packages: map[string]pkgtree.PackageOrErr{ + string(n): { + P: pkgtree.Package{ + ImportPath: n, + Name: n, + Imports: imp, + }, + }, + }, + } + + return pt +} + +func (f basicFixture) failure() error { + return f.fail +} + +// A table of basicFixtures, used in the basic solving test set. +var basicFixtures = map[string]basicFixture{ + // basic fixtures + "no dependencies": { + ds: []depspec{ + mkDepspec("root 0.0.0"), + }, + r: mksolution(), + }, + "simple dependency tree": { + ds: []depspec{ + mkDepspec("root 0.0.0", "a 1.0.0", "b 1.0.0"), + mkDepspec("a 1.0.0", "aa 1.0.0", "ab 1.0.0"), + mkDepspec("aa 1.0.0"), + mkDepspec("ab 1.0.0"), + mkDepspec("b 1.0.0", "ba 1.0.0", "bb 1.0.0"), + mkDepspec("ba 1.0.0"), + mkDepspec("bb 1.0.0"), + }, + r: mksolution( + "a 1.0.0", + "aa 1.0.0", + "ab 1.0.0", + "b 1.0.0", + "ba 1.0.0", + "bb 1.0.0", + ), + }, + "shared dependency with overlapping constraints": { + ds: []depspec{ + mkDepspec("root 0.0.0", "a 1.0.0", "b 1.0.0"), + mkDepspec("a 1.0.0", "shared >=2.0.0, <4.0.0"), + mkDepspec("b 1.0.0", "shared >=3.0.0, <5.0.0"), + mkDepspec("shared 2.0.0"), + mkDepspec("shared 3.0.0"), + mkDepspec("shared 3.6.9"), + mkDepspec("shared 4.0.0"), + mkDepspec("shared 5.0.0"), + }, + r: mksolution( + "a 1.0.0", + "b 1.0.0", + "shared 3.6.9", + ), + }, + "downgrade on overlapping constraints": { + ds: []depspec{ + mkDepspec("root 0.0.0", "a 1.0.0", "b 1.0.0"), + mkDepspec("a 1.0.0", "shared >=2.0.0, <=4.0.0"), + mkDepspec("b 1.0.0", "shared >=3.0.0, <5.0.0"), + mkDepspec("shared 2.0.0"), + mkDepspec("shared 3.0.0"), + mkDepspec("shared 3.6.9"), + mkDepspec("shared 4.0.0"), + mkDepspec("shared 5.0.0"), + }, + r: mksolution( + "a 1.0.0", + "b 1.0.0", + "shared 3.0.0", + ), + downgrade: true, + }, + "shared dependency where dependent version in turn affects other dependencies": { + ds: []depspec{ + mkDepspec("root 0.0.0", "foo <=1.0.2", "bar 1.0.0"), + mkDepspec("foo 1.0.0"), + mkDepspec("foo 1.0.1", "bang 1.0.0"), + mkDepspec("foo 1.0.2", "whoop 1.0.0"), + mkDepspec("foo 1.0.3", "zoop 1.0.0"), + mkDepspec("bar 1.0.0", "foo <=1.0.1"), + mkDepspec("bang 1.0.0"), + mkDepspec("whoop 1.0.0"), + mkDepspec("zoop 1.0.0"), + }, + r: mksolution( + "foo 1.0.1", + "bar 1.0.0", + "bang 1.0.0", + ), + }, + "removed dependency": { + ds: []depspec{ + mkDepspec("root 1.0.0", "foo 1.0.0", "bar *"), + mkDepspec("foo 1.0.0"), + mkDepspec("foo 2.0.0"), + mkDepspec("bar 1.0.0"), + mkDepspec("bar 2.0.0", "baz 1.0.0"), + mkDepspec("baz 1.0.0", "foo 2.0.0"), + }, + r: mksolution( + "foo 1.0.0", + "bar 1.0.0", + ), + maxAttempts: 2, + }, + // fixtures with locks + "with compatible locked dependency": { + ds: []depspec{ + mkDepspec("root 0.0.0", "foo *"), + mkDepspec("foo 1.0.0", "bar 1.0.0"), + mkDepspec("foo 1.0.1", "bar 1.0.1"), + mkDepspec("foo 1.0.2", "bar 1.0.2"), + mkDepspec("bar 1.0.0"), + mkDepspec("bar 1.0.1"), + mkDepspec("bar 1.0.2"), + }, + l: mklock( + "foo 1.0.1", + ), + r: mksolution( + "foo 1.0.1", + "bar 1.0.1", + ), + }, + "upgrade through lock": { + ds: []depspec{ + mkDepspec("root 0.0.0", "foo *"), + mkDepspec("foo 1.0.0", "bar 1.0.0"), + mkDepspec("foo 1.0.1", "bar 1.0.1"), + mkDepspec("foo 1.0.2", "bar 1.0.2"), + mkDepspec("bar 1.0.0"), + mkDepspec("bar 1.0.1"), + mkDepspec("bar 1.0.2"), + }, + l: mklock( + "foo 1.0.1", + ), + r: mksolution( + "foo 1.0.2", + "bar 1.0.2", + ), + changeall: true, + }, + "downgrade through lock": { + ds: []depspec{ + mkDepspec("root 0.0.0", "foo *"), + mkDepspec("foo 1.0.0", "bar 1.0.0"), + mkDepspec("foo 1.0.1", "bar 1.0.1"), + mkDepspec("foo 1.0.2", "bar 1.0.2"), + mkDepspec("bar 1.0.0"), + mkDepspec("bar 1.0.1"), + mkDepspec("bar 1.0.2"), + }, + l: mklock( + "foo 1.0.1", + ), + r: mksolution( + "foo 1.0.0", + "bar 1.0.0", + ), + changeall: true, + downgrade: true, + }, + "update one with only one": { + ds: []depspec{ + mkDepspec("root 0.0.0", "foo *"), + mkDepspec("foo 1.0.0"), + mkDepspec("foo 1.0.1"), + mkDepspec("foo 1.0.2"), + }, + l: mklock( + "foo 1.0.1", + ), + r: mksolution( + "foo 1.0.2", + ), + changelist: []ProjectRoot{"foo"}, + }, + "update one of multi": { + ds: []depspec{ + mkDepspec("root 0.0.0", "foo *", "bar *"), + mkDepspec("foo 1.0.0"), + mkDepspec("foo 1.0.1"), + mkDepspec("foo 1.0.2"), + mkDepspec("bar 1.0.0"), + mkDepspec("bar 1.0.1"), + mkDepspec("bar 1.0.2"), + }, + l: mklock( + "foo 1.0.1", + "bar 1.0.1", + ), + r: mksolution( + "foo 1.0.2", + "bar 1.0.1", + ), + changelist: []ProjectRoot{"foo"}, + }, + "update both of multi": { + ds: []depspec{ + mkDepspec("root 0.0.0", "foo *", "bar *"), + mkDepspec("foo 1.0.0"), + mkDepspec("foo 1.0.1"), + mkDepspec("foo 1.0.2"), + mkDepspec("bar 1.0.0"), + mkDepspec("bar 1.0.1"), + mkDepspec("bar 1.0.2"), + }, + l: mklock( + "foo 1.0.1", + "bar 1.0.1", + ), + r: mksolution( + "foo 1.0.2", + "bar 1.0.2", + ), + changelist: []ProjectRoot{"foo", "bar"}, + }, + "update two of more": { + ds: []depspec{ + mkDepspec("root 0.0.0", "foo *", "bar *", "baz *"), + mkDepspec("foo 1.0.0"), + mkDepspec("foo 1.0.1"), + mkDepspec("foo 1.0.2"), + mkDepspec("bar 1.0.0"), + mkDepspec("bar 1.0.1"), + mkDepspec("bar 1.0.2"), + mkDepspec("baz 1.0.0"), + mkDepspec("baz 1.0.1"), + mkDepspec("baz 1.0.2"), + }, + l: mklock( + "foo 1.0.1", + "bar 1.0.1", + "baz 1.0.1", + ), + r: mksolution( + "foo 1.0.2", + "bar 1.0.2", + "baz 1.0.1", + ), + changelist: []ProjectRoot{"foo", "bar"}, + }, + "break other lock with targeted update": { + ds: []depspec{ + mkDepspec("root 0.0.0", "foo *", "baz *"), + mkDepspec("foo 1.0.0", "bar 1.0.0"), + mkDepspec("foo 1.0.1", "bar 1.0.1"), + mkDepspec("foo 1.0.2", "bar 1.0.2"), + mkDepspec("bar 1.0.0"), + mkDepspec("bar 1.0.1"), + mkDepspec("bar 1.0.2"), + mkDepspec("baz 1.0.0"), + mkDepspec("baz 1.0.1"), + mkDepspec("baz 1.0.2"), + }, + l: mklock( + "foo 1.0.1", + "bar 1.0.1", + "baz 1.0.1", + ), + r: mksolution( + "foo 1.0.2", + "bar 1.0.2", + "baz 1.0.1", + ), + changelist: []ProjectRoot{"foo", "bar"}, + }, + "with incompatible locked dependency": { + ds: []depspec{ + mkDepspec("root 0.0.0", "foo >1.0.1"), + mkDepspec("foo 1.0.0", "bar 1.0.0"), + mkDepspec("foo 1.0.1", "bar 1.0.1"), + mkDepspec("foo 1.0.2", "bar 1.0.2"), + mkDepspec("bar 1.0.0"), + mkDepspec("bar 1.0.1"), + mkDepspec("bar 1.0.2"), + }, + l: mklock( + "foo 1.0.1", + ), + r: mksolution( + "foo 1.0.2", + "bar 1.0.2", + ), + }, + "with unrelated locked dependency": { + ds: []depspec{ + mkDepspec("root 0.0.0", "foo *"), + mkDepspec("foo 1.0.0", "bar 1.0.0"), + mkDepspec("foo 1.0.1", "bar 1.0.1"), + mkDepspec("foo 1.0.2", "bar 1.0.2"), + mkDepspec("bar 1.0.0"), + mkDepspec("bar 1.0.1"), + mkDepspec("bar 1.0.2"), + mkDepspec("baz 1.0.0 bazrev"), + }, + l: mklock( + "baz 1.0.0 bazrev", + ), + r: mksolution( + "foo 1.0.2", + "bar 1.0.2", + ), + }, + "unlocks dependencies if necessary to ensure that a new dependency is satisfied": { + ds: []depspec{ + mkDepspec("root 0.0.0", "foo *", "newdep *"), + mkDepspec("foo 1.0.0 foorev", "bar <2.0.0"), + mkDepspec("bar 1.0.0 barrev", "baz <2.0.0"), + mkDepspec("baz 1.0.0 bazrev", "qux <2.0.0"), + mkDepspec("qux 1.0.0 quxrev"), + mkDepspec("foo 2.0.0", "bar <3.0.0"), + mkDepspec("bar 2.0.0", "baz <3.0.0"), + mkDepspec("baz 2.0.0", "qux <3.0.0"), + mkDepspec("qux 2.0.0"), + mkDepspec("newdep 2.0.0", "baz >=1.5.0"), + }, + l: mklock( + "foo 1.0.0 foorev", + "bar 1.0.0 barrev", + "baz 1.0.0 bazrev", + "qux 1.0.0 quxrev", + ), + r: mksolution( + "foo 2.0.0", + "bar 2.0.0", + "baz 2.0.0", + "qux 1.0.0 quxrev", + "newdep 2.0.0", + ), + maxAttempts: 4, + }, + "break lock when only the deps necessitate it": { + ds: []depspec{ + mkDepspec("root 0.0.0", "foo *", "bar *"), + mkDepspec("foo 1.0.0 foorev", "bar <2.0.0"), + mkDepspec("foo 2.0.0", "bar <3.0.0"), + mkDepspec("bar 2.0.0", "baz <3.0.0"), + mkDepspec("baz 2.0.0", "foo >1.0.0"), + }, + l: mklock( + "foo 1.0.0 foorev", + ), + r: mksolution( + "foo 2.0.0", + "bar 2.0.0", + "baz 2.0.0", + ), + maxAttempts: 4, + }, + "locked atoms are matched on both local and net name": { + ds: []depspec{ + mkDepspec("root 0.0.0", "foo *"), + mkDepspec("foo 1.0.0 foorev"), + mkDepspec("foo 2.0.0 foorev2"), + }, + l: mklock( + "foo from baz 1.0.0 foorev", + ), + r: mksolution( + "foo 2.0.0 foorev2", + ), + }, + "pairs bare revs in lock with versions": { + ds: []depspec{ + mkDepspec("root 0.0.0", "foo ~1.0.1"), + mkDepspec("foo 1.0.0", "bar 1.0.0"), + mkDepspec("foo 1.0.1 foorev", "bar 1.0.1"), + mkDepspec("foo 1.0.2", "bar 1.0.2"), + mkDepspec("bar 1.0.0"), + mkDepspec("bar 1.0.1"), + mkDepspec("bar 1.0.2"), + }, + l: mkrevlock( + "foo 1.0.1 foorev", // mkrevlock drops the 1.0.1 + ), + r: mksolution( + "foo 1.0.1 foorev", + "bar 1.0.1", + ), + }, + // This fixture describes a situation that should be impossible with a + // real-world VCS (contents of dep at same rev are different, as indicated + // by different constraints on bar). But, that's not the SUT here, so it's + // OK. + "pairs bare revs in lock with all versions": { + ds: []depspec{ + mkDepspec("root 0.0.0", "foo ~1.0.1"), + mkDepspec("foo 1.0.0", "bar 1.0.0"), + mkDepspec("foo 1.0.1 foorev", "bar 1.0.1"), + mkDepspec("foo 1.0.2 foorev", "bar 1.0.2"), + mkDepspec("bar 1.0.0"), + mkDepspec("bar 1.0.1"), + mkDepspec("bar 1.0.2"), + }, + l: mkrevlock( + "foo 1.0.1 foorev", // mkrevlock drops the 1.0.1 + ), + r: mksolution( + "foo 1.0.2 foorev", + "bar 1.0.2", + ), + }, + "does not pair bare revs in manifest with unpaired lock version": { + ds: []depspec{ + mkDepspec("root 0.0.0", "foo ~1.0.1"), + mkDepspec("foo 1.0.0", "bar 1.0.0"), + mkDepspec("foo 1.0.1 foorev", "bar 1.0.1"), + mkDepspec("foo 1.0.2", "bar 1.0.2"), + mkDepspec("bar 1.0.0"), + mkDepspec("bar 1.0.1"), + mkDepspec("bar 1.0.2"), + }, + l: mkrevlock( + "foo 1.0.1 foorev", // mkrevlock drops the 1.0.1 + ), + r: mksolution( + "foo 1.0.1 foorev", + "bar 1.0.1", + ), + }, + "lock to branch on old rev keeps old rev": { + ds: []depspec{ + mkDepspec("root 0.0.0", "foo bmaster"), + mkDepspec("foo bmaster newrev"), + }, + l: mklock( + "foo bmaster oldrev", + ), + r: mksolution( + "foo bmaster oldrev", + ), + }, + // Whereas this is a normal situation for a branch, when it occurs for a + // tag, it means someone's been naughty upstream. Still, though, the outcome + // is the same. + // + // TODO(sdboyer) this needs to generate a warning, once we start doing that + "lock to now-moved tag on old rev keeps old rev": { + ds: []depspec{ + mkDepspec("root 0.0.0", "foo ptaggerino"), + mkDepspec("foo ptaggerino newrev"), + }, + l: mklock( + "foo ptaggerino oldrev", + ), + r: mksolution( + "foo ptaggerino oldrev", + ), + }, + "no version that matches requirement": { + ds: []depspec{ + mkDepspec("root 0.0.0", "foo ^1.0.0"), + mkDepspec("foo 2.0.0"), + mkDepspec("foo 2.1.3"), + }, + fail: &noVersionError{ + pn: mkPI("foo"), + fails: []failedVersion{ + { + v: NewVersion("2.1.3"), + f: &versionNotAllowedFailure{ + goal: mkAtom("foo 2.1.3"), + failparent: []dependency{mkDep("root", "foo ^1.0.0", "foo")}, + c: mkSVC("^1.0.0"), + }, + }, + { + v: NewVersion("2.0.0"), + f: &versionNotAllowedFailure{ + goal: mkAtom("foo 2.0.0"), + failparent: []dependency{mkDep("root", "foo ^1.0.0", "foo")}, + c: mkSVC("^1.0.0"), + }, + }, + }, + }, + }, + "no version that matches combined constraint": { + ds: []depspec{ + mkDepspec("root 0.0.0", "foo 1.0.0", "bar 1.0.0"), + mkDepspec("foo 1.0.0", "shared >=2.0.0, <3.0.0"), + mkDepspec("bar 1.0.0", "shared >=2.9.0, <4.0.0"), + mkDepspec("shared 2.5.0"), + mkDepspec("shared 3.5.0"), + }, + fail: &noVersionError{ + pn: mkPI("shared"), + fails: []failedVersion{ + { + v: NewVersion("3.5.0"), + f: &versionNotAllowedFailure{ + goal: mkAtom("shared 3.5.0"), + failparent: []dependency{mkDep("foo 1.0.0", "shared >=2.0.0, <3.0.0", "shared")}, + c: mkSVC(">=2.9.0, <3.0.0"), + }, + }, + { + v: NewVersion("2.5.0"), + f: &versionNotAllowedFailure{ + goal: mkAtom("shared 2.5.0"), + failparent: []dependency{mkDep("bar 1.0.0", "shared >=2.9.0, <4.0.0", "shared")}, + c: mkSVC(">=2.9.0, <3.0.0"), + }, + }, + }, + }, + }, + "disjoint constraints": { + ds: []depspec{ + mkDepspec("root 0.0.0", "foo 1.0.0", "bar 1.0.0"), + mkDepspec("foo 1.0.0", "shared <=2.0.0"), + mkDepspec("bar 1.0.0", "shared >3.0.0"), + mkDepspec("shared 2.0.0"), + mkDepspec("shared 4.0.0"), + }, + fail: &noVersionError{ + pn: mkPI("foo"), + fails: []failedVersion{ + { + v: NewVersion("1.0.0"), + f: &disjointConstraintFailure{ + goal: mkDep("foo 1.0.0", "shared <=2.0.0", "shared"), + failsib: []dependency{mkDep("bar 1.0.0", "shared >3.0.0", "shared")}, + nofailsib: nil, + c: mkSVC(">3.0.0"), + }, + }, + }, + }, + }, + "no valid solution": { + ds: []depspec{ + mkDepspec("root 0.0.0", "a *", "b *"), + mkDepspec("a 1.0.0", "b 1.0.0"), + mkDepspec("a 2.0.0", "b 2.0.0"), + mkDepspec("b 1.0.0", "a 2.0.0"), + mkDepspec("b 2.0.0", "a 1.0.0"), + }, + fail: &noVersionError{ + pn: mkPI("b"), + fails: []failedVersion{ + { + v: NewVersion("2.0.0"), + f: &versionNotAllowedFailure{ + goal: mkAtom("b 2.0.0"), + failparent: []dependency{mkDep("a 1.0.0", "b 1.0.0", "b")}, + c: mkSVC("1.0.0"), + }, + }, + { + v: NewVersion("1.0.0"), + f: &constraintNotAllowedFailure{ + goal: mkDep("b 1.0.0", "a 2.0.0", "a"), + v: NewVersion("1.0.0"), + }, + }, + }, + }, + }, + "no version that matches while backtracking": { + ds: []depspec{ + mkDepspec("root 0.0.0", "a *", "b >1.0.0"), + mkDepspec("a 1.0.0"), + mkDepspec("b 1.0.0"), + }, + fail: &noVersionError{ + pn: mkPI("b"), + fails: []failedVersion{ + { + v: NewVersion("1.0.0"), + f: &versionNotAllowedFailure{ + goal: mkAtom("b 1.0.0"), + failparent: []dependency{mkDep("root", "b >1.0.0", "b")}, + c: mkSVC(">1.0.0"), + }, + }, + }, + }, + }, + // The latest versions of a and b disagree on c. An older version of either + // will resolve the problem. This test validates that b, which is farther + // in the dependency graph from myapp is downgraded first. + "rolls back leaf versions first": { + ds: []depspec{ + mkDepspec("root 0.0.0", "a *"), + mkDepspec("a 1.0.0", "b *"), + mkDepspec("a 2.0.0", "b *", "c 2.0.0"), + mkDepspec("b 1.0.0"), + mkDepspec("b 2.0.0", "c 1.0.0"), + mkDepspec("c 1.0.0"), + mkDepspec("c 2.0.0"), + }, + r: mksolution( + "a 2.0.0", + "b 1.0.0", + "c 2.0.0", + ), + maxAttempts: 2, + }, + // Only one version of baz, so foo and bar will have to downgrade until they + // reach it. + "mutual downgrading": { + ds: []depspec{ + mkDepspec("root 0.0.0", "foo *"), + mkDepspec("foo 1.0.0", "bar 1.0.0"), + mkDepspec("foo 2.0.0", "bar 2.0.0"), + mkDepspec("foo 3.0.0", "bar 3.0.0"), + mkDepspec("bar 1.0.0", "baz *"), + mkDepspec("bar 2.0.0", "baz 2.0.0"), + mkDepspec("bar 3.0.0", "baz 3.0.0"), + mkDepspec("baz 1.0.0"), + }, + r: mksolution( + "foo 1.0.0", + "bar 1.0.0", + "baz 1.0.0", + ), + maxAttempts: 3, + }, + // Ensures the solver doesn't exhaustively search all versions of b when + // it's a-2.0.0 whose dependency on c-2.0.0-nonexistent led to the + // problem. We make sure b has more versions than a so that the solver + // tries a first since it sorts sibling dependencies by number of + // versions. + "search real failer": { + ds: []depspec{ + mkDepspec("root 0.0.0", "a *", "b *"), + mkDepspec("a 1.0.0", "c 1.0.0"), + mkDepspec("a 2.0.0", "c 2.0.0"), + mkDepspec("b 1.0.0"), + mkDepspec("b 2.0.0"), + mkDepspec("b 3.0.0"), + mkDepspec("c 1.0.0"), + }, + r: mksolution( + "a 1.0.0", + "b 3.0.0", + "c 1.0.0", + ), + maxAttempts: 2, + }, + // Dependencies are ordered so that packages with fewer versions are tried + // first. Here, there are two valid solutions (either a or b must be + // downgraded once). The chosen one depends on which dep is traversed first. + // Since b has fewer versions, it will be traversed first, which means a + // will come later. Since later selections are revised first, a gets + // downgraded. + "traverse into package with fewer versions first": { + ds: []depspec{ + mkDepspec("root 0.0.0", "a *", "b *"), + mkDepspec("a 1.0.0", "c *"), + mkDepspec("a 2.0.0", "c *"), + mkDepspec("a 3.0.0", "c *"), + mkDepspec("a 4.0.0", "c *"), + mkDepspec("a 5.0.0", "c 1.0.0"), + mkDepspec("b 1.0.0", "c *"), + mkDepspec("b 2.0.0", "c *"), + mkDepspec("b 3.0.0", "c *"), + mkDepspec("b 4.0.0", "c 2.0.0"), + mkDepspec("c 1.0.0"), + mkDepspec("c 2.0.0"), + }, + r: mksolution( + "a 4.0.0", + "b 4.0.0", + "c 2.0.0", + ), + maxAttempts: 2, + }, + // This is similar to the preceding fixture. When getting the number of + // versions of a package to determine which to traverse first, versions that + // are disallowed by the root package's constraints should not be + // considered. Here, foo has more versions than bar in total (4), but fewer + // that meet myapp"s constraints (only 2). There is no solution, but we will + // do less backtracking if foo is tested first. + "root constraints pre-eliminate versions": { + ds: []depspec{ + mkDepspec("root 0.0.0", "foo *", "bar *"), + mkDepspec("foo 1.0.0", "none 2.0.0"), + mkDepspec("foo 2.0.0", "none 2.0.0"), + mkDepspec("foo 3.0.0", "none 2.0.0"), + mkDepspec("foo 4.0.0", "none 2.0.0"), + mkDepspec("bar 1.0.0"), + mkDepspec("bar 2.0.0"), + mkDepspec("bar 3.0.0"), + mkDepspec("none 1.0.0"), + }, + fail: &noVersionError{ + pn: mkPI("none"), + fails: []failedVersion{ + { + v: NewVersion("1.0.0"), + f: &versionNotAllowedFailure{ + goal: mkAtom("none 1.0.0"), + failparent: []dependency{mkDep("foo 1.0.0", "none 2.0.0", "none")}, + c: mkSVC("2.0.0"), + }, + }, + }, + }, + }, + // If there"s a disjoint constraint on a package, then selecting other + // versions of it is a waste of time: no possible versions can match. We + // need to jump past it to the most recent package that affected the + // constraint. + "backjump past failed package on disjoint constraint": { + ds: []depspec{ + mkDepspec("root 0.0.0", "a *", "foo *"), + mkDepspec("a 1.0.0", "foo *"), + mkDepspec("a 2.0.0", "foo <1.0.0"), + mkDepspec("foo 2.0.0"), + mkDepspec("foo 2.0.1"), + mkDepspec("foo 2.0.2"), + mkDepspec("foo 2.0.3"), + mkDepspec("foo 2.0.4"), + mkDepspec("none 1.0.0"), + }, + r: mksolution( + "a 1.0.0", + "foo 2.0.4", + ), + maxAttempts: 2, + }, + // Revision enters vqueue if a dep has a constraint on that revision + "revision injected into vqueue": { + ds: []depspec{ + mkDepspec("root 0.0.0", "foo r123abc"), + mkDepspec("foo r123abc"), + mkDepspec("foo 1.0.0 foorev"), + mkDepspec("foo 2.0.0 foorev2"), + }, + r: mksolution( + "foo r123abc", + ), + }, + // Some basic override checks + "override root's own constraint": { + ds: []depspec{ + mkDepspec("root 0.0.0", "a *", "b *"), + mkDepspec("a 1.0.0", "b 1.0.0"), + mkDepspec("a 2.0.0", "b 1.0.0"), + mkDepspec("b 1.0.0"), + }, + ovr: ProjectConstraints{ + ProjectRoot("a"): ProjectProperties{ + Constraint: NewVersion("1.0.0"), + }, + }, + r: mksolution( + "a 1.0.0", + "b 1.0.0", + ), + }, + "override dep's constraint": { + ds: []depspec{ + mkDepspec("root 0.0.0", "a *"), + mkDepspec("a 1.0.0", "b 1.0.0"), + mkDepspec("a 2.0.0", "b 1.0.0"), + mkDepspec("b 1.0.0"), + mkDepspec("b 2.0.0"), + }, + ovr: ProjectConstraints{ + ProjectRoot("b"): ProjectProperties{ + Constraint: NewVersion("2.0.0"), + }, + }, + r: mksolution( + "a 2.0.0", + "b 2.0.0", + ), + }, + "overridden mismatched net addrs, alt in dep, back to default": { + ds: []depspec{ + mkDepspec("root 1.0.0", "foo 1.0.0", "bar 1.0.0"), + mkDepspec("foo 1.0.0", "bar from baz 1.0.0"), + mkDepspec("bar 1.0.0"), + }, + ovr: ProjectConstraints{ + ProjectRoot("bar"): ProjectProperties{ + Source: "bar", + }, + }, + r: mksolution( + "foo 1.0.0", + "bar from bar 1.0.0", + ), + }, + + // TODO(sdboyer) decide how to refactor the solver in order to re-enable these. + // Checking for revision existence is important...but kinda obnoxious. + //{ + //// Solve fails if revision constraint calls for a nonexistent revision + //n: "fail on missing revision", + //ds: []depspec{ + //mkDepspec("root 0.0.0", "bar *"), + //mkDepspec("bar 1.0.0", "foo r123abc"), + //mkDepspec("foo r123nomatch"), + //mkDepspec("foo 1.0.0"), + //mkDepspec("foo 2.0.0"), + //}, + //errp: []string{"bar", "foo", "bar"}, + //}, + //{ + //// Solve fails if revision constraint calls for a nonexistent revision, + //// even if rev constraint is specified by root + //n: "fail on missing revision from root", + //ds: []depspec{ + //mkDepspec("root 0.0.0", "foo r123nomatch"), + //mkDepspec("foo r123abc"), + //mkDepspec("foo 1.0.0"), + //mkDepspec("foo 2.0.0"), + //}, + //errp: []string{"foo", "root", "foo"}, + //}, + + // TODO(sdboyer) add fixture that tests proper handling of loops via aliases (where + // a project that wouldn't be a loop is aliased to a project that is a loop) +} + +func init() { + // This sets up a hundred versions of foo and bar, 0.0.0 through 9.9.0. Each + // version of foo depends on a baz with the same major version. Each version + // of bar depends on a baz with the same minor version. There is only one + // version of baz, 0.0.0, so only older versions of foo and bar will + // satisfy it. + fix := basicFixture{ + ds: []depspec{ + mkDepspec("root 0.0.0", "foo *", "bar *"), + mkDepspec("baz 0.0.0"), + }, + r: mksolution( + "foo 0.9.0", + "bar 9.0.0", + "baz 0.0.0", + ), + maxAttempts: 10, + } + + for i := 0; i < 10; i++ { + for j := 0; j < 10; j++ { + fix.ds = append(fix.ds, mkDepspec(fmt.Sprintf("foo %v.%v.0", i, j), fmt.Sprintf("baz %v.0.0", i))) + fix.ds = append(fix.ds, mkDepspec(fmt.Sprintf("bar %v.%v.0", i, j), fmt.Sprintf("baz 0.%v.0", j))) + } + } + + basicFixtures["complex backtrack"] = fix + + for k, fix := range basicFixtures { + // Assign the name into the fixture itself + fix.n = k + basicFixtures[k] = fix + } +} + +// reachMaps contain externalReach()-type data for a given depspec fixture's +// universe of projects, packages, and versions. +type reachMap map[pident]map[string][]string + +type depspecSourceManager struct { + specs []depspec + rm reachMap + ig map[string]bool +} + +type fixSM interface { + SourceManager + rootSpec() depspec + allSpecs() []depspec + ignore() map[string]bool +} + +var _ fixSM = &depspecSourceManager{} + +func newdepspecSM(ds []depspec, ignore []string) *depspecSourceManager { + ig := make(map[string]bool) + if len(ignore) > 0 { + for _, pkg := range ignore { + ig[pkg] = true + } + } + + return &depspecSourceManager{ + specs: ds, + rm: computeBasicReachMap(ds), + ig: ig, + } +} + +func (sm *depspecSourceManager) GetManifestAndLock(id ProjectIdentifier, v Version, an ProjectAnalyzer) (Manifest, Lock, error) { + // If the input version is a PairedVersion, look only at its top version, + // not the underlying. This is generally consistent with the idea that, for + // this class of lookup, the rev probably DOES exist, but upstream changed + // it (typically a branch). For the purposes of tests, then, that's an OK + // scenario, because otherwise we'd have to enumerate all the revs in the + // fixture declarations, which would screw up other things. + if pv, ok := v.(PairedVersion); ok { + v = pv.Unpair() + } + + src := toFold(id.normalizedSource()) + for _, ds := range sm.specs { + if src == string(ds.n) && v.Matches(ds.v) { + return ds, dummyLock{}, nil + } + } + + return nil, nil, fmt.Errorf("Project %s at version %s could not be found", id, v) +} + +func (sm *depspecSourceManager) ListPackages(id ProjectIdentifier, v Version) (pkgtree.PackageTree, error) { + pid := pident{n: ProjectRoot(toFold(id.normalizedSource())), v: v} + if pv, ok := v.(PairedVersion); ok && pv.Revision() == "FAKEREV" { + // An empty rev may come in here because that's what we produce in + // ListVersions(). If that's what we see, then just pretend like we have + // an unpaired. + pid.v = pv.Unpair() + } + + if r, exists := sm.rm[pid]; exists { + return pkgtree.PackageTree{ + ImportRoot: id.normalizedSource(), + Packages: map[string]pkgtree.PackageOrErr{ + string(pid.n): { + P: pkgtree.Package{ + ImportPath: string(pid.n), + Name: string(pid.n), + Imports: r[string(pid.n)], + }, + }, + }, + }, nil + } + + // if incoming version was paired, walk the map and search for a match on + // top-only version + if pv, ok := v.(PairedVersion); ok { + uv := pv.Unpair() + for pid, r := range sm.rm { + if uv.Matches(pid.v) { + return pkgtree.PackageTree{ + ImportRoot: id.normalizedSource(), + Packages: map[string]pkgtree.PackageOrErr{ + string(pid.n): { + P: pkgtree.Package{ + ImportPath: string(pid.n), + Name: string(pid.n), + Imports: r[string(pid.n)], + }, + }, + }, + }, nil + } + } + } + + return pkgtree.PackageTree{}, fmt.Errorf("Project %s at version %s could not be found", pid.n, v) +} + +func (sm *depspecSourceManager) ListVersions(id ProjectIdentifier) ([]PairedVersion, error) { + var pvl []PairedVersion + src := toFold(id.normalizedSource()) + for _, ds := range sm.specs { + if src != string(ds.n) { + continue + } + + switch tv := ds.v.(type) { + case Revision: + // To simulate the behavior of the real SourceManager, we do not return + // raw revisions from listVersions(). + case PairedVersion: + pvl = append(pvl, tv) + case UnpairedVersion: + // Dummy revision; if the fixture doesn't provide it, we know + // the test doesn't need revision info, anyway. + pvl = append(pvl, tv.Pair(Revision("FAKEREV"))) + default: + panic(fmt.Sprintf("unreachable: type of version was %#v for spec %s", ds.v, id)) + } + } + + if len(pvl) == 0 { + return nil, fmt.Errorf("Project %s could not be found", id) + } + return pvl, nil +} + +func (sm *depspecSourceManager) RevisionPresentIn(id ProjectIdentifier, r Revision) (bool, error) { + src := toFold(id.normalizedSource()) + for _, ds := range sm.specs { + if src == string(ds.n) && r == ds.v { + return true, nil + } + } + + return false, fmt.Errorf("Project %s has no revision %s", id, r) +} + +func (sm *depspecSourceManager) SourceExists(id ProjectIdentifier) (bool, error) { + src := toFold(id.normalizedSource()) + for _, ds := range sm.specs { + if src == string(ds.n) { + return true, nil + } + } + + return false, nil +} + +func (sm *depspecSourceManager) SyncSourceFor(id ProjectIdentifier) error { + // Ignore err because it can't happen + if exist, _ := sm.SourceExists(id); !exist { + return fmt.Errorf("Source %s does not exist", id) + } + return nil +} + +func (sm *depspecSourceManager) Release() {} + +func (sm *depspecSourceManager) ExportProject(context.Context, ProjectIdentifier, Version, string) error { + return fmt.Errorf("dummy sm doesn't support exporting") +} + +func (sm *depspecSourceManager) DeduceProjectRoot(ip string) (ProjectRoot, error) { + fip := toFold(ip) + for _, ds := range sm.allSpecs() { + n := string(ds.n) + if fip == n || strings.HasPrefix(fip, n+"/") { + return ProjectRoot(ip[:len(n)]), nil + } + } + return "", fmt.Errorf("Could not find %s, or any parent, in list of known fixtures", ip) +} + +func (sm *depspecSourceManager) SourceURLsForPath(ip string) ([]*url.URL, error) { + return nil, fmt.Errorf("dummy sm doesn't implement SourceURLsForPath") +} + +func (sm *depspecSourceManager) rootSpec() depspec { + return sm.specs[0] +} + +func (sm *depspecSourceManager) allSpecs() []depspec { + return sm.specs +} + +func (sm *depspecSourceManager) ignore() map[string]bool { + return sm.ig +} + +// InferConstraint tries to puzzle out what kind of version is given in a string - +// semver, a revision, or as a fallback, a plain tag. This current implementation +// is a panic because there's no current circumstance under which the depspecSourceManager +// is useful outside of the gps solving tests, and it shouldn't be used anywhere else without a conscious and intentional +// expansion of its semantics. +func (sm *depspecSourceManager) InferConstraint(s string, pi ProjectIdentifier) (Constraint, error) { + panic("depsecSourceManager is only for gps solving tests") +} + +type depspecBridge struct { + *bridge +} + +func (b *depspecBridge) listVersions(id ProjectIdentifier) ([]Version, error) { + if vl, exists := b.vlists[id]; exists { + return vl, nil + } + + pvl, err := b.sm.ListVersions(id) + if err != nil { + return nil, err + } + + // Construct a []Version slice. If any paired versions use the fake rev, + // remove the underlying component. + vl := make([]Version, 0, len(pvl)) + for _, v := range pvl { + if v.Revision() == "FAKEREV" { + vl = append(vl, v.Unpair()) + } else { + vl = append(vl, v) + } + } + + if b.down { + SortForDowngrade(vl) + } else { + SortForUpgrade(vl) + } + + b.vlists[id] = vl + return vl, nil +} + +// override verifyRoot() on bridge to prevent any filesystem interaction +func (b *depspecBridge) verifyRootDir(path string) error { + root := b.sm.(fixSM).rootSpec() + if string(root.n) != path { + return fmt.Errorf("Expected only root project %q to verifyRootDir(), got %q", root.n, path) + } + + return nil +} + +func (b *depspecBridge) ListPackages(id ProjectIdentifier, v Version) (pkgtree.PackageTree, error) { + return b.sm.(fixSM).ListPackages(id, v) +} + +func (b *depspecBridge) vendorCodeExists(id ProjectIdentifier) (bool, error) { + return false, nil +} + +// enforce interfaces +var _ Manifest = depspec{} +var _ Lock = dummyLock{} +var _ Lock = fixLock{} + +// impl Spec interface +func (ds depspec) DependencyConstraints() ProjectConstraints { + return pcSliceToMap(ds.deps) +} + +type fixLock []LockedProject + +// impl Lock interface +func (fixLock) InputsDigest() []byte { + return []byte("fooooorooooofooorooofoo") +} + +// impl Lock interface +func (l fixLock) Projects() []LockedProject { + return l +} + +type dummyLock struct{} + +// impl Lock interface +func (dummyLock) InputsDigest() []byte { + return []byte("fooooorooooofooorooofoo") +} + +// impl Lock interface +func (dummyLock) Projects() []LockedProject { + return nil +} diff --git a/vendor/github.com/golang/dep/gps/solve_bimodal_test.go b/vendor/github.com/golang/dep/gps/solve_bimodal_test.go new file mode 100644 index 00000000..7dfa7562 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/solve_bimodal_test.go @@ -0,0 +1,1504 @@ +// Copyright 2017 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 gps + +import ( + "fmt" + "path/filepath" + "strings" + + "github.com/golang/dep/gps/pkgtree" +) + +// dsp - "depspec with packages" +// +// Wraps a set of tpkgs onto a depspec, and returns it. +func dsp(ds depspec, pkgs ...tpkg) depspec { + ds.pkgs = pkgs + return ds +} + +// pkg makes a tpkg appropriate for use in bimodal testing +func pkg(path string, imports ...string) tpkg { + return tpkg{ + path: path, + imports: imports, + } +} + +func init() { + for k, fix := range bimodalFixtures { + // Assign the name into the fixture itself + fix.n = k + bimodalFixtures[k] = fix + } +} + +// Fixtures that rely on simulated bimodal (project and package-level) +// analysis for correct operation. The name given in the map gets assigned into +// the fixture itself in init(). +var bimodalFixtures = map[string]bimodalFixture{ + // Simple case, ensures that we do the very basics of picking up and + // including a single, simple import that is not expressed as a constraint + "simple bm-add": { + ds: []depspec{ + dsp(mkDepspec("root 0.0.0"), + pkg("root", "a")), + dsp(mkDepspec("a 1.0.0"), + pkg("a")), + }, + r: mksolution( + "a 1.0.0", + ), + }, + // Ensure it works when the import jump is not from the package with the + // same path as root, but from a subpkg + "subpkg bm-add": { + ds: []depspec{ + dsp(mkDepspec("root 0.0.0"), + pkg("root", "root/foo"), + pkg("root/foo", "a"), + ), + dsp(mkDepspec("a 1.0.0"), + pkg("a"), + ), + }, + r: mksolution( + "a 1.0.0", + ), + }, + // The same, but with a jump through two subpkgs + "double-subpkg bm-add": { + ds: []depspec{ + dsp(mkDepspec("root 0.0.0"), + pkg("root", "root/foo"), + pkg("root/foo", "root/bar"), + pkg("root/bar", "a"), + ), + dsp(mkDepspec("a 1.0.0"), + pkg("a"), + ), + }, + r: mksolution( + "a 1.0.0", + ), + }, + // Same again, but now nest the subpkgs + "double nested subpkg bm-add": { + ds: []depspec{ + dsp(mkDepspec("root 0.0.0"), + pkg("root", "root/foo"), + pkg("root/foo", "root/foo/bar"), + pkg("root/foo/bar", "a"), + ), + dsp(mkDepspec("a 1.0.0"), + pkg("a"), + ), + }, + r: mksolution( + "a 1.0.0", + ), + }, + // Importing package from project with no root package + "bm-add on project with no pkg in root dir": { + ds: []depspec{ + dsp(mkDepspec("root 0.0.0"), + pkg("root", "a/foo")), + dsp(mkDepspec("a 1.0.0"), + pkg("a/foo")), + }, + r: mksolution( + mklp("a 1.0.0", "foo"), + ), + }, + // Import jump is in a dep, and points to a transitive dep + "transitive bm-add": { + ds: []depspec{ + dsp(mkDepspec("root 0.0.0"), + pkg("root", "root/foo"), + pkg("root/foo", "a"), + ), + dsp(mkDepspec("a 1.0.0"), + pkg("a", "b"), + ), + dsp(mkDepspec("b 1.0.0"), + pkg("b"), + ), + }, + r: mksolution( + "a 1.0.0", + "b 1.0.0", + ), + }, + // Constraints apply only if the project that declares them has a + // reachable import + "constraints activated by import": { + ds: []depspec{ + dsp(mkDepspec("root 0.0.0", "b 1.0.0"), + pkg("root", "root/foo"), + pkg("root/foo", "a"), + ), + dsp(mkDepspec("a 1.0.0"), + pkg("a", "b"), + ), + dsp(mkDepspec("b 1.0.0"), + pkg("b"), + ), + dsp(mkDepspec("b 1.1.0"), + pkg("b"), + ), + }, + r: mksolution( + "a 1.0.0", + "b 1.1.0", + ), + }, + // Constraints apply only if the project that declares them has a + // reachable import - non-root + "constraints activated by import, transitive": { + ds: []depspec{ + dsp(mkDepspec("root 0.0.0"), + pkg("root", "root/foo", "b"), + pkg("root/foo", "a"), + ), + dsp(mkDepspec("a 1.0.0", "b 1.0.0"), + pkg("a"), + ), + dsp(mkDepspec("b 1.0.0"), + pkg("b"), + ), + dsp(mkDepspec("b 1.1.0"), + pkg("b"), + ), + }, + r: mksolution( + "a 1.0.0", + "b 1.1.0", + ), + }, + // Import jump is in a dep, and points to a transitive dep - but only in not + // the first version we try + "transitive bm-add on older version": { + ds: []depspec{ + dsp(mkDepspec("root 0.0.0", "a ~1.0.0"), + pkg("root", "root/foo"), + pkg("root/foo", "a"), + ), + dsp(mkDepspec("a 1.0.0"), + pkg("a", "b"), + ), + dsp(mkDepspec("a 1.1.0"), + pkg("a"), + ), + dsp(mkDepspec("b 1.0.0"), + pkg("b"), + ), + }, + r: mksolution( + "a 1.0.0", + "b 1.0.0", + ), + }, + // Import jump is in a dep, and points to a transitive dep - but will only + // get there via backtracking + "backtrack to dep on bm-add": { + ds: []depspec{ + dsp(mkDepspec("root 0.0.0"), + pkg("root", "root/foo"), + pkg("root/foo", "a", "b"), + ), + dsp(mkDepspec("a 1.0.0"), + pkg("a", "c"), + ), + dsp(mkDepspec("a 1.1.0"), + pkg("a"), + ), + // Include two versions of b, otherwise it'll be selected first + dsp(mkDepspec("b 0.9.0"), + pkg("b", "c"), + ), + dsp(mkDepspec("b 1.0.0"), + pkg("b", "c"), + ), + dsp(mkDepspec("c 1.0.0", "a 1.0.0"), + pkg("c", "a"), + ), + }, + r: mksolution( + "a 1.0.0", + "b 1.0.0", + "c 1.0.0", + ), + }, + "backjump through pkg-only selection": { + ds: []depspec{ + dsp(mkDepspec("root 0.0.0"), + pkg("root", "root/foo"), + pkg("root/foo", "a", "b"), + ), + dsp(mkDepspec("a 1.0.0"), + pkg("a", "c"), + ), + // Include two versions of b to ensure that a is visited first + dsp(mkDepspec("b 0.9.0", "d ^1.0.0"), + pkg("b", "c/other", "d"), + ), + dsp(mkDepspec("b 1.0.0", "d ^1.2.0"), + pkg("b", "c/other", "d"), + ), + // Three versions of c so it's last + dsp(mkDepspec("c 1.0.0", "d ^1.0.0"), + pkg("c", "d"), + pkg("c/other"), + ), + dsp(mkDepspec("d 1.0.0"), + pkg("d"), + ), + dsp(mkDepspec("d 1.1.0"), + pkg("d"), + ), + }, + r: mksolution( + "a 1.0.0", + "b 0.9.0", + mklp("c 1.0.0", ".", "other"), + "d 1.1.0", + ), + }, + // Import jump is in a dep subpkg, and points to a transitive dep + "transitive subpkg bm-add": { + ds: []depspec{ + dsp(mkDepspec("root 0.0.0"), + pkg("root", "root/foo"), + pkg("root/foo", "a"), + ), + dsp(mkDepspec("a 1.0.0"), + pkg("a", "a/bar"), + pkg("a/bar", "b"), + ), + dsp(mkDepspec("b 1.0.0"), + pkg("b"), + ), + }, + r: mksolution( + mklp("a 1.0.0", ".", "bar"), + "b 1.0.0", + ), + }, + // Import jump is in a dep subpkg, pointing to a transitive dep, but only in + // not the first version we try + "transitive subpkg bm-add on older version": { + ds: []depspec{ + dsp(mkDepspec("root 0.0.0", "a ~1.0.0"), + pkg("root", "root/foo"), + pkg("root/foo", "a"), + ), + dsp(mkDepspec("a 1.0.0"), + pkg("a", "a/bar"), + pkg("a/bar", "b"), + ), + dsp(mkDepspec("a 1.1.0"), + pkg("a", "a/bar"), + pkg("a/bar"), + ), + dsp(mkDepspec("b 1.0.0"), + pkg("b"), + ), + }, + r: mksolution( + mklp("a 1.0.0", ".", "bar"), + "b 1.0.0", + ), + }, + "project cycle involving root": { + ds: []depspec{ + dsp(mkDepspec("root 0.0.0", "a ~1.0.0"), + pkg("root", "a"), + pkg("root/foo"), + ), + dsp(mkDepspec("a 1.0.0"), + pkg("a", "root/foo"), + ), + }, + r: mksolution( + "a 1.0.0", + ), + }, + "project cycle involving root with backtracking": { + ds: []depspec{ + dsp(mkDepspec("root 0.0.0", "a ~1.0.0"), + pkg("root", "a", "b"), + pkg("root/foo"), + ), + dsp(mkDepspec("a 1.0.0"), + pkg("a", "root/foo"), + ), + dsp(mkDepspec("a 1.0.1"), + pkg("a", "root/foo"), + ), + dsp(mkDepspec("b 1.0.0", "a 1.0.0"), + pkg("b", "a"), + ), + dsp(mkDepspec("b 1.0.1", "a 1.0.0"), + pkg("b", "a"), + ), + dsp(mkDepspec("b 1.0.2", "a 1.0.0"), + pkg("b", "a"), + ), + }, + r: mksolution( + "a 1.0.0", + "b 1.0.2", + ), + }, + "unify project on disjoint package imports + source switching": { + ds: []depspec{ + dsp(mkDepspec("root 0.0.0", "b from baz 1.0.0"), + pkg("root", "a", "b"), + ), + dsp(mkDepspec("a 1.0.0"), + pkg("a", "b/foo"), + ), + dsp(mkDepspec("b 1.0.0"), + pkg("b"), + pkg("b/foo"), + ), + dsp(mkDepspec("baz 1.0.0"), + pkg("b"), + pkg("b/foo"), + ), + }, + r: mksolution( + "a 1.0.0", + mklp("b from baz 1.0.0", ".", "foo"), + ), + }, + "project cycle not involving root": { + ds: []depspec{ + dsp(mkDepspec("root 0.0.0", "a ~1.0.0"), + pkg("root", "a"), + ), + dsp(mkDepspec("a 1.0.0"), + pkg("a", "b"), + pkg("a/foo"), + ), + dsp(mkDepspec("b 1.0.0"), + pkg("b", "a/foo"), + ), + }, + r: mksolution( + mklp("a 1.0.0", ".", "foo"), + "b 1.0.0", + ), + }, + "project cycle not involving root with internal paths": { + ds: []depspec{ + dsp(mkDepspec("root 0.0.0", "a ~1.0.0"), + pkg("root", "a"), + ), + dsp(mkDepspec("a 1.0.0"), + pkg("a", "b/baz"), + pkg("a/foo", "a/quux", "a/quark"), + pkg("a/quux"), + pkg("a/quark"), + ), + dsp(mkDepspec("b 1.0.0"), + pkg("b", "a/foo"), + pkg("b/baz", "b"), + ), + }, + r: mksolution( + mklp("a 1.0.0", ".", "foo", "quark", "quux"), + mklp("b 1.0.0", ".", "baz"), + ), + }, + // Ensure that if a constraint is expressed, but no actual import exists, + // then the constraint is disregarded - the project named in the constraint + // is not part of the solution. + "ignore constraint without import": { + ds: []depspec{ + dsp(mkDepspec("root 0.0.0", "a 1.0.0"), + pkg("root", "root/foo"), + pkg("root/foo"), + ), + dsp(mkDepspec("a 1.0.0"), + pkg("a"), + ), + }, + r: mksolution(), + }, + // Transitive deps from one project (a) get incrementally included as other + // deps incorporate its various packages. + "multi-stage pkg incorporation": { + ds: []depspec{ + dsp(mkDepspec("root 0.0.0"), + pkg("root", "a", "d"), + ), + dsp(mkDepspec("a 1.0.0"), + pkg("a", "b"), + pkg("a/second", "c"), + ), + dsp(mkDepspec("b 2.0.0"), + pkg("b"), + ), + dsp(mkDepspec("c 1.2.0"), + pkg("c"), + ), + dsp(mkDepspec("d 1.0.0"), + pkg("d", "a/second"), + ), + }, + r: mksolution( + mklp("a 1.0.0", ".", "second"), + "b 2.0.0", + "c 1.2.0", + "d 1.0.0", + ), + }, + // Regression - make sure that the the constraint/import intersector only + // accepts a project 'match' if exactly equal, or a separating slash is + // present. + "radix path separator post-check": { + ds: []depspec{ + dsp(mkDepspec("root 0.0.0"), + pkg("root", "foo", "foobar"), + ), + dsp(mkDepspec("foo 1.0.0"), + pkg("foo"), + ), + dsp(mkDepspec("foobar 1.0.0"), + pkg("foobar"), + ), + }, + r: mksolution( + "foo 1.0.0", + "foobar 1.0.0", + ), + }, + // Well-formed failure when there's a dependency on a pkg that doesn't exist + "fail when imports nonexistent package": { + ds: []depspec{ + dsp(mkDepspec("root 0.0.0", "a 1.0.0"), + pkg("root", "a/foo"), + ), + dsp(mkDepspec("a 1.0.0"), + pkg("a"), + ), + }, + fail: &noVersionError{ + pn: mkPI("a"), + fails: []failedVersion{ + { + v: NewVersion("1.0.0"), + f: &checkeeHasProblemPackagesFailure{ + goal: mkAtom("a 1.0.0"), + failpkg: map[string]errDeppers{ + "a/foo": { + err: nil, // nil indicates package is missing + deppers: []atom{ + mkAtom("root"), + }, + }, + }, + }, + }, + }, + }, + }, + // Transitive deps from one project (a) get incrementally included as other + // deps incorporate its various packages, and fail with proper error when we + // discover one incrementally that isn't present + "fail multi-stage missing pkg": { + ds: []depspec{ + dsp(mkDepspec("root 0.0.0"), + pkg("root", "a", "d"), + ), + dsp(mkDepspec("a 1.0.0"), + pkg("a", "b"), + pkg("a/second", "c"), + ), + dsp(mkDepspec("b 2.0.0"), + pkg("b"), + ), + dsp(mkDepspec("c 1.2.0"), + pkg("c"), + ), + dsp(mkDepspec("d 1.0.0"), + pkg("d", "a/second"), + pkg("d", "a/nonexistent"), + ), + }, + fail: &noVersionError{ + pn: mkPI("d"), + fails: []failedVersion{ + { + v: NewVersion("1.0.0"), + f: &depHasProblemPackagesFailure{ + goal: mkADep("d 1.0.0", "a", Any(), "a/nonexistent"), + v: NewVersion("1.0.0"), + prob: map[string]error{ + "a/nonexistent": nil, + }, + }, + }, + }, + }, + }, + // Check ignores on the root project + "ignore in double-subpkg": { + ds: []depspec{ + dsp(mkDepspec("root 0.0.0"), + pkg("root", "root/foo"), + pkg("root/foo", "root/bar", "b"), + pkg("root/bar", "a"), + ), + dsp(mkDepspec("a 1.0.0"), + pkg("a"), + ), + dsp(mkDepspec("b 1.0.0"), + pkg("b"), + ), + }, + ignore: []string{"root/bar"}, + r: mksolution( + "b 1.0.0", + ), + }, + // Ignores on a dep pkg + "ignore through dep pkg": { + ds: []depspec{ + dsp(mkDepspec("root 0.0.0"), + pkg("root", "root/foo"), + pkg("root/foo", "a"), + ), + dsp(mkDepspec("a 1.0.0"), + pkg("a", "a/bar"), + pkg("a/bar", "b"), + ), + dsp(mkDepspec("b 1.0.0"), + pkg("b"), + ), + }, + ignore: []string{"a/bar"}, + r: mksolution( + "a 1.0.0", + ), + }, + // Preferred version, as derived from a dep's lock, is attempted first + "respect prefv, simple case": { + ds: []depspec{ + dsp(mkDepspec("root 0.0.0"), + pkg("root", "a")), + dsp(mkDepspec("a 1.0.0"), + pkg("a", "b")), + dsp(mkDepspec("b 1.0.0 foorev"), + pkg("b")), + dsp(mkDepspec("b 2.0.0 barrev"), + pkg("b")), + }, + lm: map[string]fixLock{ + "a 1.0.0": mklock( + "b 1.0.0 foorev", + ), + }, + r: mksolution( + "a 1.0.0", + "b 1.0.0 foorev", + ), + }, + // Preferred version, as derived from a dep's lock, is attempted first, even + // if the root also has a direct dep on it (root doesn't need to use + // preferreds, because it has direct control AND because the root lock + // already supersedes dep lock "preferences") + "respect dep prefv with root import": { + ds: []depspec{ + dsp(mkDepspec("root 0.0.0"), + pkg("root", "a", "b")), + dsp(mkDepspec("a 1.0.0"), + pkg("a", "b")), + //dsp(newDepspec("a 1.0.1"), + //pkg("a", "b")), + //dsp(newDepspec("a 1.1.0"), + //pkg("a", "b")), + dsp(mkDepspec("b 1.0.0 foorev"), + pkg("b")), + dsp(mkDepspec("b 2.0.0 barrev"), + pkg("b")), + }, + lm: map[string]fixLock{ + "a 1.0.0": mklock( + "b 1.0.0 foorev", + ), + }, + r: mksolution( + "a 1.0.0", + "b 1.0.0 foorev", + ), + }, + // Preferred versions can only work if the thing offering it has been + // selected, or at least marked in the unselected queue + "prefv only works if depper is selected": { + ds: []depspec{ + dsp(mkDepspec("root 0.0.0"), + pkg("root", "a", "b")), + // Three atoms for a, which will mean it gets visited after b + dsp(mkDepspec("a 1.0.0"), + pkg("a", "b")), + dsp(mkDepspec("a 1.0.1"), + pkg("a", "b")), + dsp(mkDepspec("a 1.1.0"), + pkg("a", "b")), + dsp(mkDepspec("b 1.0.0 foorev"), + pkg("b")), + dsp(mkDepspec("b 2.0.0 barrev"), + pkg("b")), + }, + lm: map[string]fixLock{ + "a 1.0.0": mklock( + "b 1.0.0 foorev", + ), + }, + r: mksolution( + "a 1.1.0", + "b 2.0.0 barrev", + ), + }, + "override unconstrained root import": { + ds: []depspec{ + dsp(mkDepspec("root 0.0.0"), + pkg("root", "a")), + dsp(mkDepspec("a 1.0.0"), + pkg("a")), + dsp(mkDepspec("a 2.0.0"), + pkg("a")), + }, + ovr: ProjectConstraints{ + ProjectRoot("a"): ProjectProperties{ + Constraint: NewVersion("1.0.0"), + }, + }, + r: mksolution( + "a 1.0.0", + ), + }, + "simple case-only differences": { + ds: []depspec{ + dsp(mkDepspec("root 0.0.0"), + pkg("root", "foo", "bar")), + dsp(mkDepspec("foo 1.0.0"), + pkg("foo", "Bar")), + dsp(mkDepspec("bar 1.0.0"), + pkg("bar")), + }, + fail: &noVersionError{ + pn: mkPI("foo"), + fails: []failedVersion{ + { + v: NewVersion("1.0.0"), + f: &caseMismatchFailure{ + goal: mkDep("foo 1.0.0", "Bar 1.0.0", "Bar"), + current: ProjectRoot("bar"), + failsib: []dependency{mkDep("root", "bar 1.0.0", "bar")}, + }, + }, + }, + }, + }, + "case variations acceptable with agreement": { + ds: []depspec{ + dsp(mkDepspec("root 0.0.0"), + pkg("root", "foo")), + dsp(mkDepspec("foo 1.0.0"), + pkg("foo", "Bar", "baz")), + dsp(mkDepspec("baz 1.0.0"), + pkg("baz", "Bar")), + dsp(mkDepspec("bar 1.0.0"), + pkg("bar")), + }, + r: mksolution( + "foo 1.0.0", + "Bar 1.0.0", + "baz 1.0.0", + ), + }, + "case variations within root": { + ds: []depspec{ + dsp(mkDepspec("root 0.0.0"), + pkg("root", "foo", "bar", "Bar")), + dsp(mkDepspec("foo 1.0.0"), + pkg("foo")), + dsp(mkDepspec("bar 1.0.0"), + pkg("bar")), + }, + fail: &noVersionError{ + pn: mkPI("foo"), + fails: []failedVersion{ + { + v: NewVersion("1.0.0"), + f: &caseMismatchFailure{ + goal: mkDep("foo 1.0.0", "Bar 1.0.0", "Bar"), + current: ProjectRoot("bar"), + failsib: []dependency{mkDep("root", "foo 1.0.0", "foo")}, + }, + }, + }, + }, + broken: "need to implement checking for import case variations *within* the root", + }, + "case variations within single dep": { + ds: []depspec{ + dsp(mkDepspec("root 0.0.0"), + pkg("root", "foo")), + dsp(mkDepspec("foo 1.0.0"), + pkg("foo", "bar", "Bar")), + dsp(mkDepspec("bar 1.0.0"), + pkg("bar")), + }, + fail: &noVersionError{ + pn: mkPI("foo"), + fails: []failedVersion{ + { + v: NewVersion("1.0.0"), + f: &caseMismatchFailure{ + goal: mkDep("foo 1.0.0", "Bar 1.0.0", "Bar"), + current: ProjectRoot("bar"), + failsib: []dependency{mkDep("root", "foo 1.0.0", "foo")}, + }, + }, + }, + }, + broken: "need to implement checking for import case variations *within* a single project", + }, + "case variations across multiple deps": { + ds: []depspec{ + dsp(mkDepspec("root 0.0.0"), + pkg("root", "foo", "bar")), + dsp(mkDepspec("foo 1.0.0"), + pkg("foo", "bar", "baz")), + dsp(mkDepspec("baz 1.0.0"), + pkg("baz", "Bar")), + dsp(mkDepspec("bar 1.0.0"), + pkg("bar")), + }, + fail: &noVersionError{ + pn: mkPI("baz"), + fails: []failedVersion{ + { + v: NewVersion("1.0.0"), + f: &caseMismatchFailure{ + goal: mkDep("baz 1.0.0", "Bar 1.0.0", "Bar"), + current: ProjectRoot("bar"), + failsib: []dependency{ + mkDep("root", "bar 1.0.0", "bar"), + mkDep("foo 1.0.0", "bar 1.0.0", "bar"), + }, + }, + }, + }, + }, + }, + // This isn't actually as crazy as it might seem, as the root is defined by + // the addresser, not the addressee. It would occur (to provide a + // real-as-of-this-writing example) if something imports + // github.com/Sirupsen/logrus, as the contained subpackage at + // github.com/Sirupsen/logrus/hooks/syslog imports + // github.com/sirupsen/logrus. The only reason that doesn't blow up all the + // time is that most people only import the root package, not the syslog + // subpackage. + "canonical case is established by mutual self-imports": { + ds: []depspec{ + dsp(mkDepspec("root 0.0.0"), + pkg("root", "foo")), + dsp(mkDepspec("foo 1.0.0"), + pkg("foo", "Bar")), + dsp(mkDepspec("bar 1.0.0"), + pkg("bar", "bar/subpkg"), + pkg("bar/subpkg")), + }, + fail: &noVersionError{ + pn: mkPI("Bar"), + fails: []failedVersion{ + { + v: NewVersion("1.0.0"), + f: &wrongCaseFailure{ + correct: ProjectRoot("bar"), + goal: mkDep("Bar 1.0.0", "bar 1.0.0", "bar"), + badcase: []dependency{mkDep("foo 1.0.0", "Bar 1.0.0", "Bar/subpkg")}, + }, + }, + }, + }, + }, + "canonical case only applies if relevant imports are activated": { + ds: []depspec{ + dsp(mkDepspec("root 0.0.0"), + pkg("root", "foo")), + dsp(mkDepspec("foo 1.0.0"), + pkg("foo", "Bar/subpkg")), + dsp(mkDepspec("bar 1.0.0"), + pkg("bar", "bar/subpkg"), + pkg("bar/subpkg")), + }, + r: mksolution( + "foo 1.0.0", + mklp("Bar 1.0.0", "subpkg"), + ), + }, + "simple case-only variations plus source variance": { + ds: []depspec{ + dsp(mkDepspec("root 0.0.0"), + pkg("root", "foo", "bar")), + dsp(mkDepspec("foo 1.0.0", "Bar from quux 1.0.0"), + pkg("foo", "Bar")), + dsp(mkDepspec("bar 1.0.0"), + pkg("bar")), + dsp(mkDepspec("quux 1.0.0"), + pkg("bar")), + }, + fail: &noVersionError{ + pn: mkPI("foo"), + fails: []failedVersion{ + { + v: NewVersion("1.0.0"), + f: &caseMismatchFailure{ + goal: mkDep("foo 1.0.0", "Bar from quux 1.0.0", "Bar"), + current: ProjectRoot("bar"), + failsib: []dependency{mkDep("root", "bar 1.0.0", "bar")}, + }, + }, + }, + }, + }, + "case-only variations plus source variance with internal canonicality": { + ds: []depspec{ + dsp(mkDepspec("root 0.0.0", "Bar from quux 1.0.0"), + pkg("root", "foo", "Bar")), + dsp(mkDepspec("foo 1.0.0", "Bar from quux 1.0.0"), + pkg("foo", "Bar")), + dsp(mkDepspec("bar 1.0.0"), + pkg("bar", "bar/subpkg"), + pkg("bar/subpkg")), + dsp(mkDepspec("quux 1.0.0"), + pkg("bar", "bar/subpkg"), + pkg("bar/subpkg")), + }, + fail: &noVersionError{ + pn: mkPI("Bar"), + fails: []failedVersion{ + { + v: NewVersion("1.0.0"), + f: &wrongCaseFailure{ + correct: ProjectRoot("bar"), + goal: mkDep("Bar from quux 1.0.0", "bar 1.0.0", "bar"), + badcase: []dependency{mkDep("root", "Bar 1.0.0", "Bar/subpkg")}, + }, + }, + }, + }, + }, + "alternate net address": { + ds: []depspec{ + dsp(mkDepspec("root 1.0.0", "foo from bar 2.0.0"), + pkg("root", "foo")), + dsp(mkDepspec("foo 1.0.0"), + pkg("foo")), + dsp(mkDepspec("foo 2.0.0"), + pkg("foo")), + dsp(mkDepspec("bar 1.0.0"), + pkg("foo")), + dsp(mkDepspec("bar 2.0.0"), + pkg("foo")), + }, + r: mksolution( + "foo from bar 2.0.0", + ), + }, + "alternate net address, version only in alt": { + ds: []depspec{ + dsp(mkDepspec("root 1.0.0", "foo from bar 2.0.0"), + pkg("root", "foo")), + dsp(mkDepspec("foo 1.0.0"), + pkg("foo")), + dsp(mkDepspec("bar 1.0.0"), + pkg("foo")), + dsp(mkDepspec("bar 2.0.0"), + pkg("foo")), + }, + r: mksolution( + "foo from bar 2.0.0", + ), + }, + "alternate net address in dep": { + ds: []depspec{ + dsp(mkDepspec("root 1.0.0", "foo 1.0.0"), + pkg("root", "foo")), + dsp(mkDepspec("foo 1.0.0", "bar from baz 2.0.0"), + pkg("foo", "bar")), + dsp(mkDepspec("bar 1.0.0"), + pkg("bar")), + dsp(mkDepspec("baz 1.0.0"), + pkg("bar")), + dsp(mkDepspec("baz 2.0.0"), + pkg("bar")), + }, + r: mksolution( + "foo 1.0.0", + "bar from baz 2.0.0", + ), + }, + // Because NOT specifying an alternate net address for a given import path + // is taken as an "eh, whatever", if we see an empty net addr after + // something else has already set an alternate one, then the second should + // just "go along" with whatever's already been specified. + "alternate net address with second depper": { + ds: []depspec{ + dsp(mkDepspec("root 1.0.0", "foo from bar 2.0.0"), + pkg("root", "foo", "baz")), + dsp(mkDepspec("foo 1.0.0"), + pkg("foo")), + dsp(mkDepspec("foo 2.0.0"), + pkg("foo")), + dsp(mkDepspec("bar 1.0.0"), + pkg("foo")), + dsp(mkDepspec("bar 2.0.0"), + pkg("foo")), + dsp(mkDepspec("baz 1.0.0"), + pkg("baz", "foo")), + }, + r: mksolution( + "foo from bar 2.0.0", + "baz 1.0.0", + ), + }, + // Same as the previous, except the alternate declaration originates in a + // dep, not the root. + "alternate net addr from dep, with second default depper": { + ds: []depspec{ + dsp(mkDepspec("root 1.0.0", "foo 1.0.0"), + pkg("root", "foo", "bar")), + dsp(mkDepspec("foo 1.0.0", "bar 2.0.0"), + pkg("foo", "baz")), + dsp(mkDepspec("foo 2.0.0", "bar 2.0.0"), + pkg("foo", "baz")), + dsp(mkDepspec("bar 2.0.0", "baz from quux 1.0.0"), + pkg("bar", "baz")), + dsp(mkDepspec("baz 1.0.0"), + pkg("baz")), + dsp(mkDepspec("baz 2.0.0"), + pkg("baz")), + dsp(mkDepspec("quux 1.0.0"), + pkg("baz")), + }, + r: mksolution( + "foo 1.0.0", + "bar 2.0.0", + "baz from quux 1.0.0", + ), + }, + // When a given project is initially brought in using the default (i.e., + // empty) ProjectIdentifier.Source, and a later, presumably + // as-yet-undiscovered dependency specifies an alternate net addr for it, we + // have to fail - even though, if the deps were visited in the opposite + // order (deeper dep w/the alternate location first, default location + // second), it would be fine. + // + // TODO A better solution here would involve restarting the solver w/a + // marker to use that alternate, or (ugh) introducing a new failure + // path/marker type that changes how backtracking works. (In fact, these + // approaches are probably demonstrably equivalent.) + "fails with net mismatch when deeper dep specs it": { + ds: []depspec{ + dsp(mkDepspec("root 1.0.0", "foo 1.0.0"), + pkg("root", "foo", "baz")), + dsp(mkDepspec("foo 1.0.0", "bar 2.0.0"), + pkg("foo", "bar")), + dsp(mkDepspec("bar 2.0.0", "baz from quux 1.0.0"), + pkg("bar", "baz")), + dsp(mkDepspec("baz 1.0.0"), + pkg("baz")), + dsp(mkDepspec("quux 1.0.0"), + pkg("baz")), + }, + fail: &noVersionError{ + pn: mkPI("bar"), + fails: []failedVersion{ + { + v: NewVersion("2.0.0"), + f: &sourceMismatchFailure{ + shared: ProjectRoot("baz"), + current: "baz", + mismatch: "quux", + prob: mkAtom("bar 2.0.0"), + sel: []dependency{mkDep("foo 1.0.0", "bar 2.0.0", "bar")}, + }, + }, + }, + }, + }, + "with mismatched net addrs": { + ds: []depspec{ + dsp(mkDepspec("root 1.0.0", "foo 1.0.0", "bar 1.0.0"), + pkg("root", "foo", "bar")), + dsp(mkDepspec("foo 1.0.0", "bar from baz 1.0.0"), + pkg("foo", "bar")), + dsp(mkDepspec("bar 1.0.0"), + pkg("bar")), + dsp(mkDepspec("baz 1.0.0"), + pkg("bar")), + }, + fail: &noVersionError{ + pn: mkPI("foo"), + fails: []failedVersion{ + { + v: NewVersion("1.0.0"), + f: &sourceMismatchFailure{ + shared: ProjectRoot("bar"), + current: "bar", + mismatch: "baz", + prob: mkAtom("foo 1.0.0"), + sel: []dependency{mkDep("root", "foo 1.0.0", "foo")}, + }, + }, + }, + }, + }, + "overridden mismatched net addrs, alt in dep": { + ds: []depspec{ + dsp(mkDepspec("root 0.0.0"), + pkg("root", "foo")), + dsp(mkDepspec("foo 1.0.0", "bar from baz 1.0.0"), + pkg("foo", "bar")), + dsp(mkDepspec("bar 1.0.0"), + pkg("bar")), + dsp(mkDepspec("baz 1.0.0"), + pkg("bar")), + }, + ovr: ProjectConstraints{ + ProjectRoot("bar"): ProjectProperties{ + Source: "baz", + }, + }, + r: mksolution( + "foo 1.0.0", + "bar from baz 1.0.0", + ), + }, + "overridden mismatched net addrs, alt in root": { + ds: []depspec{ + dsp(mkDepspec("root 0.0.0", "bar from baz 1.0.0"), + pkg("root", "foo")), + dsp(mkDepspec("foo 1.0.0"), + pkg("foo", "bar")), + dsp(mkDepspec("bar 1.0.0"), + pkg("bar")), + dsp(mkDepspec("baz 1.0.0"), + pkg("bar")), + }, + ovr: ProjectConstraints{ + ProjectRoot("bar"): ProjectProperties{ + Source: "baz", + }, + }, + r: mksolution( + "foo 1.0.0", + "bar from baz 1.0.0", + ), + }, + "require package": { + ds: []depspec{ + dsp(mkDepspec("root 0.0.0", "bar 1.0.0"), + pkg("root", "foo")), + dsp(mkDepspec("foo 1.0.0"), + pkg("foo", "bar")), + dsp(mkDepspec("bar 1.0.0"), + pkg("bar")), + dsp(mkDepspec("baz 1.0.0"), + pkg("baz")), + }, + require: []string{"baz"}, + r: mksolution( + "foo 1.0.0", + "bar 1.0.0", + "baz 1.0.0", + ), + }, + "require activates constraints": { + ds: []depspec{ + dsp(mkDepspec("root 0.0.0", "foo 1.0.0", "bar 1.0.0"), + pkg("root", "foo")), + dsp(mkDepspec("foo 1.0.0"), + pkg("foo", "bar")), + dsp(mkDepspec("bar 1.0.0"), + pkg("bar")), + dsp(mkDepspec("bar 1.1.0"), + pkg("bar")), + }, + require: []string{"bar"}, + r: mksolution( + "foo 1.0.0", + "bar 1.0.0", + ), + }, + "require subpackage": { + ds: []depspec{ + dsp(mkDepspec("root 0.0.0", "bar 1.0.0"), + pkg("root", "foo")), + dsp(mkDepspec("foo 1.0.0"), + pkg("foo", "bar")), + dsp(mkDepspec("bar 1.0.0"), + pkg("bar")), + dsp(mkDepspec("baz 1.0.0"), + pkg("baz", "baz/qux"), + pkg("baz/qux")), + }, + require: []string{"baz/qux"}, + r: mksolution( + "foo 1.0.0", + "bar 1.0.0", + mklp("baz 1.0.0", "qux"), + ), + }, + "require impossible subpackage": { + ds: []depspec{ + dsp(mkDepspec("root 0.0.0", "baz 1.0.0"), + pkg("root", "foo")), + dsp(mkDepspec("foo 1.0.0"), + pkg("foo")), + dsp(mkDepspec("baz 1.0.0"), + pkg("baz")), + dsp(mkDepspec("baz 2.0.0"), + pkg("baz", "baz/qux"), + pkg("baz/qux")), + }, + require: []string{"baz/qux"}, + fail: &noVersionError{ + pn: mkPI("baz"), + fails: []failedVersion{ + { + v: NewVersion("2.0.0"), + f: &versionNotAllowedFailure{ + goal: mkAtom("baz 2.0.0"), + failparent: []dependency{mkDep("root", "baz 1.0.0", "baz/qux")}, + c: NewVersion("1.0.0"), + }, + }, + { + v: NewVersion("1.0.0"), + f: &checkeeHasProblemPackagesFailure{ + goal: mkAtom("baz 1.0.0"), + failpkg: map[string]errDeppers{ + "baz/qux": { + err: nil, // nil indicates package is missing + deppers: []atom{ + mkAtom("root"), + }, + }, + }, + }, + }, + }, + }, + }, + "require subpkg conflicts with other dep constraint": { + ds: []depspec{ + dsp(mkDepspec("root 0.0.0"), + pkg("root", "foo")), + dsp(mkDepspec("foo 1.0.0", "baz 1.0.0"), + pkg("foo", "baz")), + dsp(mkDepspec("baz 1.0.0"), + pkg("baz")), + dsp(mkDepspec("baz 2.0.0"), + pkg("baz", "baz/qux"), + pkg("baz/qux")), + }, + require: []string{"baz/qux"}, + fail: &noVersionError{ + pn: mkPI("baz"), + fails: []failedVersion{ + { + v: NewVersion("2.0.0"), + f: &versionNotAllowedFailure{ + goal: mkAtom("baz 2.0.0"), + failparent: []dependency{mkDep("foo 1.0.0", "baz 1.0.0", "baz")}, + c: NewVersion("1.0.0"), + }, + }, + { + v: NewVersion("1.0.0"), + f: &checkeeHasProblemPackagesFailure{ + goal: mkAtom("baz 1.0.0"), + failpkg: map[string]errDeppers{ + "baz/qux": { + err: nil, // nil indicates package is missing + deppers: []atom{ + mkAtom("root"), + }, + }, + }, + }, + }, + }, + }, + }, + "require independent subpkg conflicts with other dep constraint": { + ds: []depspec{ + dsp(mkDepspec("root 0.0.0"), + pkg("root", "foo")), + dsp(mkDepspec("foo 1.0.0", "baz 1.0.0"), + pkg("foo", "baz")), + dsp(mkDepspec("baz 1.0.0"), + pkg("baz")), + dsp(mkDepspec("baz 2.0.0"), + pkg("baz"), + pkg("baz/qux")), + }, + require: []string{"baz/qux"}, + fail: &noVersionError{ + pn: mkPI("baz"), + fails: []failedVersion{ + { + v: NewVersion("2.0.0"), + f: &versionNotAllowedFailure{ + goal: mkAtom("baz 2.0.0"), + failparent: []dependency{mkDep("foo 1.0.0", "baz 1.0.0", "baz")}, + c: NewVersion("1.0.0"), + }, + }, + { + v: NewVersion("1.0.0"), + f: &checkeeHasProblemPackagesFailure{ + goal: mkAtom("baz 1.0.0"), + failpkg: map[string]errDeppers{ + "baz/qux": { + err: nil, // nil indicates package is missing + deppers: []atom{ + mkAtom("root"), + }, + }, + }, + }, + }, + }, + }, + }, +} + +// tpkg is a representation of a single package. It has its own import path, as +// well as a list of paths it itself "imports". +type tpkg struct { + // Full import path of this package + path string + // Slice of full paths to its virtual imports + imports []string +} + +type bimodalFixture struct { + // name of this fixture datum + n string + // bimodal project; first is always treated as root project + ds []depspec + // results; map of name/version pairs + r map[ProjectIdentifier]LockedProject + // max attempts the solver should need to find solution. 0 means no limit + maxAttempts int + // Use downgrade instead of default upgrade sorter + downgrade bool + // lock file simulator, if one's to be used at all + l fixLock + // map of locks for deps, if any. keys should be of the form: + // " " + lm map[string]fixLock + // solve failure expected, if any + fail error + // overrides, if any + ovr ProjectConstraints + // request up/downgrade to all projects + changeall bool + // pkgs to ignore + ignore []string + // pkgs to require + require []string + // if the fixture is currently broken/expected to fail, this has a message + // recording why + broken string +} + +func (f bimodalFixture) name() string { + return f.n +} + +func (f bimodalFixture) specs() []depspec { + return f.ds +} + +func (f bimodalFixture) maxTries() int { + return f.maxAttempts +} + +func (f bimodalFixture) solution() map[ProjectIdentifier]LockedProject { + return f.r +} + +func (f bimodalFixture) rootmanifest() RootManifest { + m := simpleRootManifest{ + c: pcSliceToMap(f.ds[0].deps), + ovr: f.ovr, + ig: pkgtree.NewIgnoredRuleset(f.ignore), + req: make(map[string]bool), + } + for _, req := range f.require { + m.req[req] = true + } + + return m +} + +func (f bimodalFixture) rootTree() pkgtree.PackageTree { + pt := pkgtree.PackageTree{ + ImportRoot: string(f.ds[0].n), + Packages: map[string]pkgtree.PackageOrErr{}, + } + + for _, pkg := range f.ds[0].pkgs { + elems := strings.Split(pkg.path, "/") + pt.Packages[pkg.path] = pkgtree.PackageOrErr{ + P: pkgtree.Package{ + ImportPath: pkg.path, + Name: elems[len(elems)-1], + // TODO(sdboyer) ugh, tpkg type has no space for supporting test + // imports... + Imports: pkg.imports, + }, + } + } + + return pt +} + +func (f bimodalFixture) failure() error { + return f.fail +} + +// bmSourceManager is an SM specifically for the bimodal fixtures. It composes +// the general depspec SM, and differs from it in how it answers static analysis +// calls, and its support for package ignores and dep lock data. +type bmSourceManager struct { + depspecSourceManager + lm map[string]fixLock +} + +var _ SourceManager = &bmSourceManager{} + +func newbmSM(bmf bimodalFixture) *bmSourceManager { + sm := &bmSourceManager{ + depspecSourceManager: *newdepspecSM(bmf.ds, bmf.ignore), + } + sm.rm = computeBimodalExternalMap(bmf.ds) + sm.lm = bmf.lm + + return sm +} + +func (sm *bmSourceManager) ListPackages(id ProjectIdentifier, v Version) (pkgtree.PackageTree, error) { + // Deal with address-based root-switching with both case folding and + // alternate sources. + var src, fsrc, root, froot string + src, fsrc = id.normalizedSource(), toFold(id.normalizedSource()) + if id.Source != "" { + root = string(id.ProjectRoot) + froot = toFold(root) + } else { + root, froot = src, fsrc + } + + for k, ds := range sm.specs { + // Cheat for root, otherwise we blow up b/c version is empty + if fsrc == string(ds.n) && (k == 0 || ds.v.Matches(v)) { + var replace bool + if root != string(ds.n) { + // We're in a case-varying lookup; ensure we replace the actual + // leading ProjectRoot portion of import paths with the literal + // string from the input. + replace = true + } + + ptree := pkgtree.PackageTree{ + ImportRoot: src, + Packages: make(map[string]pkgtree.PackageOrErr), + } + for _, pkg := range ds.pkgs { + if replace { + pkg.path = strings.Replace(pkg.path, froot, root, 1) + } + ptree.Packages[pkg.path] = pkgtree.PackageOrErr{ + P: pkgtree.Package{ + ImportPath: pkg.path, + Name: filepath.Base(pkg.path), + Imports: pkg.imports, + }, + } + } + + return ptree, nil + } + } + + return pkgtree.PackageTree{}, fmt.Errorf("Project %s at version %s could not be found", id, v) +} + +func (sm *bmSourceManager) GetManifestAndLock(id ProjectIdentifier, v Version, an ProjectAnalyzer) (Manifest, Lock, error) { + src := toFold(id.normalizedSource()) + for _, ds := range sm.specs { + if src == string(ds.n) && v.Matches(ds.v) { + if l, exists := sm.lm[src+" "+v.String()]; exists { + return ds, l, nil + } + return ds, dummyLock{}, nil + } + } + + // TODO(sdboyer) proper solver-type errors + return nil, nil, fmt.Errorf("Project %s at version %s could not be found", id, v) +} + +// computeBimodalExternalMap takes a set of depspecs and computes an +// internally-versioned ReachMap that is useful for quickly answering +// ReachMap.Flatten()-type calls. +// +// Note that it does not do things like stripping out stdlib packages - these +// maps are intended for use in SM fixtures, and that's a higher-level +// responsibility within the system. +func computeBimodalExternalMap(specs []depspec) map[pident]map[string][]string { + // map of project name+version -> map of subpkg name -> external pkg list + rm := make(map[pident]map[string][]string) + + for _, ds := range specs { + ptree := pkgtree.PackageTree{ + ImportRoot: string(ds.n), + Packages: make(map[string]pkgtree.PackageOrErr), + } + for _, pkg := range ds.pkgs { + ptree.Packages[pkg.path] = pkgtree.PackageOrErr{ + P: pkgtree.Package{ + ImportPath: pkg.path, + Name: filepath.Base(pkg.path), + Imports: pkg.imports, + }, + } + } + reachmap, em := ptree.ToReachMap(false, true, true, nil) + if len(em) > 0 { + panic(fmt.Sprintf("pkgs with errors in reachmap processing: %s", em)) + } + + drm := make(map[string][]string) + for ip, ie := range reachmap { + drm[ip] = ie.External + } + rm[pident{n: ds.n, v: ds.v}] = drm + } + + return rm +} diff --git a/vendor/github.com/golang/dep/gps/solve_failures.go b/vendor/github.com/golang/dep/gps/solve_failures.go new file mode 100644 index 00000000..05daedd7 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/solve_failures.go @@ -0,0 +1,572 @@ +// Copyright 2017 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 gps + +import ( + "bytes" + "fmt" + "sort" + "strings" +) + +func a2vs(a atom) string { + if a.v == rootRev || a.v == nil { + return "(root)" + } + + return fmt.Sprintf("%s@%s", a.id, a.v) +} + +type traceError interface { + traceString() string +} + +type noVersionError struct { + pn ProjectIdentifier + fails []failedVersion +} + +func (e *noVersionError) Error() string { + if len(e.fails) == 0 { + return fmt.Sprintf("No versions found for project %q.", e.pn.ProjectRoot) + } + + var buf bytes.Buffer + fmt.Fprintf(&buf, "No versions of %s met constraints:", e.pn.ProjectRoot) + for _, f := range e.fails { + fmt.Fprintf(&buf, "\n\t%s: %s", f.v, f.f.Error()) + } + + return buf.String() +} + +func (e *noVersionError) traceString() string { + if len(e.fails) == 0 { + return fmt.Sprintf("No versions found") + } + + var buf bytes.Buffer + fmt.Fprintf(&buf, "No versions of %s met constraints:", e.pn.ProjectRoot) + for _, f := range e.fails { + if te, ok := f.f.(traceError); ok { + fmt.Fprintf(&buf, "\n %s: %s", f.v, te.traceString()) + } else { + fmt.Fprintf(&buf, "\n %s: %s", f.v, f.f.Error()) + } + } + + return buf.String() +} + +// caseMismatchFailure occurs when there are import paths that differ only by +// case. The compiler disallows this case. +type caseMismatchFailure struct { + // goal is the depender atom that tried to introduce the case-varying name, + // along with the case-varying name. + goal dependency + // current is the specific casing of a ProjectRoot that is presently + // selected for all possible case variations of its contained unicode code + // points. + current ProjectRoot + // failsib is the list of active dependencies that have determined the + // specific casing for the target project. + failsib []dependency +} + +func (e *caseMismatchFailure) Error() string { + if len(e.failsib) == 1 { + str := "Could not introduce %s due to a case-only variation: it depends on %q, but %q was already established as the case variant for that project root by depender %s" + return fmt.Sprintf(str, a2vs(e.goal.depender), e.goal.dep.Ident.ProjectRoot, e.current, a2vs(e.failsib[0].depender)) + } + + var buf bytes.Buffer + + str := "Could not introduce %s due to a case-only variation: it depends on %q, but %q was already established as the case variant for that project root by the following other dependers:\n" + fmt.Fprintf(&buf, str, a2vs(e.goal.depender), e.goal.dep.Ident.ProjectRoot, e.current) + + for _, c := range e.failsib { + fmt.Fprintf(&buf, "\t%s\n", a2vs(c.depender)) + } + + return buf.String() +} + +func (e *caseMismatchFailure) traceString() string { + var buf bytes.Buffer + fmt.Fprintf(&buf, "case-only variation in dependency on %q; %q already established by:\n", e.goal.dep.Ident.ProjectRoot, e.current) + for _, f := range e.failsib { + fmt.Fprintf(&buf, "%s\n", a2vs(f.depender)) + } + + return buf.String() +} + +// wrongCaseFailure occurs when one or more projects - A, B, ... - depend on +// another project - Z - with an incorrect case variant, as indicated by the +// case variant used internally by Z to reference its own packages. +// +// For example, github.com/sirupsen/logrus/hooks/syslog references itself via +// github.com/sirupsen/logrus, establishing that as the canonical case variant. +type wrongCaseFailure struct { + // correct is the canonical representation of the ProjectRoot + correct ProjectRoot + // goal is the incorrectly-referenced target project + goal dependency + // badcase is the list of active dependencies that have specified an + // incorrect ProjectRoot casing for the project in question. + badcase []dependency +} + +func (e *wrongCaseFailure) Error() string { + if len(e.badcase) == 1 { + str := "Could not introduce %s; imports amongst its packages establish %q as the canonical casing for root, but %s tried to import it as %q" + return fmt.Sprintf(str, a2vs(e.goal.depender), e.correct, a2vs(e.badcase[0].depender), e.badcase[0].dep.Ident.ProjectRoot) + } + + var buf bytes.Buffer + + str := "Could not introduce %s; imports amongst its packages establish %q as the canonical casing for root, but the following projects tried to import it as %q" + fmt.Fprintf(&buf, str, a2vs(e.goal.depender), e.correct, e.badcase[0].dep.Ident.ProjectRoot) + + for _, c := range e.badcase { + fmt.Fprintf(&buf, "\t%s\n", a2vs(c.depender)) + } + + return buf.String() +} + +func (e *wrongCaseFailure) traceString() string { + var buf bytes.Buffer + fmt.Fprintf(&buf, "internal imports establish %q as correct casing; %q was used by:\n", e.correct, e.goal.dep.Ident.ProjectRoot) + for _, f := range e.badcase { + fmt.Fprintf(&buf, "%s\n", a2vs(f.depender)) + } + + return buf.String() +} + +// disjointConstraintFailure occurs when attempting to introduce an atom that +// itself has an acceptable version, but one of its dependency constraints is +// disjoint with one or more dependency constraints already active for that +// identifier. +type disjointConstraintFailure struct { + // goal is the dependency with the problematic constraint, forcing us to + // reject the atom that introduces it. + goal dependency + // failsib is the list of active dependencies that are disjoint with the + // goal dependency. This will be at least one, but may not be all of the + // active dependencies. + failsib []dependency + // nofailsib is the list of active dependencies that are NOT disjoint with + // the goal dependency. The total of nofailsib and failsib will always be + // the total number of active dependencies on target identifier. + nofailsib []dependency + // c is the current constraint on the target identifier. It is intersection + // of all the active dependencies' constraints. + c Constraint +} + +func (e *disjointConstraintFailure) Error() string { + if len(e.failsib) == 1 { + str := "Could not introduce %s, as it has a dependency on %s with constraint %s, which has no overlap with existing constraint %s from %s" + return fmt.Sprintf(str, a2vs(e.goal.depender), e.goal.dep.Ident, e.goal.dep.Constraint.String(), e.failsib[0].dep.Constraint.String(), a2vs(e.failsib[0].depender)) + } + + var buf bytes.Buffer + + var sibs []dependency + if len(e.failsib) > 1 { + sibs = e.failsib + + str := "Could not introduce %s, as it has a dependency on %s with constraint %s, which has no overlap with the following existing constraints:\n" + fmt.Fprintf(&buf, str, a2vs(e.goal.depender), e.goal.dep.Ident, e.goal.dep.Constraint.String()) + } else { + sibs = e.nofailsib + + str := "Could not introduce %s, as it has a dependency on %s with constraint %s, which does not overlap with the intersection of existing constraints from other currently selected packages:\n" + fmt.Fprintf(&buf, str, a2vs(e.goal.depender), e.goal.dep.Ident, e.goal.dep.Constraint.String()) + } + + for _, c := range sibs { + fmt.Fprintf(&buf, "\t%s from %s\n", c.dep.Constraint.String(), a2vs(c.depender)) + } + + return buf.String() +} + +func (e *disjointConstraintFailure) traceString() string { + var buf bytes.Buffer + fmt.Fprintf(&buf, "constraint %s on %s disjoint with other dependers:\n", e.goal.dep.Constraint.String(), e.goal.dep.Ident) + for _, f := range e.failsib { + fmt.Fprintf( + &buf, + "%s from %s (no overlap)\n", + f.dep.Constraint.String(), + a2vs(f.depender), + ) + } + for _, f := range e.nofailsib { + fmt.Fprintf( + &buf, + "%s from %s (some overlap)\n", + f.dep.Constraint.String(), + a2vs(f.depender), + ) + } + + return buf.String() +} + +// Indicates that an atom could not be introduced because one of its dep +// constraints does not admit the currently-selected version of the target +// project. +type constraintNotAllowedFailure struct { + // The dependency with the problematic constraint that could not be + // introduced. + goal dependency + // The (currently selected) version of the target project that was not + // admissible by the goal dependency. + v Version +} + +func (e *constraintNotAllowedFailure) Error() string { + return fmt.Sprintf( + "Could not introduce %s, as it has a dependency on %s with constraint %s, which does not allow the currently selected version of %s", + a2vs(e.goal.depender), + e.goal.dep.Ident, + e.goal.dep.Constraint, + e.v, + ) +} + +func (e *constraintNotAllowedFailure) traceString() string { + return fmt.Sprintf( + "%s depends on %s with %s, but that's already selected at %s", + a2vs(e.goal.depender), + e.goal.dep.Ident.ProjectRoot, + e.goal.dep.Constraint, + e.v, + ) +} + +// versionNotAllowedFailure describes a failure where an atom is rejected +// because its version is not allowed by current constraints. +// +// (This is one of the more straightforward types of failures) +type versionNotAllowedFailure struct { + // goal is the atom that was rejected by current constraints. + goal atom + // failparent is the list of active dependencies that caused the atom to be + // rejected. Note that this only includes dependencies that actually + // rejected the atom, which will be at least one, but may not be all the + // active dependencies on the atom's identifier. + failparent []dependency + // c is the current constraint on the atom's identifier. This is the intersection + // of all active dependencies' constraints. + c Constraint +} + +func (e *versionNotAllowedFailure) Error() string { + if len(e.failparent) == 1 { + return fmt.Sprintf( + "Could not introduce %s, as it is not allowed by constraint %s from project %s.", + a2vs(e.goal), + e.failparent[0].dep.Constraint.String(), + e.failparent[0].depender.id, + ) + } + + var buf bytes.Buffer + + fmt.Fprintf(&buf, "Could not introduce %s, as it is not allowed by constraints from the following projects:\n", a2vs(e.goal)) + + for _, f := range e.failparent { + fmt.Fprintf(&buf, "\t%s from %s\n", f.dep.Constraint.String(), a2vs(f.depender)) + } + + return buf.String() +} + +func (e *versionNotAllowedFailure) traceString() string { + var buf bytes.Buffer + + fmt.Fprintf(&buf, "%s not allowed by constraint %s:\n", a2vs(e.goal), e.c.String()) + for _, f := range e.failparent { + fmt.Fprintf(&buf, " %s from %s\n", f.dep.Constraint.String(), a2vs(f.depender)) + } + + return buf.String() +} + +type missingSourceFailure struct { + goal ProjectIdentifier + prob string +} + +func (e *missingSourceFailure) Error() string { + return fmt.Sprintf(e.prob, e.goal) +} + +type badOptsFailure string + +func (e badOptsFailure) Error() string { + return string(e) +} + +type sourceMismatchFailure struct { + // The ProjectRoot over which there is disagreement about where it should be + // sourced from + shared ProjectRoot + // The current value for the network source + current string + // The mismatched value for the network source + mismatch string + // The currently selected dependencies which have agreed upon/established + // the given network source + sel []dependency + // The atom with the constraint that has the new, incompatible network source + prob atom +} + +func (e *sourceMismatchFailure) Error() string { + var cur []string + for _, c := range e.sel { + cur = append(cur, string(c.depender.id.ProjectRoot)) + } + + str := "Could not introduce %s, as it depends on %s from %s, but %s is already marked as coming from %s by %s" + return fmt.Sprintf(str, a2vs(e.prob), e.shared, e.mismatch, e.shared, e.current, strings.Join(cur, ", ")) +} + +func (e *sourceMismatchFailure) traceString() string { + var buf bytes.Buffer + fmt.Fprintf(&buf, "disagreement on network addr for %s:\n", e.shared) + + fmt.Fprintf(&buf, " %s from %s\n", e.mismatch, e.prob.id) + for _, dep := range e.sel { + fmt.Fprintf(&buf, " %s from %s\n", e.current, dep.depender.id) + } + + return buf.String() +} + +type errDeppers struct { + err error + deppers []atom +} + +// checkeeHasProblemPackagesFailure indicates that the goal atom was rejected +// because one or more of the packages required by its deppers had errors. +// +// "errors" includes package nonexistence, which is indicated by a nil err in +// the corresponding errDeppers failpkg map value. +// +// checkeeHasProblemPackagesFailure complements depHasProblemPackagesFailure; +// one or the other could appear to describe the same fundamental issue, +// depending on the order in which dependencies were visited. +type checkeeHasProblemPackagesFailure struct { + // goal is the atom that was rejected due to problematic packages. + goal atom + // failpkg is a map of package names to the error describing the problem + // with them, plus a list of the selected atoms that require that package. + failpkg map[string]errDeppers +} + +func (e *checkeeHasProblemPackagesFailure) Error() string { + var buf bytes.Buffer + indent := "" + + if len(e.failpkg) > 1 { + indent = "\t" + fmt.Fprintf( + &buf, "Could not introduce %s due to multiple problematic subpackages:\n", + a2vs(e.goal), + ) + } + + for pkg, errdep := range e.failpkg { + var cause string + if errdep.err == nil { + cause = "is missing" + } else { + cause = fmt.Sprintf("does not contain usable Go code (%T).", errdep.err) + } + + if len(e.failpkg) == 1 { + fmt.Fprintf( + &buf, "Could not introduce %s, as its subpackage %s %s.", + a2vs(e.goal), + pkg, + cause, + ) + } else { + fmt.Fprintf(&buf, "\tSubpackage %s %s.", pkg, cause) + } + + if len(errdep.deppers) == 1 { + fmt.Fprintf( + &buf, " (Package is required by %s.)", + a2vs(errdep.deppers[0]), + ) + } else { + fmt.Fprintf(&buf, " Package is required by:") + for _, pa := range errdep.deppers { + fmt.Fprintf(&buf, "\n%s\t%s", indent, a2vs(pa)) + } + } + } + + return buf.String() +} + +func (e *checkeeHasProblemPackagesFailure) traceString() string { + var buf bytes.Buffer + + fmt.Fprintf(&buf, "%s at %s has problem subpkg(s):\n", e.goal.id.ProjectRoot, e.goal.v) + for pkg, errdep := range e.failpkg { + if errdep.err == nil { + fmt.Fprintf(&buf, "\t%s is missing; ", pkg) + } else { + fmt.Fprintf(&buf, "\t%s has err (%T); ", pkg, errdep.err) + } + + if len(errdep.deppers) == 1 { + fmt.Fprintf(&buf, "required by %s.", a2vs(errdep.deppers[0])) + } else { + fmt.Fprintf(&buf, " required by:") + for _, pa := range errdep.deppers { + fmt.Fprintf(&buf, "\n\t\t%s at %s", pa.id, pa.v) + } + } + } + + return buf.String() +} + +// depHasProblemPackagesFailure indicates that the goal dependency was rejected +// because there were problems with one or more of the packages the dependency +// requires in the atom currently selected for that dependency. (This failure +// can only occur if the target dependency is already selected.) +// +// "errors" includes package nonexistence, which is indicated by a nil err as +// the corresponding prob map value. +// +// depHasProblemPackagesFailure complements checkeeHasProblemPackagesFailure; +// one or the other could appear to describe the same fundamental issue, +// depending on the order in which dependencies were visited. +type depHasProblemPackagesFailure struct { + // goal is the dependency that was rejected due to the atom currently + // selected for the dependency's target id having errors (including, and + // probably most commonly, + // nonexistence) in one or more packages named by the dependency. + goal dependency + // v is the version of the currently selected atom targeted by the goal + // dependency. + v Version + // prob is a map of problem packages to their specific error. It does not + // include missing packages. + prob map[string]error +} + +func (e *depHasProblemPackagesFailure) Error() string { + fcause := func(pkg string) string { + if err := e.prob[pkg]; err != nil { + return fmt.Sprintf("does not contain usable Go code (%T).", err) + } + return "is missing." + } + + if len(e.prob) == 1 { + var pkg string + for pkg = range e.prob { + } + + return fmt.Sprintf( + "Could not introduce %s, as it requires package %s from %s, but in version %s that package %s", + a2vs(e.goal.depender), + pkg, + e.goal.dep.Ident, + e.v, + fcause(pkg), + ) + } + + var buf bytes.Buffer + fmt.Fprintf( + &buf, "Could not introduce %s, as it requires problematic packages from %s (current version %s):", + a2vs(e.goal.depender), + e.goal.dep.Ident, + e.v, + ) + + pkgs := make([]string, len(e.prob)) + k := 0 + for pkg := range e.prob { + pkgs[k] = pkg + k++ + } + sort.Strings(pkgs) + for _, pkg := range pkgs { + fmt.Fprintf(&buf, "\t%s %s", pkg, fcause(pkg)) + } + + return buf.String() +} + +func (e *depHasProblemPackagesFailure) traceString() string { + var buf bytes.Buffer + fcause := func(pkg string) string { + if err := e.prob[pkg]; err != nil { + return fmt.Sprintf("has parsing err (%T).", err) + } + return "is missing" + } + + fmt.Fprintf( + &buf, "%s depping on %s at %s has problem subpkg(s):", + a2vs(e.goal.depender), + e.goal.dep.Ident, + e.v, + ) + + pkgs := make([]string, len(e.prob)) + k := 0 + for pkg := range e.prob { + pkgs[k] = pkg + k++ + } + sort.Strings(pkgs) + for _, pkg := range pkgs { + fmt.Fprintf(&buf, "\t%s %s", pkg, fcause(pkg)) + } + + return buf.String() +} + +// nonexistentRevisionFailure indicates that a revision constraint was specified +// for a given project, but that that revision does not exist in the source +// repository. +type nonexistentRevisionFailure struct { + goal dependency + r Revision +} + +func (e *nonexistentRevisionFailure) Error() string { + return fmt.Sprintf( + "Could not introduce %s, as it requires %s at revision %s, but that revision does not exist", + a2vs(e.goal.depender), + e.goal.dep.Ident, + e.r, + ) +} + +func (e *nonexistentRevisionFailure) traceString() string { + return fmt.Sprintf( + "%s wants missing rev %s of %s", + a2vs(e.goal.depender), + e.r, + e.goal.dep.Ident, + ) +} diff --git a/vendor/github.com/golang/dep/gps/solve_test.go b/vendor/github.com/golang/dep/gps/solve_test.go new file mode 100644 index 00000000..607bcd7e --- /dev/null +++ b/vendor/github.com/golang/dep/gps/solve_test.go @@ -0,0 +1,259 @@ +// Copyright 2017 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 gps + +import ( + "bytes" + "context" + "fmt" + "log" + "reflect" + "sort" + "testing" + + "github.com/golang/dep/internal/test" +) + +// overrideMkBridge overrides the base bridge with the depspecBridge that skips +// verifyRootDir calls +func overrideMkBridge(s *solver, sm SourceManager, down bool) sourceBridge { + return &depspecBridge{mkBridge(s, sm, down)} +} + +func fixSolve(params SolveParameters, sm SourceManager, t *testing.T) (Solution, error) { + // Trace unconditionally; by passing the trace through t.Log(), the testing + // system will decide whether or not to actually show the output (based on + // -v, or selectively on test failure). + params.TraceLogger = log.New(test.Writer{TB: t}, "", 0) + // always return false, otherwise it would identify pretty much all of + // our fixtures as being stdlib and skip everything + params.stdLibFn = func(string) bool { return false } + params.mkBridgeFn = overrideMkBridge + s, err := Prepare(params, sm) + if err != nil { + return nil, err + } + + return s.Solve(context.Background()) +} + +// Test all the basic table fixtures. +// +// Or, just the one named in the fix arg. +func TestBasicSolves(t *testing.T) { + // sort them by their keys so we get stable output + names := make([]string, 0, len(basicFixtures)) + for n := range basicFixtures { + names = append(names, n) + } + + sort.Strings(names) + for _, n := range names { + n := n + t.Run(n, func(t *testing.T) { + t.Parallel() + solveBasicsAndCheck(basicFixtures[n], t) + }) + } +} + +func solveBasicsAndCheck(fix basicFixture, t *testing.T) (res Solution, err error) { + sm := newdepspecSM(fix.ds, nil) + if fix.broken != "" { + t.Skip(fix.broken) + } + + params := SolveParameters{ + RootDir: string(fix.ds[0].n), + RootPackageTree: fix.rootTree(), + Manifest: fix.rootmanifest(), + Lock: dummyLock{}, + Downgrade: fix.downgrade, + ChangeAll: fix.changeall, + ToChange: fix.changelist, + ProjectAnalyzer: naiveAnalyzer{}, + } + + if fix.l != nil { + params.Lock = fix.l + } + + res, err = fixSolve(params, sm, t) + + return fixtureSolveSimpleChecks(fix, res, err, t) +} + +// Test all the bimodal table fixtures. +// +// Or, just the one named in the fix arg. +func TestBimodalSolves(t *testing.T) { + // sort them by their keys so we get stable output + names := make([]string, 0, len(bimodalFixtures)) + for n := range bimodalFixtures { + names = append(names, n) + } + + sort.Strings(names) + for _, n := range names { + n := n + t.Run(n, func(t *testing.T) { + t.Parallel() + solveBimodalAndCheck(bimodalFixtures[n], t) + }) + } +} + +func solveBimodalAndCheck(fix bimodalFixture, t *testing.T) (res Solution, err error) { + sm := newbmSM(fix) + if fix.broken != "" { + t.Skip(fix.broken) + } + + params := SolveParameters{ + RootDir: string(fix.ds[0].n), + RootPackageTree: fix.rootTree(), + Manifest: fix.rootmanifest(), + Lock: dummyLock{}, + Downgrade: fix.downgrade, + ChangeAll: fix.changeall, + ProjectAnalyzer: naiveAnalyzer{}, + } + + if fix.l != nil { + params.Lock = fix.l + } + + res, err = fixSolve(params, sm, t) + + return fixtureSolveSimpleChecks(fix, res, err, t) +} + +func fixtureSolveSimpleChecks(fix specfix, soln Solution, err error, t *testing.T) (Solution, error) { + ppi := func(id ProjectIdentifier) string { + // need this so we can clearly tell if there's a Source or not + if id.Source == "" { + return string(id.ProjectRoot) + } + return fmt.Sprintf("%s (from %s)", id.ProjectRoot, id.Source) + } + + pv := func(v Version) string { + if pv, ok := v.(PairedVersion); ok { + return fmt.Sprintf("%s (%s)", pv.Unpair(), pv.Revision()) + } + return v.String() + } + + fixfail := fix.failure() + if err != nil { + if fixfail == nil { + t.Errorf("Solve failed unexpectedly:\n%s", err) + } else if !(fixfail.Error() == err.Error()) { + // TODO(sdboyer) reflect.DeepEqual works for now, but once we start + // modeling more complex cases, this should probably become more robust + t.Errorf("Failure mismatch:\n\t(GOT): %s\n\t(WNT): %s", err, fixfail) + } + } else if fixfail != nil { + var buf bytes.Buffer + fmt.Fprintf(&buf, "Solver succeeded, but expecting failure:\n%s\nProjects in solution:", fixfail) + for _, p := range soln.Projects() { + fmt.Fprintf(&buf, "\n\t- %s at %s", ppi(p.Ident()), p.Version()) + } + t.Error(buf.String()) + } else { + r := soln.(solution) + if fix.maxTries() > 0 && r.Attempts() > fix.maxTries() { + t.Errorf("Solver completed in %v attempts, but expected %v or fewer", r.att, fix.maxTries()) + } + + // Dump result projects into a map for easier interrogation + rp := make(map[ProjectIdentifier]LockedProject) + for _, lp := range r.p { + rp[lp.pi] = lp + } + + fixlen, rlen := len(fix.solution()), len(rp) + if fixlen != rlen { + // Different length, so they definitely disagree + t.Errorf("Solver reported %v package results, result expected %v", rlen, fixlen) + } + + // Whether or not len is same, still have to verify that results agree + // Walk through fixture/expected results first + for id, flp := range fix.solution() { + if lp, exists := rp[id]; !exists { + t.Errorf("Project %q expected but missing from results", ppi(id)) + } else { + // delete result from map so we skip it on the reverse pass + delete(rp, id) + if flp.Version() != lp.Version() { + t.Errorf("Expected version %q of project %q, but actual version was %q", pv(flp.Version()), ppi(id), pv(lp.Version())) + } + + if !reflect.DeepEqual(lp.pkgs, flp.pkgs) { + t.Errorf("Package list was not not as expected for project %s@%s:\n\t(GOT) %s\n\t(WNT) %s", ppi(id), pv(lp.Version()), lp.pkgs, flp.pkgs) + } + } + } + + // Now walk through remaining actual results + for id, lp := range rp { + if _, exists := fix.solution()[id]; !exists { + t.Errorf("Unexpected project %s@%s present in results, with pkgs:\n\t%s", ppi(id), pv(lp.Version()), lp.pkgs) + } + } + } + + return soln, err +} + +// This tests that, when a root lock is underspecified (has only a version) we +// don't allow a match on that version from a rev in the manifest. We may allow +// this in the future, but disallow it for now because going from an immutable +// requirement to a mutable lock automagically is a bad direction that could +// produce weird side effects. +func TestRootLockNoVersionPairMatching(t *testing.T) { + fix := basicFixture{ + n: "does not match unpaired lock versions with paired real versions", + ds: []depspec{ + mkDepspec("root 0.0.0", "foo *"), // foo's constraint rewritten below to foorev + mkDepspec("foo 1.0.0", "bar 1.0.0"), + mkDepspec("foo 1.0.1 foorev", "bar 1.0.1"), + mkDepspec("foo 1.0.2 foorev", "bar 1.0.2"), + mkDepspec("bar 1.0.0"), + mkDepspec("bar 1.0.1"), + mkDepspec("bar 1.0.2"), + }, + l: mklock( + "foo 1.0.1", + ), + r: mksolution( + "foo 1.0.2 foorev", + "bar 1.0.2", + ), + } + + pd := fix.ds[0].deps[0] + pd.Constraint = Revision("foorev") + fix.ds[0].deps[0] = pd + + sm := newdepspecSM(fix.ds, nil) + + l2 := make(fixLock, 1) + copy(l2, fix.l) + l2[0].v = nil + + params := SolveParameters{ + RootDir: string(fix.ds[0].n), + RootPackageTree: fix.rootTree(), + Manifest: fix.rootmanifest(), + Lock: l2, + ProjectAnalyzer: naiveAnalyzer{}, + } + + res, err := fixSolve(params, sm, t) + + fixtureSolveSimpleChecks(fix, res, err, t) +} diff --git a/vendor/github.com/golang/dep/gps/solver.go b/vendor/github.com/golang/dep/gps/solver.go new file mode 100644 index 00000000..bede9d53 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/solver.go @@ -0,0 +1,1421 @@ +// Copyright 2017 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 gps + +import ( + "container/heap" + "context" + "fmt" + "log" + "sort" + "strings" + "sync" + "sync/atomic" + + "github.com/armon/go-radix" + "github.com/golang/dep/gps/paths" + "github.com/golang/dep/gps/pkgtree" + "github.com/pkg/errors" +) + +var rootRev = Revision("") + +// SolveParameters hold all arguments to a solver run. +// +// Only RootDir and RootPackageTree are absolutely required. A nil Manifest is +// allowed, though it usually makes little sense. +// +// Of these properties, only the Manifest and RootPackageTree are (directly) +// incorporated in memoization hashing. +type SolveParameters struct { + // The path to the root of the project on which the solver should operate. + // This should point to the directory that should contain the vendor/ + // directory. + // + // In general, it is wise for this to be under an active GOPATH, though it + // is not (currently) required. + // + // A real path to a readable directory is required. + RootDir string + + // The ProjectAnalyzer is responsible for extracting Manifest and + // (optionally) Lock information from dependencies. The solver passes it + // along to its SourceManager's GetManifestAndLock() method as needed. + // + // An analyzer is required. + ProjectAnalyzer ProjectAnalyzer + + // The tree of packages that comprise the root project, as well as the + // import path that should identify the root of that tree. + // + // In most situations, tools should simply pass the result of ListPackages() + // directly through here. + // + // The ImportRoot property must be a non-empty string, and at least one + // element must be present in the Packages map. + RootPackageTree pkgtree.PackageTree + + // The root manifest. This contains all the dependency constraints + // associated with normal Manifests, as well as the particular controls + // afforded only to the root project. + // + // May be nil, but for most cases, that would be unwise. + Manifest RootManifest + + // The root lock. Optional. Generally, this lock is the output of a previous + // solve run. + // + // If provided, the solver will attempt to preserve the versions specified + // in the lock, unless ToChange or ChangeAll settings indicate otherwise. + Lock Lock + + // ToChange is a list of project names that should be changed - that is, any + // versions specified for those projects in the root lock file should be + // ignored. + // + // Passing ChangeAll has subtly different behavior from enumerating all + // projects into ToChange. In general, ToChange should *only* be used if the + // user expressly requested an upgrade for a specific project. + ToChange []ProjectRoot + + // ChangeAll indicates that all projects should be changed - that is, any + // versions specified in the root lock file should be ignored. + ChangeAll bool + + // Downgrade indicates whether the solver will attempt to upgrade (false) or + // downgrade (true) projects that are not locked, or are marked for change. + // + // Upgrading is, by far, the most typical case. The field is named + // 'Downgrade' so that the bool's zero value corresponds to that most + // typical case. + Downgrade bool + + // TraceLogger is the logger to use for generating trace output. If set, the + // solver will generate informative trace output as it moves through the + // solving process. + TraceLogger *log.Logger + + // stdLibFn is the function to use to recognize standard library import paths. + // Only overridden for tests. Defaults to paths.IsStandardImportPath if nil. + stdLibFn func(string) bool + + // mkBridgeFn is the function to use to create sourceBridges. + // Only overridden for tests (so we can run with virtual RootDir). + // Defaults to mkBridge if nil. + mkBridgeFn func(*solver, SourceManager, bool) sourceBridge +} + +// solver is a CDCL-style constraint solver with satisfiability conditions +// hardcoded to the needs of the Go package management problem space. +type solver struct { + // The current number of attempts made over the course of this solve. This + // number increments each time the algorithm completes a backtrack and + // starts moving forward again. + attempts int + + // Logger used exclusively for trace output, or nil to suppress. + tl *log.Logger + + // The function to use to recognize standard library import paths. + stdLibFn func(string) bool + + // A bridge to the standard SourceManager. The adapter does some local + // caching of pre-sorted version lists, as well as translation between the + // full-on ProjectIdentifiers that the solver deals with and the simplified + // names a SourceManager operates on. + b sourceBridge + + // A versionUnifier, to facilitate cross-type version comparison and set + // operations. + vUnify *versionUnifier + + // A stack containing projects and packages that are currently "selected" - + // that is, they have passed all satisfiability checks, and are part of the + // current solution. + // + // The *selection type is mostly just a dumb data container; the solver + // itself is responsible for maintaining that invariant. + sel *selection + + // The current list of projects that we need to incorporate into the solution in + // order for the solution to be complete. This list is implemented as a + // priority queue that places projects least likely to induce errors at the + // front, in order to minimize the amount of backtracking required to find a + // solution. + // + // Entries are added to and removed from this list by the solver at the same + // time that the selected queue is updated, either with an addition or + // removal. + unsel *unselected + + // A stack of all the currently active versionQueues in the solver. The set + // of projects represented here corresponds closely to what's in s.sel, + // although s.sel will always contain the root project, and s.vqs never + // will. Also, s.vqs is only added to (or popped from during backtracking) + // when a new project is selected; it is untouched when new packages are + // added to an existing project. + vqs []*versionQueue + + // Contains data and constraining information from the root project + rd rootdata + + // metrics for the current solve run. + mtr *metrics + + // Indicates whether the solver has been run. It is invalid to run this type + // of solver more than once. + hasrun int32 +} + +func (params SolveParameters) toRootdata() (rootdata, error) { + if params.ProjectAnalyzer == nil { + return rootdata{}, badOptsFailure("must provide a ProjectAnalyzer") + } + if params.RootDir == "" { + return rootdata{}, badOptsFailure("params must specify a non-empty root directory") + } + if params.RootPackageTree.ImportRoot == "" { + return rootdata{}, badOptsFailure("params must include a non-empty import root") + } + if len(params.RootPackageTree.Packages) == 0 { + return rootdata{}, badOptsFailure("at least one package must be present in the PackageTree") + } + if params.Lock == nil && len(params.ToChange) != 0 { + return rootdata{}, badOptsFailure(fmt.Sprintf("update specifically requested for %s, but no lock was provided to upgrade from", params.ToChange)) + } + + if params.Manifest == nil { + params.Manifest = simpleRootManifest{} + } + + rd := rootdata{ + ir: params.Manifest.IgnoredPackages(), + req: params.Manifest.RequiredPackages(), + ovr: params.Manifest.Overrides(), + rpt: params.RootPackageTree.Copy(), + chng: make(map[ProjectRoot]struct{}), + rlm: make(map[ProjectRoot]LockedProject), + chngall: params.ChangeAll, + dir: params.RootDir, + an: params.ProjectAnalyzer, + } + + // Ensure the required and overrides maps are at least initialized + if rd.req == nil { + rd.req = make(map[string]bool) + } + if rd.ovr == nil { + rd.ovr = make(ProjectConstraints) + } + + if rd.ir.Len() > 0 { + var both []string + for pkg := range params.Manifest.RequiredPackages() { + if rd.ir.IsIgnored(pkg) { + both = append(both, pkg) + } + } + switch len(both) { + case 0: + break + case 1: + return rootdata{}, badOptsFailure(fmt.Sprintf("%q was given as both a required and ignored package", both[0])) + default: + return rootdata{}, badOptsFailure(fmt.Sprintf("multiple packages given as both required and ignored: %s", strings.Join(both, ", "))) + } + } + + // Validate no empties in the overrides map + var eovr []string + for pr, pp := range rd.ovr { + if pp.Constraint == nil && pp.Source == "" { + eovr = append(eovr, string(pr)) + } + } + + if eovr != nil { + // Maybe it's a little nitpicky to do this (we COULD proceed; empty + // overrides have no effect), but this errs on the side of letting the + // tool/user know there's bad input. Purely as a principle, that seems + // preferable to silently allowing progress with icky input. + if len(eovr) > 1 { + return rootdata{}, badOptsFailure(fmt.Sprintf("Overrides lacked any non-zero properties for multiple project roots: %s", strings.Join(eovr, " "))) + } + return rootdata{}, badOptsFailure(fmt.Sprintf("An override was declared for %s, but without any non-zero properties", eovr[0])) + } + + // Prep safe, normalized versions of root manifest and lock data + rd.rm = prepManifest(params.Manifest) + + if params.Lock != nil { + for _, lp := range params.Lock.Projects() { + rd.rlm[lp.Ident().ProjectRoot] = lp + } + + // Also keep a prepped one, mostly for the bridge. This is probably + // wasteful, but only minimally so, and yay symmetry + rd.rl = prepLock(params.Lock) + } + + for _, p := range params.ToChange { + if _, exists := rd.rlm[p]; !exists { + return rootdata{}, badOptsFailure(fmt.Sprintf("cannot update %s as it is not in the lock", p)) + } + rd.chng[p] = struct{}{} + } + + return rd, nil +} + +// Prepare readies a Solver for use. +// +// This function reads and validates the provided SolveParameters. If a problem +// with the inputs is detected, an error is returned. Otherwise, a Solver is +// returned, ready to hash and check inputs or perform a solving run. +func Prepare(params SolveParameters, sm SourceManager) (Solver, error) { + if sm == nil { + return nil, badOptsFailure("must provide non-nil SourceManager") + } + + rd, err := params.toRootdata() + if err != nil { + return nil, err + } + + if params.stdLibFn == nil { + params.stdLibFn = paths.IsStandardImportPath + } + + s := &solver{ + tl: params.TraceLogger, + stdLibFn: params.stdLibFn, + rd: rd, + } + + // Set up the bridge and ensure the root dir is in good, working order + // before doing anything else. + if params.mkBridgeFn == nil { + s.b = mkBridge(s, sm, params.Downgrade) + } else { + s.b = params.mkBridgeFn(s, sm, params.Downgrade) + } + err = s.b.verifyRootDir(params.RootDir) + if err != nil { + return nil, err + } + s.vUnify = &versionUnifier{ + b: s.b, + } + + // Initialize stacks and queues + s.sel = &selection{ + deps: make(map[ProjectRoot][]dependency), + foldRoots: make(map[string]ProjectRoot), + vu: s.vUnify, + } + s.unsel = &unselected{ + sl: make([]bimodalIdentifier, 0), + cmp: s.unselectedComparator, + } + + return s, nil +} + +// A Solver is the main workhorse of gps: given a set of project inputs, it +// performs a constraint solving analysis to develop a complete Solution, or +// else fail with an informative error. +// +// If a Solution is found, an implementing tool may persist it - typically into +// a "lock file" - and/or use it to write out a directory tree of dependencies, +// suitable to be a vendor directory, via CreateVendorTree. +type Solver interface { + // HashInputs hashes the unique inputs to this solver, returning the hash + // digest. It is guaranteed that, if the resulting digest is equal to the + // digest returned from a previous Solution.InputHash(), that that Solution + // is valid for this Solver's inputs. + // + // In such a case, it may not be necessary to run Solve() at all. + HashInputs() []byte + + // Solve initiates a solving run. It will either abort due to a canceled + // Context, complete successfully with a Solution, or fail with an + // informative error. + // + // It is generally not allowed that this method be called twice for any + // given solver. + Solve(context.Context) (Solution, error) + + // Name returns a string identifying the particular solver backend. + // + // Different solvers likely have different invariants, and likely will not + // have the same result sets for any particular inputs. + Name() string + + // Version returns an int indicating the version of the solver of the given + // Name(). Implementations should change their reported version ONLY when + // the logic is changed in such a way that substantially changes the result + // set that is possible for a substantial subset of likely inputs. + // + // "Substantial" is an imprecise term, and it is used intentionally. There + // are no easy, general ways of subdividing constraint solving problems such + // that one can know, a priori, the full impact that subtle algorithmic + // changes will have on possible result sets. Consequently, we have to fall + // back on coarser, intuition-based reasoning as to whether a change is + // large enough that it is likely to be broadly user-visible. + // + // This is acceptable, because this value is not used programmatically by + // the solver in any way. Rather, it is intend for implementing tools to + // use as a coarse signal to users about compatibility between their tool's + // version and the current data, typically via persistence to a Lock. + // Changes to the version number reported should be weighed between + // confusing teams by having two members' tools continuously rolling back + // each others' chosen Solutions for no apparent reason, and annoying teams + // by changing the number for changes so remote that warnings about solver + // version mismatches become meaningless. + // + // Err on the side of caution. + // + // Chronology is the only implication of the ordering - that lower version + // numbers were published before higher numbers. + Version() int +} + +func (s *solver) Name() string { + return "gps-cdcl" +} + +func (s *solver) Version() int { + return 1 +} + +// DeductionErrs maps package import path to errors occurring during deduction. +type DeductionErrs map[string]error + +func (e DeductionErrs) Error() string { + return "could not deduce external imports' project roots" +} + +// ValidateParams validates the solver parameters to ensure solving can be completed. +func ValidateParams(params SolveParameters, sm SourceManager) error { + // Ensure that all packages are deducible without issues. + var deducePkgsGroup sync.WaitGroup + deductionErrs := make(DeductionErrs) + var errsMut sync.Mutex + + rd, err := params.toRootdata() + if err != nil { + return err + } + + deducePkg := func(ip string, sm SourceManager) { + _, err := sm.DeduceProjectRoot(ip) + if err != nil { + errsMut.Lock() + deductionErrs[ip] = err + errsMut.Unlock() + } + deducePkgsGroup.Done() + } + + for _, ip := range rd.externalImportList(paths.IsStandardImportPath) { + deducePkgsGroup.Add(1) + go deducePkg(ip, sm) + } + + deducePkgsGroup.Wait() + + if len(deductionErrs) > 0 { + return deductionErrs + } + + return nil +} + +// Solve attempts to find a dependency solution for the given project, as +// represented by the SolveParameters with which this Solver was created. +// +// This is the entry point to the main gps workhorse. +func (s *solver) Solve(ctx context.Context) (Solution, error) { + // Solving can only be run once per solver. + if !atomic.CompareAndSwapInt32(&s.hasrun, 0, 1) { + return nil, errors.New("solve method can only be run once per instance") + } + // Make sure the bridge has the context before we start. + //s.b.ctx = ctx + + // Set up a metrics object + s.mtr = newMetrics() + s.vUnify.mtr = s.mtr + + // Prime the queues with the root project + if err := s.selectRoot(); err != nil { + return nil, err + } + + all, err := s.solve(ctx) + + s.mtr.pop() + var soln solution + if err == nil { + soln = solution{ + att: s.attempts, + solv: s, + } + soln.analyzerInfo = s.rd.an.Info() + soln.hd = s.HashInputs() + + // Convert ProjectAtoms into LockedProjects + soln.p = make([]LockedProject, len(all)) + k := 0 + for pa, pl := range all { + soln.p[k] = pa2lp(pa, pl) + k++ + } + } + + s.traceFinish(soln, err) + if s.tl != nil { + s.mtr.dump(s.tl) + } + return soln, err +} + +// solve is the top-level loop for the solving process. +func (s *solver) solve(ctx context.Context) (map[atom]map[string]struct{}, error) { + // Pull out the donechan once up front so that we're not potentially + // triggering mutex cycling and channel creation on each iteration. + donechan := ctx.Done() + + // Main solving loop + for { + select { + case <-donechan: + return nil, ctx.Err() + default: + } + + bmi, has := s.nextUnselected() + + if !has { + // no more packages to select - we're done. + break + } + + // This split is the heart of "bimodal solving": we follow different + // satisfiability and selection paths depending on whether we've already + // selected the base project/repo that came off the unselected queue. + // + // (If we've already selected the project, other parts of the algorithm + // guarantee the bmi will contain at least one package from this project + // that has yet to be selected.) + if awp, is := s.sel.selected(bmi.id); !is { + s.mtr.push("new-atom") + // Analysis path for when we haven't selected the project yet - need + // to create a version queue. + queue, err := s.createVersionQueue(bmi) + if err != nil { + s.mtr.pop() + // Err means a failure somewhere down the line; try backtracking. + s.traceStartBacktrack(bmi, err, false) + success, berr := s.backtrack(ctx) + if berr != nil { + err = berr + } else if success { + // backtracking succeeded, move to the next unselected id + continue + } + return nil, err + } + + if queue.current() == nil { + panic("canary - queue is empty, but flow indicates success") + } + + awp := atomWithPackages{ + a: atom{ + id: queue.id, + v: queue.current(), + }, + pl: bmi.pl, + } + err = s.selectAtom(awp, false) + s.mtr.pop() + if err != nil { + // Only a released SourceManager should be able to cause this. + return nil, err + } + + s.vqs = append(s.vqs, queue) + } else { + s.mtr.push("add-atom") + // We're just trying to add packages to an already-selected project. + // That means it's not OK to burn through the version queue for that + // project as we do when first selecting a project, as doing so + // would upend the guarantees on which all previous selections of + // the project are based (both the initial one, and any package-only + // ones). + + // Because we can only safely operate within the scope of the + // single, currently selected version, we can skip looking for the + // queue and just use the version given in what came back from + // s.sel.selected(). + nawp := atomWithPackages{ + a: atom{ + id: bmi.id, + v: awp.a.v, + }, + pl: bmi.pl, + } + + s.traceCheckPkgs(bmi) + err := s.check(nawp, true) + if err != nil { + s.mtr.pop() + // Err means a failure somewhere down the line; try backtracking. + s.traceStartBacktrack(bmi, err, true) + success, berr := s.backtrack(ctx) + if berr != nil { + err = berr + } else if success { + // backtracking succeeded, move to the next unselected id + continue + } + return nil, err + } + err = s.selectAtom(nawp, true) + s.mtr.pop() + if err != nil { + // Only a released SourceManager should be able to cause this. + return nil, err + } + + // We don't add anything to the stack of version queues because the + // backtracker knows not to pop the vqstack if it backtracks + // across a pure-package addition. + } + } + + // Getting this far means we successfully found a solution. Combine the + // selected projects and packages. + projs := make(map[atom]map[string]struct{}) + + // Skip the first project. It's always the root, and that shouldn't be + // included in results. + for _, sel := range s.sel.projects[1:] { + pm, exists := projs[sel.a.a] + if !exists { + pm = make(map[string]struct{}) + projs[sel.a.a] = pm + } + + for _, path := range sel.a.pl { + pm[path] = struct{}{} + } + } + return projs, nil +} + +// selectRoot is a specialized selectAtom, used solely to initially +// populate the queues at the beginning of a solve run. +func (s *solver) selectRoot() error { + s.mtr.push("select-root") + // Push the root project onto the queue. + awp := s.rd.rootAtom() + s.sel.pushSelection(awp, false) + + // If we're looking for root's deps, get it from opts and local root + // analysis, rather than having the sm do it. + deps, err := s.intersectConstraintsWithImports(s.rd.combineConstraints(), s.rd.externalImportList(s.stdLibFn)) + if err != nil { + if contextCanceledOrSMReleased(err) { + return err + } + // TODO(sdboyer) this could well happen; handle it with a more graceful error + panic(fmt.Sprintf("canary - shouldn't be possible %s", err)) + } + + for _, dep := range deps { + // If we have no lock, or if this dep isn't in the lock, then prefetch + // it. See longer explanation in selectAtom() for how we benefit from + // parallelism here. + if s.rd.needVersionsFor(dep.Ident.ProjectRoot) { + go s.b.SyncSourceFor(dep.Ident) + } + + s.sel.pushDep(dependency{depender: awp.a, dep: dep}) + // Add all to unselected queue + heap.Push(s.unsel, bimodalIdentifier{id: dep.Ident, pl: dep.pl, fromRoot: true}) + } + + s.traceSelectRoot(s.rd.rpt, deps) + s.mtr.pop() + return nil +} + +func (s *solver) getImportsAndConstraintsOf(a atomWithPackages) ([]string, []completeDep, error) { + var err error + + if s.rd.isRoot(a.a.id.ProjectRoot) { + panic("Should never need to recheck imports/constraints from root during solve") + } + + // Work through the source manager to get project info and static analysis + // information. + m, _, err := s.b.GetManifestAndLock(a.a.id, a.a.v, s.rd.an) + if err != nil { + return nil, nil, err + } + + ptree, err := s.b.ListPackages(a.a.id, a.a.v) + if err != nil { + return nil, nil, err + } + + rm, em := ptree.ToReachMap(true, false, true, s.rd.ir) + // Use maps to dedupe the unique internal and external packages. + exmap, inmap := make(map[string]struct{}), make(map[string]struct{}) + + for _, pkg := range a.pl { + inmap[pkg] = struct{}{} + for _, ipkg := range rm[pkg].Internal { + inmap[ipkg] = struct{}{} + } + } + + var pl []string + // If lens are the same, then the map must have the same contents as the + // slice; no need to build a new one. + if len(inmap) == len(a.pl) { + pl = a.pl + } else { + pl = make([]string, 0, len(inmap)) + for pkg := range inmap { + pl = append(pl, pkg) + } + sort.Strings(pl) + } + + // Add to the list those packages that are reached by the packages + // explicitly listed in the atom + for _, pkg := range a.pl { + // Skip ignored packages + if s.rd.ir.IsIgnored(pkg) { + continue + } + + ie, exists := rm[pkg] + if !exists { + // Missing package here *should* only happen if the target pkg was + // poisoned; check the errors map. + if importErr, eexists := em[pkg]; eexists { + return nil, nil, importErr + } + + // Nope, it's actually full-on not there. + return nil, nil, fmt.Errorf("package %s does not exist within project %s", pkg, a.a.id) + } + + for _, ex := range ie.External { + exmap[ex] = struct{}{} + } + } + + reach := make([]string, 0, len(exmap)) + for pkg := range exmap { + reach = append(reach, pkg) + } + sort.Strings(reach) + + deps := s.rd.ovr.overrideAll(m.DependencyConstraints()) + cd, err := s.intersectConstraintsWithImports(deps, reach) + return pl, cd, err +} + +// intersectConstraintsWithImports takes a list of constraints and a list of +// externally reached packages, and creates a []completeDep that is guaranteed +// to include all packages named by import reach, using constraints where they +// are available, or Any() where they are not. +func (s *solver) intersectConstraintsWithImports(deps []workingConstraint, reach []string) ([]completeDep, error) { + // Create a radix tree with all the projects we know from the manifest + xt := radix.New() + for _, dep := range deps { + xt.Insert(string(dep.Ident.ProjectRoot), dep) + } + + // Step through the reached packages; if they have prefix matches in + // the trie, assume (mostly) it's a correct correspondence. + dmap := make(map[ProjectRoot]completeDep) + for _, rp := range reach { + // If it's a stdlib-shaped package, skip it. + if s.stdLibFn(rp) { + continue + } + + // Look for a prefix match; it'll be the root project/repo containing + // the reached package + if pre, idep, match := xt.LongestPrefix(rp); match && isPathPrefixOrEqual(pre, rp) { + // Match is valid; put it in the dmap, either creating a new + // completeDep or appending it to the existing one for this base + // project/prefix. + dep := idep.(workingConstraint) + if cdep, exists := dmap[dep.Ident.ProjectRoot]; exists { + cdep.pl = append(cdep.pl, rp) + dmap[dep.Ident.ProjectRoot] = cdep + } else { + dmap[dep.Ident.ProjectRoot] = completeDep{ + workingConstraint: dep, + pl: []string{rp}, + } + } + continue + } + + // No match. Let the SourceManager try to figure out the root + root, err := s.b.DeduceProjectRoot(rp) + if err != nil { + // Nothing we can do if we can't suss out a root + return nil, err + } + + // Make a new completeDep with an open constraint, respecting overrides + pd := s.rd.ovr.override(root, ProjectProperties{Constraint: Any()}) + + // Insert the pd into the trie so that further deps from this + // project get caught by the prefix search + xt.Insert(string(root), pd) + // And also put the complete dep into the dmap + dmap[root] = completeDep{ + workingConstraint: pd, + pl: []string{rp}, + } + } + + // Dump all the deps from the map into the expected return slice + cdeps := make([]completeDep, 0, len(dmap)) + for _, cdep := range dmap { + cdeps = append(cdeps, cdep) + } + + return cdeps, nil +} + +func (s *solver) createVersionQueue(bmi bimodalIdentifier) (*versionQueue, error) { + id := bmi.id + // If on the root package, there's no queue to make + if s.rd.isRoot(id.ProjectRoot) { + return newVersionQueue(id, nil, nil, s.b) + } + + exists, err := s.b.SourceExists(id) + if err != nil { + return nil, err + } + if !exists { + exists, err = s.b.vendorCodeExists(id) + if err != nil { + return nil, err + } + if exists { + // Project exists only in vendor + // FIXME(sdboyer) this just totally doesn't work at all right now + } else { + return nil, fmt.Errorf("project '%s' could not be located", id) + } + } + + var lockv Version + if len(s.rd.rlm) > 0 { + lockv, err = s.getLockVersionIfValid(id) + if err != nil { + // Can only get an error here if an upgrade was expressly requested on + // code that exists only in vendor + return nil, err + } + } + + var prefv Version + if bmi.fromRoot { + // If this bmi came from the root, then we want to search through things + // with a dependency on it in order to see if any have a lock that might + // express a prefv + // + // TODO(sdboyer) nested loop; prime candidate for a cache somewhere + for _, dep := range s.sel.getDependenciesOn(bmi.id) { + // Skip the root, of course + if s.rd.isRoot(dep.depender.id.ProjectRoot) { + continue + } + + _, l, err := s.b.GetManifestAndLock(dep.depender.id, dep.depender.v, s.rd.an) + if err != nil || l == nil { + // err being non-nil really shouldn't be possible, but the lock + // being nil is quite likely + continue + } + + for _, lp := range l.Projects() { + if lp.Ident().eq(bmi.id) { + prefv = lp.Version() + } + } + } + + // OTHER APPROACH - WRONG, BUT MAYBE USEFUL FOR REFERENCE? + // If this bmi came from the root, then we want to search the unselected + // queue to see if anything *else* wants this ident, in which case we + // pick up that prefv + //for _, bmi2 := range s.unsel.sl { + //// Take the first thing from the queue that's for the same ident, + //// and has a non-nil prefv + //if bmi.id.eq(bmi2.id) { + //if bmi2.prefv != nil { + //prefv = bmi2.prefv + //} + //} + //} + + } else { + // Otherwise, just use the preferred version expressed in the bmi + prefv = bmi.prefv + } + + q, err := newVersionQueue(id, lockv, prefv, s.b) + if err != nil { + // TODO(sdboyer) this particular err case needs to be improved to be ONLY for cases + // where there's absolutely nothing findable about a given project name + return nil, err + } + + // Hack in support for revisions. + // + // By design, revs aren't returned from ListVersion(). Thus, if the dep in + // the bmi was has a rev constraint, it is (almost) guaranteed to fail, even + // if that rev does exist in the repo. So, detect a rev and push it into the + // vq here, instead. + // + // Happily, the solver maintains the invariant that constraints on a given + // ident cannot be incompatible, so we know that if we find one rev, then + // any other deps will have to also be on that rev (or Any). + // + // TODO(sdboyer) while this does work, it bypasses the interface-implied guarantees + // of the version queue, and is therefore not a great strategy for API + // coherency. Folding this in to a formal interface would be better. + if tc, ok := s.sel.getConstraint(bmi.id).(Revision); ok && q.pi[0] != tc { + // We know this is the only thing that could possibly match, so put it + // in at the front - if it isn't there already. + // TODO(sdboyer) existence of the revision is guaranteed by checkRevisionExists(); restore that call. + q.pi = append([]Version{tc}, q.pi...) + } + + // Having assembled the queue, search it for a valid version. + s.traceCheckQueue(q, bmi, false, 1) + return q, s.findValidVersion(q, bmi.pl) +} + +// findValidVersion walks through a versionQueue until it finds a version that +// satisfies the constraints held in the current state of the solver. +// +// The satisfiability checks triggered from here are constrained to operate only +// on those dependencies induced by the list of packages given in the second +// parameter. +func (s *solver) findValidVersion(q *versionQueue, pl []string) error { + if nil == q.current() { + // this case should not be reachable, but reflects improper solver state + // if it is, so panic immediately + panic("version queue is empty, should not happen") + } + + faillen := len(q.fails) + + for { + cur := q.current() + s.traceInfo("try %s@%s", q.id, cur) + err := s.check(atomWithPackages{ + a: atom{ + id: q.id, + v: cur, + }, + pl: pl, + }, false) + if err == nil { + // we have a good version, can return safely + return nil + } + + if q.advance(err) != nil { + // Error on advance, have to bail out + break + } + if q.isExhausted() { + // Queue is empty, bail with error + break + } + } + + s.fail(s.sel.getDependenciesOn(q.id)[0].depender.id) + + // Return a compound error of all the new errors encountered during this + // attempt to find a new, valid version + return &noVersionError{ + pn: q.id, + fails: q.fails[faillen:], + } +} + +// getLockVersionIfValid finds an atom for the given ProjectIdentifier from the +// root lock, assuming: +// +// 1. A root lock was provided +// 2. The general flag to change all projects was not passed +// 3. A flag to change this particular ProjectIdentifier was not passed +// +// If any of these three conditions are true (or if the id cannot be found in +// the root lock), then no atom will be returned. +func (s *solver) getLockVersionIfValid(id ProjectIdentifier) (Version, error) { + // If the project is specifically marked for changes, then don't look for a + // locked version. + if _, explicit := s.rd.chng[id.ProjectRoot]; explicit || s.rd.chngall { + // For projects with an upstream or cache repository, it's safe to + // ignore what's in the lock, because there's presumably more versions + // to be found and attempted in the repository. If it's only in vendor, + // though, then we have to try to use what's in the lock, because that's + // the only version we'll be able to get. + if exist, _ := s.b.SourceExists(id); exist { + // Upgrades mean breaking the lock + s.b.breakLock() + return nil, nil + } + + // However, if a change was *expressly* requested for something that + // exists only in vendor, then that guarantees we don't have enough + // information to complete a solution. In that case, error out. + if explicit { + return nil, &missingSourceFailure{ + goal: id, + prob: "Cannot upgrade %s, as no source repository could be found.", + } + } + } + + lp, exists := s.rd.rlm[id.ProjectRoot] + if !exists { + return nil, nil + } + + constraint := s.sel.getConstraint(id) + v := lp.Version() + if !constraint.Matches(v) { + var found bool + if tv, ok := v.(Revision); ok { + // If we only have a revision from the root's lock, allow matching + // against other versions that have that revision + for _, pv := range s.vUnify.pairRevision(id, tv) { + if constraint.Matches(pv) { + v = pv + found = true + break + } + } + //} else if _, ok := constraint.(Revision); ok { + //// If the current constraint is itself a revision, and the lock gave + //// an unpaired version, see if they match up + //// + //if u, ok := v.(UnpairedVersion); ok { + //pv := s.sm.pairVersion(id, u) + //if constraint.Matches(pv) { + //v = pv + //found = true + //} + //} + } + + if !found { + // No match found, which means we're going to be breaking the lock + // Still return the invalid version so that is included in the trace + s.b.breakLock() + } + } + + return v, nil +} + +// backtrack works backwards from the current failed solution to find the next +// solution to try. +func (s *solver) backtrack(ctx context.Context) (bool, error) { + if len(s.vqs) == 0 { + // nothing to backtrack to + return false, nil + } + + donechan := ctx.Done() + s.mtr.push("backtrack") + defer s.mtr.pop() + for { + for { + select { + case <-donechan: + return false, ctx.Err() + default: + } + + if len(s.vqs) == 0 { + // no more versions, nowhere further to backtrack + return false, nil + } + if s.vqs[len(s.vqs)-1].failed { + break + } + + s.vqs, s.vqs[len(s.vqs)-1] = s.vqs[:len(s.vqs)-1], nil + + // Pop selections off until we get to a project. + var proj bool + var awp atomWithPackages + for !proj { + var err error + awp, proj, err = s.unselectLast() + if err != nil { + if !contextCanceledOrSMReleased(err) { + panic(fmt.Sprintf("canary - should only have been able to get a context cancellation or SM release, got %T %s", err, err)) + } + return false, err + } + s.traceBacktrack(awp.bmi(), !proj) + } + } + + // Grab the last versionQueue off the list of queues + q := s.vqs[len(s.vqs)-1] + + // Walk back to the next project. This may entail walking through some + // package-only selections. + var proj bool + var awp atomWithPackages + for !proj { + var err error + awp, proj, err = s.unselectLast() + if err != nil { + if !contextCanceledOrSMReleased(err) { + panic(fmt.Sprintf("canary - should only have been able to get a context cancellation or SM release, got %T %s", err, err)) + } + return false, err + } + s.traceBacktrack(awp.bmi(), !proj) + } + + if !q.id.eq(awp.a.id) { + panic("canary - version queue stack and selected project stack are misaligned") + } + + // Advance the queue past the current version, which we know is bad + // TODO(sdboyer) is it feasible to make available the failure reason here? + if q.advance(nil) == nil && !q.isExhausted() { + // Search for another acceptable version of this failed dep in its queue + s.traceCheckQueue(q, awp.bmi(), true, 0) + if s.findValidVersion(q, awp.pl) == nil { + // Found one! Put it back on the selected queue and stop + // backtracking + + // reusing the old awp is fine + awp.a.v = q.current() + err := s.selectAtom(awp, false) + if err != nil { + if !contextCanceledOrSMReleased(err) { + panic(fmt.Sprintf("canary - should only have been able to get a context cancellation or SM release, got %T %s", err, err)) + } + return false, err + } + break + } + } + + s.traceBacktrack(awp.bmi(), false) + + // No solution found; continue backtracking after popping the queue + // we just inspected off the list + // GC-friendly pop pointer elem in slice + s.vqs, s.vqs[len(s.vqs)-1] = s.vqs[:len(s.vqs)-1], nil + } + + // Backtracking was successful if loop ended before running out of versions + if len(s.vqs) == 0 { + return false, nil + } + s.attempts++ + return true, nil +} + +func (s *solver) nextUnselected() (bimodalIdentifier, bool) { + if len(s.unsel.sl) > 0 { + return s.unsel.sl[0], true + } + + return bimodalIdentifier{}, false +} + +func (s *solver) unselectedComparator(i, j int) bool { + ibmi, jbmi := s.unsel.sl[i], s.unsel.sl[j] + iname, jname := ibmi.id, jbmi.id + + // Most important thing is pushing package additions ahead of project + // additions. Package additions can't walk their version queue, so all they + // do is narrow the possibility of success; better to find out early and + // fast if they're going to fail than wait until after we've done real work + // on a project and have to backtrack across it. + + // FIXME the impl here is currently O(n) in the number of selections; it + // absolutely cannot stay in a hot sorting path like this + // FIXME while other solver invariants probably protect us from it, this + // call-out means that it's possible for external state change to invalidate + // heap invariants. + _, isel := s.sel.selected(iname) + _, jsel := s.sel.selected(jname) + + if isel && !jsel { + return true + } + if !isel && jsel { + return false + } + + if iname.eq(jname) { + return false + } + + _, ilock := s.rd.rlm[iname.ProjectRoot] + _, jlock := s.rd.rlm[jname.ProjectRoot] + + switch { + case ilock && !jlock: + return true + case !ilock && jlock: + return false + case ilock && jlock: + return iname.Less(jname) + } + + // Now, sort by number of available versions. This will trigger network + // activity, but at this point we know that the project we're looking at + // isn't locked by the root. And, because being locked by root is the only + // way avoid that call when making a version queue, we know we're gonna have + // to pay that cost anyway. + + // We can safely ignore an err from listVersions here because, if there is + // an actual problem, it'll be noted and handled somewhere else saner in the + // solving algorithm. + ivl, _ := s.b.listVersions(iname) + jvl, _ := s.b.listVersions(jname) + iv, jv := len(ivl), len(jvl) + + // Packages with fewer versions to pick from are less likely to benefit from + // backtracking, so deal with them earlier in order to minimize the amount + // of superfluous backtracking through them we do. + switch { + case iv == 0 && jv != 0: + return true + case iv != 0 && jv == 0: + return false + case iv != jv: + return iv < jv + } + + // Finally, if all else fails, fall back to comparing by name + return iname.Less(jname) +} + +func (s *solver) fail(id ProjectIdentifier) { + // TODO(sdboyer) does this need updating, now that we have non-project package + // selection? + + // skip if the root project + if !s.rd.isRoot(id.ProjectRoot) { + // just look for the first (oldest) one; the backtracker will necessarily + // traverse through and pop off any earlier ones + for _, vq := range s.vqs { + if vq.id.eq(id) { + vq.failed = true + return + } + } + } +} + +// selectAtom pulls an atom into the selection stack, alongside some of +// its contained packages. New resultant dependency requirements are added to +// the unselected priority queue. +// +// Behavior is slightly diffferent if pkgonly is true. +func (s *solver) selectAtom(a atomWithPackages, pkgonly bool) error { + s.mtr.push("select-atom") + s.unsel.remove(bimodalIdentifier{ + id: a.a.id, + pl: a.pl, + }) + + pl, deps, err := s.getImportsAndConstraintsOf(a) + if err != nil { + if contextCanceledOrSMReleased(err) { + return err + } + // This shouldn't be possible; other checks should have ensured all + // packages and deps are present for any argument passed to this method. + panic(fmt.Sprintf("canary - shouldn't be possible %s", err)) + } + // Assign the new internal package list into the atom, then push it onto the + // selection stack + a.pl = pl + s.sel.pushSelection(a, pkgonly) + + // If this atom has a lock, pull it out so that we can potentially inject + // preferred versions into any bmis we enqueue + // + // TODO(sdboyer) making this call here could be the first thing to trigger + // network activity...maybe? if so, can we mitigate by deferring the work to + // queue consumption time? + _, l, _ := s.b.GetManifestAndLock(a.a.id, a.a.v, s.rd.an) + var lmap map[ProjectIdentifier]Version + if l != nil { + lmap = make(map[ProjectIdentifier]Version) + for _, lp := range l.Projects() { + lmap[lp.Ident()] = lp.Version() + } + } + + for _, dep := range deps { + // Root can come back up here if there's a project-level cycle. + // Satisfiability checks have already ensured invariants are maintained, + // so we know we can just skip it here. + if s.rd.isRoot(dep.Ident.ProjectRoot) { + continue + } + // If this is dep isn't in the lock, do some prefetching. (If it is, we + // might be able to get away with zero network activity for it, so don't + // prefetch). This provides an opportunity for some parallelism wins, on + // two fronts: + // + // 1. Because this loop may have multiple deps in it, we could end up + // simultaneously fetching both in the background while solving proceeds + // + // 2. Even if only one dep gets prefetched here, the worst case is that + // that same dep comes out of the unselected queue next, and we gain a + // few microseconds before blocking later. Best case, the dep doesn't + // come up next, but some other dep comes up that wasn't prefetched, and + // both fetches proceed in parallel. + if s.rd.needVersionsFor(dep.Ident.ProjectRoot) { + go s.b.SyncSourceFor(dep.Ident) + } + + s.sel.pushDep(dependency{depender: a.a, dep: dep}) + // Go through all the packages introduced on this dep, selecting only + // the ones where the only depper on them is what the preceding line just + // pushed in. Then, put those into the unselected queue. + rpm := s.sel.getRequiredPackagesIn(dep.Ident) + var newp []string + for _, pkg := range dep.pl { + // Just one means that the dep we're visiting is the sole importer. + if rpm[pkg] == 1 { + newp = append(newp, pkg) + } + } + + if len(newp) > 0 { + // If there was a previously-established alternate source for this + // dependency, but the current atom did not express one (and getting + // here means the atom passed the source hot-swapping check - see + // checkIdentMatches()), then we have to create the new bmi with the + // alternate source. Otherwise, we end up with two discrete project + // entries for the project root in the final output, one with the + // alternate source, and one without. See #969. + id, _ := s.sel.getIdentFor(dep.Ident.ProjectRoot) + bmi := bimodalIdentifier{ + id: id, + pl: newp, + // This puts in a preferred version if one's in the map, else + // drops in the zero value (nil) + prefv: lmap[dep.Ident], + } + heap.Push(s.unsel, bmi) + } + } + + s.traceSelect(a, pkgonly) + s.mtr.pop() + + return nil +} + +func (s *solver) unselectLast() (atomWithPackages, bool, error) { + s.mtr.push("unselect") + defer s.mtr.pop() + awp, first := s.sel.popSelection() + heap.Push(s.unsel, bimodalIdentifier{id: awp.a.id, pl: awp.pl}) + + _, deps, err := s.getImportsAndConstraintsOf(awp) + if err != nil { + if contextCanceledOrSMReleased(err) { + return atomWithPackages{}, false, err + } + // This shouldn't be possible; other checks should have ensured all + // packages and deps are present for any argument passed to this method. + panic(fmt.Sprintf("canary - shouldn't be possible %s", err)) + } + + for _, dep := range deps { + // Skip popping if the dep is the root project, which can occur if + // there's a project-level import cycle. (This occurs frequently with + // e.g. kubernetes and docker) + if s.rd.isRoot(dep.Ident.ProjectRoot) { + continue + } + s.sel.popDep(dep.Ident) + + // if no parents/importers, remove from unselected queue + if s.sel.depperCount(dep.Ident) == 0 { + s.unsel.remove(bimodalIdentifier{id: dep.Ident, pl: dep.pl}) + } + } + + return awp, first, nil +} + +// simple (temporary?) helper just to convert atoms into locked projects +func pa2lp(pa atom, pkgs map[string]struct{}) LockedProject { + lp := LockedProject{ + pi: pa.id, + } + + switch v := pa.v.(type) { + case UnpairedVersion: + lp.v = v + case Revision: + lp.r = v + case versionPair: + lp.v = v.v + lp.r = v.r + default: + panic("unreachable") + } + + lp.pkgs = make([]string, len(pkgs)) + k := 0 + + pr := string(pa.id.ProjectRoot) + trim := pr + "/" + for pkg := range pkgs { + if pkg == string(pa.id.ProjectRoot) { + lp.pkgs[k] = "." + } else { + lp.pkgs[k] = strings.TrimPrefix(pkg, trim) + } + k++ + } + sort.Strings(lp.pkgs) + + return lp +} + +func contextCanceledOrSMReleased(err error) bool { + return err == context.Canceled || err == context.DeadlineExceeded || err == ErrSourceManagerIsReleased +} diff --git a/vendor/github.com/golang/dep/gps/solver_inputs_test.go b/vendor/github.com/golang/dep/gps/solver_inputs_test.go new file mode 100644 index 00000000..b78f01eb --- /dev/null +++ b/vendor/github.com/golang/dep/gps/solver_inputs_test.go @@ -0,0 +1,228 @@ +// Copyright 2017 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 gps + +import ( + "io/ioutil" + "log" + "math/rand" + "strconv" + "strings" + "testing" + + "github.com/golang/dep/gps/pkgtree" + "github.com/golang/dep/internal/test" +) + +// TestBadSolveOpts exercises the different possible inputs to a solver that can +// be determined as invalid in Prepare(), without any further work +func TestBadSolveOpts(t *testing.T) { + pn := strconv.FormatInt(rand.Int63(), 36) + fix := basicFixtures["no dependencies"] + fix.ds[0].n = ProjectRoot(pn) + + sm := newdepspecSM(fix.ds, nil) + params := SolveParameters{ + mkBridgeFn: overrideMkBridge, + } + + _, err := Prepare(params, nil) + if err == nil { + t.Errorf("Prepare should have errored on nil SourceManager") + } else if !strings.Contains(err.Error(), "non-nil SourceManager") { + t.Error("Prepare should have given error on nil SourceManager, but gave:", err) + } + + _, err = Prepare(params, sm) + if err == nil { + t.Errorf("Prepare should have errored without ProjectAnalyzer") + } else if !strings.Contains(err.Error(), "must provide a ProjectAnalyzer") { + t.Error("Prepare should have given error without ProjectAnalyzer, but gave:", err) + } + + params.ProjectAnalyzer = naiveAnalyzer{} + _, err = Prepare(params, sm) + if err == nil { + t.Errorf("Prepare should have errored on empty root") + } else if !strings.Contains(err.Error(), "non-empty root directory") { + t.Error("Prepare should have given error on empty root, but gave:", err) + } + + params.RootDir = pn + _, err = Prepare(params, sm) + if err == nil { + t.Errorf("Prepare should have errored on empty name") + } else if !strings.Contains(err.Error(), "non-empty import root") { + t.Error("Prepare should have given error on empty import root, but gave:", err) + } + + params.RootPackageTree = pkgtree.PackageTree{ + ImportRoot: pn, + } + _, err = Prepare(params, sm) + if err == nil { + t.Errorf("Prepare should have errored on empty name") + } else if !strings.Contains(err.Error(), "at least one package") { + t.Error("Prepare should have given error on empty import root, but gave:", err) + } + + params.RootPackageTree = pkgtree.PackageTree{ + ImportRoot: pn, + Packages: map[string]pkgtree.PackageOrErr{ + pn: { + P: pkgtree.Package{ + ImportPath: pn, + Name: pn, + }, + }, + }, + } + params.TraceLogger = log.New(ioutil.Discard, "", 0) + + params.Manifest = simpleRootManifest{ + ovr: ProjectConstraints{ + ProjectRoot("foo"): ProjectProperties{}, + }, + } + _, err = Prepare(params, sm) + if err == nil { + t.Errorf("Should have errored on override with empty ProjectProperties") + } else if !strings.Contains(err.Error(), "foo, but without any non-zero properties") { + t.Error("Prepare should have given error override with empty ProjectProperties, but gave:", err) + } + + params.Manifest = simpleRootManifest{ + ig: pkgtree.NewIgnoredRuleset([]string{"foo"}), + req: map[string]bool{"foo": true}, + } + _, err = Prepare(params, sm) + if err == nil { + t.Errorf("Should have errored on pkg both ignored and required") + } else if !strings.Contains(err.Error(), "was given as both a required and ignored package") { + t.Error("Prepare should have given error with single ignore/require conflict error, but gave:", err) + } + + params.Manifest = simpleRootManifest{ + ig: pkgtree.NewIgnoredRuleset([]string{"foo", "bar"}), + req: map[string]bool{"foo": true, "bar": true}, + } + _, err = Prepare(params, sm) + if err == nil { + t.Errorf("Should have errored on pkg both ignored and required") + } else if !strings.Contains(err.Error(), "multiple packages given as both required and ignored:") { + t.Error("Prepare should have given error with multiple ignore/require conflict error, but gave:", err) + } + + params.Manifest = simpleRootManifest{ + ig: pkgtree.NewIgnoredRuleset([]string{"foo*"}), + req: map[string]bool{"foo/bar": true}, + } + _, err = Prepare(params, sm) + if err == nil { + t.Errorf("Should have errored on pkg both ignored (with wildcard) and required") + } else if !strings.Contains(err.Error(), "was given as both a required and ignored package") { + t.Error("Prepare should have given error with single ignore/require conflict error, but gave:", err) + } + params.Manifest = nil + + params.ToChange = []ProjectRoot{"foo"} + _, err = Prepare(params, sm) + if err == nil { + t.Errorf("Should have errored on non-empty ToChange without a lock provided") + } else if !strings.Contains(err.Error(), "update specifically requested for") { + t.Error("Prepare should have given error on ToChange without Lock, but gave:", err) + } + + params.Lock = safeLock{ + p: []LockedProject{ + NewLockedProject(mkPI("bar"), Revision("makebelieve"), nil), + }, + } + _, err = Prepare(params, sm) + if err == nil { + t.Errorf("Should have errored on ToChange containing project not in lock") + } else if !strings.Contains(err.Error(), "cannot update foo as it is not in the lock") { + t.Error("Prepare should have given error on ToChange with item not present in Lock, but gave:", err) + } + + params.Lock, params.ToChange = nil, nil + _, err = Prepare(params, sm) + if err != nil { + t.Error("Basic conditions satisfied, prepare should have completed successfully, err as:", err) + } + + // swap out the test mkBridge override temporarily, just to make sure we get + // the right error + params.mkBridgeFn = nil + + _, err = Prepare(params, sm) + if err == nil { + t.Errorf("Should have errored on nonexistent root") + } else if !strings.Contains(err.Error(), "could not read project root") { + t.Error("Prepare should have given error nonexistent project root dir, but gave:", err) + } + + // Pointing it at a file should also be an err + params.RootDir = "solve_test.go" + _, err = Prepare(params, sm) + if err == nil { + t.Errorf("Should have errored on file for RootDir") + } else if !strings.Contains(err.Error(), "is a file, not a directory") { + t.Error("Prepare should have given error on file as RootDir, but gave:", err) + } +} + +func TestValidateParams(t *testing.T) { + h := test.NewHelper(t) + defer h.Cleanup() + + cacheDir := "gps-cache" + h.TempDir(cacheDir) + sm, err := NewSourceManager(SourceManagerConfig{ + Cachedir: h.Path(cacheDir), + Logger: log.New(test.Writer{TB: t}, "", 0), + }) + h.Must(err) + defer sm.Release() + + h.TempDir("src") + + testcases := []struct { + imports []string + err bool + }{ + {[]string{"google.com/non-existing/package"}, true}, + {[]string{"google.com/non-existing/package/subpkg"}, true}, + {[]string{"github.com/sdboyer/testrepo"}, false}, + {[]string{"github.com/sdboyer/testrepo/subpkg"}, false}, + } + + params := SolveParameters{ + ProjectAnalyzer: naiveAnalyzer{}, + RootDir: h.Path("src"), + RootPackageTree: pkgtree.PackageTree{ + ImportRoot: "github.com/sdboyer/dep", + }, + } + + for _, tc := range testcases { + params.RootPackageTree.Packages = map[string]pkgtree.PackageOrErr{ + "github.com/sdboyer/dep": { + P: pkgtree.Package{ + Name: "github.com/sdboyer/dep", + ImportPath: "github.com/sdboyer/dep", + Imports: tc.imports, + }, + }, + } + + err = ValidateParams(params, sm) + if tc.err && err == nil { + t.Fatalf("expected an error when deducing package fails, got none") + } else if !tc.err && err != nil { + t.Fatalf("deducing packges should have succeeded, got err: %#v", err) + } + } +} diff --git a/vendor/github.com/golang/dep/gps/source.go b/vendor/github.com/golang/dep/gps/source.go new file mode 100644 index 00000000..54723754 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/source.go @@ -0,0 +1,638 @@ +// Copyright 2017 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 gps + +import ( + "context" + "fmt" + "log" + "sync" + + "github.com/golang/dep/gps/pkgtree" + "github.com/pkg/errors" +) + +// sourceState represent the states that a source can be in, depending on how +// much search and discovery work ahs been done by a source's managing gateway. +// +// These are basically used to achieve a cheap approximation of a FSM. +type sourceState int32 + +const ( + sourceIsSetUp sourceState = 1 << iota + sourceExistsUpstream + sourceExistsLocally + sourceHasLatestVersionList + sourceHasLatestLocally +) + +type srcReturnChans struct { + ret chan *sourceGateway + err chan error +} + +func (rc srcReturnChans) awaitReturn() (sg *sourceGateway, err error) { + select { + case sg = <-rc.ret: + case err = <-rc.err: + } + return +} + +type sourceCoordinator struct { + supervisor *supervisor + srcmut sync.RWMutex // guards srcs and nameToURL maps + srcs map[string]*sourceGateway + nameToURL map[string]string + psrcmut sync.Mutex // guards protoSrcs map + protoSrcs map[string][]srcReturnChans + deducer deducer + cachedir string + logger *log.Logger +} + +func newSourceCoordinator(superv *supervisor, deducer deducer, cachedir string, logger *log.Logger) *sourceCoordinator { + return &sourceCoordinator{ + supervisor: superv, + deducer: deducer, + cachedir: cachedir, + logger: logger, + srcs: make(map[string]*sourceGateway), + nameToURL: make(map[string]string), + protoSrcs: make(map[string][]srcReturnChans), + } +} + +func (sc *sourceCoordinator) close() {} + +func (sc *sourceCoordinator) getSourceGatewayFor(ctx context.Context, id ProjectIdentifier) (*sourceGateway, error) { + if err := sc.supervisor.ctx.Err(); err != nil { + return nil, err + } + + normalizedName := id.normalizedSource() + + sc.srcmut.RLock() + if url, has := sc.nameToURL[normalizedName]; has { + srcGate, has := sc.srcs[url] + sc.srcmut.RUnlock() + if has { + return srcGate, nil + } + panic(fmt.Sprintf("%q was URL for %q in nameToURL, but no corresponding srcGate in srcs map", url, normalizedName)) + } + + // Without a direct match, we must fold the input name to a generally + // stable, caseless variant and primarily work from that. This ensures that + // on case-insensitive filesystems, we do not end up with multiple + // sourceGateways for paths that vary only by case. We perform folding + // unconditionally, independent of whether the underlying fs is + // case-sensitive, in order to ensure uniform behavior. + // + // This has significant implications. It is effectively deciding that the + // ProjectRoot portion of import paths are case-insensitive, which is by no + // means an invariant maintained by all hosting systems. If this presents a + // problem in practice, then we can explore expanding the deduction system + // to include case-sensitivity-for-roots metadata and treat it on a + // host-by-host basis. Such cases would still be rejected by the Go + // toolchain's compiler, though, and case-sensitivity in root names is + // likely to be at least frowned on if not disallowed by most hosting + // systems. So we follow this path, which is both a vastly simpler solution + // and one that seems quite likely to work in practice. + foldedNormalName := toFold(normalizedName) + notFolded := foldedNormalName != normalizedName + if notFolded { + // If the folded name differs from the input name, then there may + // already be an entry for it in the nameToURL map, so check again. + if url, has := sc.nameToURL[foldedNormalName]; has { + // There was a match on the canonical folded variant. Upgrade to a + // write lock, so that future calls on this name don't need to + // burn cycles on folding. + sc.srcmut.RUnlock() + sc.srcmut.Lock() + // It may be possible that another goroutine could interleave + // between the unlock and re-lock. Even if they do, though, they'll + // only have recorded the same url value as we have here. In other + // words, these operations commute, so we can safely write here + // without checking again. + sc.nameToURL[normalizedName] = url + + srcGate, has := sc.srcs[url] + sc.srcmut.Unlock() + if has { + return srcGate, nil + } + panic(fmt.Sprintf("%q was URL for %q in nameToURL, but no corresponding srcGate in srcs map", url, normalizedName)) + } + } + sc.srcmut.RUnlock() + + // No gateway exists for this path yet; set up a proto, being careful to fold + // together simultaneous attempts on the same case-folded path. + sc.psrcmut.Lock() + if chans, has := sc.protoSrcs[foldedNormalName]; has { + // Another goroutine is already working on this normalizedName. Fold + // in with that work by attaching our return channels to the list. + rc := srcReturnChans{ + ret: make(chan *sourceGateway, 1), + err: make(chan error, 1), + } + sc.protoSrcs[foldedNormalName] = append(chans, rc) + sc.psrcmut.Unlock() + return rc.awaitReturn() + } + + sc.protoSrcs[foldedNormalName] = []srcReturnChans{} + sc.psrcmut.Unlock() + + doReturn := func(sg *sourceGateway, err error) { + sc.psrcmut.Lock() + if sg != nil { + for _, rc := range sc.protoSrcs[foldedNormalName] { + rc.ret <- sg + } + } else if err != nil { + for _, rc := range sc.protoSrcs[foldedNormalName] { + rc.err <- err + } + } else { + panic("sg and err both nil") + } + + delete(sc.protoSrcs, foldedNormalName) + sc.psrcmut.Unlock() + } + + pd, err := sc.deducer.deduceRootPath(ctx, normalizedName) + if err != nil { + // As in the deducer, don't cache errors so that externally-driven retry + // strategies can be constructed. + doReturn(nil, err) + return nil, err + } + + // It'd be quite the feat - but not impossible - for a gateway + // corresponding to this normalizedName to have slid into the main + // sources map after the initial unlock, but before this goroutine got + // scheduled. Guard against that by checking the main sources map again + // and bailing out if we find an entry. + var srcGate *sourceGateway + sc.srcmut.RLock() + if url, has := sc.nameToURL[foldedNormalName]; has { + if srcGate, has := sc.srcs[url]; has { + sc.srcmut.RUnlock() + doReturn(srcGate, nil) + return srcGate, nil + } + panic(fmt.Sprintf("%q was URL for %q in nameToURL, but no corresponding srcGate in srcs map", url, normalizedName)) + } + sc.srcmut.RUnlock() + + srcGate = newSourceGateway(pd.mb, sc.supervisor, sc.cachedir) + + // The normalized name is usually different from the source URL- e.g. + // github.com/sdboyer/gps vs. https://github.com/sdboyer/gps. But it's + // possible to arrive here with a full URL as the normalized name - and both + // paths *must* lead to the same sourceGateway instance in order to ensure + // disk access is correctly managed. + // + // Therefore, we now must query the sourceGateway to get the actual + // sourceURL it's operating on, and ensure it's *also* registered at + // that path in the map. This will cause it to actually initiate the + // maybeSource.try() behavior in order to settle on a URL. + url, err := srcGate.sourceURL(ctx) + if err != nil { + doReturn(nil, err) + return nil, err + } + + // If the normalizedName and foldedNormalName differ, then we're pretty well + // guaranteed that returned URL will also need folding into canonical form. + var unfoldedURL string + if notFolded { + unfoldedURL = url + url = toFold(url) + } + + // We know we have a working srcGateway at this point, and need to + // integrate it back into the main map. + sc.srcmut.Lock() + defer sc.srcmut.Unlock() + // Record the name -> URL mapping, making sure that we also get the + // self-mapping. + sc.nameToURL[foldedNormalName] = url + if url != foldedNormalName { + sc.nameToURL[url] = url + } + + // Make sure we have both the folded and unfolded names and URLs recorded in + // the map, if the input needed folding. + if notFolded { + sc.nameToURL[normalizedName] = url + sc.nameToURL[unfoldedURL] = url + } + + if sa, has := sc.srcs[url]; has { + // URL already had an entry in the main map; use that as the result. + doReturn(sa, nil) + return sa, nil + } + + sc.srcs[url] = srcGate + doReturn(srcGate, nil) + return srcGate, nil +} + +// sourceGateways manage all incoming calls for data from sources, serializing +// and caching them as needed. +type sourceGateway struct { + cachedir string + maybe maybeSource + srcState sourceState + src source + cache singleSourceCache + mu sync.Mutex // global lock, serializes all behaviors + suprvsr *supervisor +} + +func newSourceGateway(maybe maybeSource, superv *supervisor, cachedir string) *sourceGateway { + sg := &sourceGateway{ + maybe: maybe, + cachedir: cachedir, + suprvsr: superv, + } + sg.cache = sg.createSingleSourceCache() + + return sg +} + +func (sg *sourceGateway) syncLocal(ctx context.Context) error { + sg.mu.Lock() + defer sg.mu.Unlock() + + _, err := sg.require(ctx, sourceIsSetUp|sourceExistsLocally|sourceHasLatestLocally) + return err +} + +func (sg *sourceGateway) existsInCache(ctx context.Context) bool { + sg.mu.Lock() + defer sg.mu.Unlock() + + _, err := sg.require(ctx, sourceIsSetUp|sourceExistsLocally) + if err != nil { + return false + } + + return sg.srcState&sourceExistsLocally != 0 +} + +func (sg *sourceGateway) existsUpstream(ctx context.Context) bool { + sg.mu.Lock() + defer sg.mu.Unlock() + + _, err := sg.require(ctx, sourceIsSetUp|sourceExistsUpstream) + if err != nil { + return false + } + + return sg.srcState&sourceExistsUpstream != 0 +} + +func (sg *sourceGateway) exportVersionTo(ctx context.Context, v Version, to string) error { + sg.mu.Lock() + defer sg.mu.Unlock() + + _, err := sg.require(ctx, sourceIsSetUp|sourceExistsLocally) + if err != nil { + return err + } + + r, err := sg.convertToRevision(ctx, v) + if err != nil { + return err + } + + err = sg.suprvsr.do(ctx, sg.src.upstreamURL(), ctExportTree, func(ctx context.Context) error { + return sg.src.exportRevisionTo(ctx, r, to) + }) + + // It's possible (in git) that we may have tried this against a version that + // doesn't exist in the repository cache, even though we know it exists in + // the upstream. If it looks like that might be the case, update the local + // and retry. + // TODO(sdboyer) It'd be better if we could check the error to see if this + // actually was the cause of the problem. + if err != nil && sg.srcState&sourceHasLatestLocally == 0 { + if _, err = sg.require(ctx, sourceHasLatestLocally); err == nil { + err = sg.suprvsr.do(ctx, sg.src.upstreamURL(), ctExportTree, func(ctx context.Context) error { + return sg.src.exportRevisionTo(ctx, r, to) + }) + } + } + + return err +} + +func (sg *sourceGateway) getManifestAndLock(ctx context.Context, pr ProjectRoot, v Version, an ProjectAnalyzer) (Manifest, Lock, error) { + sg.mu.Lock() + defer sg.mu.Unlock() + + r, err := sg.convertToRevision(ctx, v) + if err != nil { + return nil, nil, err + } + + m, l, has := sg.cache.getManifestAndLock(r, an.Info()) + if has { + return m, l, nil + } + + _, err = sg.require(ctx, sourceIsSetUp|sourceExistsLocally) + if err != nil { + return nil, nil, err + } + + label := fmt.Sprintf("%s:%s", sg.src.upstreamURL(), an.Info()) + err = sg.suprvsr.do(ctx, label, ctGetManifestAndLock, func(ctx context.Context) error { + m, l, err = sg.src.getManifestAndLock(ctx, pr, r, an) + return err + }) + + // It's possible (in git) that we may have tried this against a version that + // doesn't exist in the repository cache, even though we know it exists in + // the upstream. If it looks like that might be the case, update the local + // and retry. + // TODO(sdboyer) It'd be better if we could check the error to see if this + // actually was the cause of the problem. + if err != nil && sg.srcState&sourceHasLatestLocally == 0 { + // TODO(sdboyer) we should warn/log/something in adaptive recovery + // situations like this + _, err = sg.require(ctx, sourceHasLatestLocally) + if err != nil { + return nil, nil, err + } + + err = sg.suprvsr.do(ctx, label, ctGetManifestAndLock, func(ctx context.Context) error { + m, l, err = sg.src.getManifestAndLock(ctx, pr, r, an) + return err + }) + } + + if err != nil { + return nil, nil, err + } + + sg.cache.setManifestAndLock(r, an.Info(), m, l) + return m, l, nil +} + +// FIXME ProjectRoot input either needs to parameterize the cache, or be +// incorporated on the fly on egress...? +func (sg *sourceGateway) listPackages(ctx context.Context, pr ProjectRoot, v Version) (pkgtree.PackageTree, error) { + sg.mu.Lock() + defer sg.mu.Unlock() + + r, err := sg.convertToRevision(ctx, v) + if err != nil { + return pkgtree.PackageTree{}, err + } + + ptree, has := sg.cache.getPackageTree(r) + if has { + return ptree, nil + } + + _, err = sg.require(ctx, sourceIsSetUp|sourceExistsLocally) + if err != nil { + return pkgtree.PackageTree{}, err + } + + label := fmt.Sprintf("%s:%s", pr, sg.src.upstreamURL()) + err = sg.suprvsr.do(ctx, label, ctListPackages, func(ctx context.Context) error { + ptree, err = sg.src.listPackages(ctx, pr, r) + return err + }) + + // It's possible (in git) that we may have tried this against a version that + // doesn't exist in the repository cache, even though we know it exists in + // the upstream. If it looks like that might be the case, update the local + // and retry. + // TODO(sdboyer) It'd be better if we could check the error to see if this + // actually was the cause of the problem. + if err != nil && sg.srcState&sourceHasLatestLocally == 0 { + // TODO(sdboyer) we should warn/log/something in adaptive recovery + // situations like this + _, err = sg.require(ctx, sourceHasLatestLocally) + if err != nil { + return pkgtree.PackageTree{}, err + } + + err = sg.suprvsr.do(ctx, label, ctListPackages, func(ctx context.Context) error { + ptree, err = sg.src.listPackages(ctx, pr, r) + return err + }) + } + + if err != nil { + return pkgtree.PackageTree{}, err + } + + sg.cache.setPackageTree(r, ptree) + return ptree, nil +} + +func (sg *sourceGateway) convertToRevision(ctx context.Context, v Version) (Revision, error) { + // When looking up by Version, there are four states that may have + // differing opinions about version->revision mappings: + // + // 1. The upstream source/repo (canonical) + // 2. The local source/repo + // 3. The local cache + // 4. The input (params to this method) + // + // If the input differs from any of the above, it's likely because some lock + // got written somewhere with a version/rev pair that has since changed or + // been removed. But correct operation dictates that such a mis-mapping be + // respected; if the mis-mapping is to be corrected, it has to be done + // intentionally by the caller, not automatically here. + r, has := sg.cache.toRevision(v) + if has { + return r, nil + } + + if sg.srcState&sourceHasLatestVersionList != 0 { + // We have the latest version list already and didn't get a match, so + // this is definitely a failure case. + return "", fmt.Errorf("version %q does not exist in source", v) + } + + // The version list is out of date; it's possible this version might + // show up after loading it. + _, err := sg.require(ctx, sourceIsSetUp|sourceHasLatestVersionList) + if err != nil { + return "", err + } + + r, has = sg.cache.toRevision(v) + if !has { + return "", fmt.Errorf("version %q does not exist in source", v) + } + + return r, nil +} + +func (sg *sourceGateway) listVersions(ctx context.Context) ([]PairedVersion, error) { + sg.mu.Lock() + defer sg.mu.Unlock() + + // TODO(sdboyer) The problem here is that sourceExistsUpstream may not be + // sufficient (e.g. bzr, hg), but we don't want to force local b/c git + // doesn't need it + _, err := sg.require(ctx, sourceIsSetUp|sourceExistsUpstream|sourceHasLatestVersionList) + if err != nil { + return nil, err + } + if pvs, ok := sg.cache.getAllVersions(); ok { + return pvs, nil + } + return nil, nil +} + +func (sg *sourceGateway) revisionPresentIn(ctx context.Context, r Revision) (bool, error) { + sg.mu.Lock() + defer sg.mu.Unlock() + + _, err := sg.require(ctx, sourceIsSetUp|sourceExistsLocally) + if err != nil { + return false, err + } + + if _, exists := sg.cache.getVersionsFor(r); exists { + return true, nil + } + + present, err := sg.src.revisionPresentIn(r) + if err == nil && present { + sg.cache.markRevisionExists(r) + } + return present, err +} + +func (sg *sourceGateway) disambiguateRevision(ctx context.Context, r Revision) (Revision, error) { + sg.mu.Lock() + defer sg.mu.Unlock() + + _, err := sg.require(ctx, sourceIsSetUp|sourceExistsLocally) + if err != nil { + return "", err + } + + return sg.src.disambiguateRevision(ctx, r) +} + +func (sg *sourceGateway) sourceURL(ctx context.Context) (string, error) { + sg.mu.Lock() + defer sg.mu.Unlock() + + _, err := sg.require(ctx, sourceIsSetUp) + if err != nil { + return "", err + } + + return sg.src.upstreamURL(), nil +} + +// createSingleSourceCache creates a singleSourceCache instance for use by +// the encapsulated source. +func (sg *sourceGateway) createSingleSourceCache() singleSourceCache { + // TODO(sdboyer) when persistent caching is ready, just drop in the creation + // of a source-specific handle here + return newMemoryCache() +} + +func (sg *sourceGateway) require(ctx context.Context, wanted sourceState) (errState sourceState, err error) { + todo := (^sg.srcState) & wanted + var flag sourceState = 1 + + for todo != 0 { + if todo&flag != 0 { + // Assign the currently visited bit to errState so that we can + // return easily later. + // + // Also set up addlState so that individual ops can easily attach + // more states that were incidentally satisfied by the op. + errState = flag + var addlState sourceState + + switch flag { + case sourceIsSetUp: + sg.src, addlState, err = sg.maybe.try(ctx, sg.cachedir, sg.cache, sg.suprvsr) + case sourceExistsUpstream: + err = sg.suprvsr.do(ctx, sg.src.sourceType(), ctSourcePing, func(ctx context.Context) error { + if !sg.src.existsUpstream(ctx) { + return fmt.Errorf("%s does not exist upstream", sg.src.upstreamURL()) + } + return nil + }) + case sourceExistsLocally: + if !sg.src.existsLocally(ctx) { + err = sg.suprvsr.do(ctx, sg.src.sourceType(), ctSourceInit, func(ctx context.Context) error { + return sg.src.initLocal(ctx) + }) + + if err == nil { + addlState |= sourceHasLatestLocally + } else { + err = errors.Wrapf(err, "%s does not exist in the local cache and fetching failed", sg.src.upstreamURL()) + } + } + case sourceHasLatestVersionList: + var pvl []PairedVersion + err = sg.suprvsr.do(ctx, sg.src.sourceType(), ctListVersions, func(ctx context.Context) error { + pvl, err = sg.src.listVersions(ctx) + return err + }) + + if err == nil { + sg.cache.setVersionMap(pvl) + } + case sourceHasLatestLocally: + err = sg.suprvsr.do(ctx, sg.src.sourceType(), ctSourceFetch, func(ctx context.Context) error { + return sg.src.updateLocal(ctx) + }) + } + + if err != nil { + return + } + + checked := flag | addlState + sg.srcState |= checked + todo &= ^checked + } + + flag <<= 1 + } + + return 0, nil +} + +// source is an abstraction around the different underlying types (git, bzr, hg, +// svn, maybe raw on-disk code, and maybe eventually a registry) that can +// provide versioned project source trees. +type source interface { + existsLocally(context.Context) bool + existsUpstream(context.Context) bool + upstreamURL() string + initLocal(context.Context) error + updateLocal(context.Context) error + listVersions(context.Context) ([]PairedVersion, error) + getManifestAndLock(context.Context, ProjectRoot, Revision, ProjectAnalyzer) (Manifest, Lock, error) + listPackages(context.Context, ProjectRoot, Revision) (pkgtree.PackageTree, error) + revisionPresentIn(Revision) (bool, error) + disambiguateRevision(context.Context, Revision) (Revision, error) + exportRevisionTo(context.Context, Revision, string) error + sourceType() string +} diff --git a/vendor/github.com/golang/dep/gps/source_cache.go b/vendor/github.com/golang/dep/gps/source_cache.go new file mode 100644 index 00000000..7b5b5660 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/source_cache.go @@ -0,0 +1,226 @@ +// Copyright 2017 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 gps + +import ( + "fmt" + "sync" + + "github.com/golang/dep/gps/pkgtree" +) + +// singleSourceCache provides a method set for storing and retrieving data about +// a single source. +type singleSourceCache interface { + // Store the manifest and lock information for a given revision, as defined by + // a particular ProjectAnalyzer. + setManifestAndLock(Revision, ProjectAnalyzerInfo, Manifest, Lock) + + // Get the manifest and lock information for a given revision, as defined by + // a particular ProjectAnalyzer. + getManifestAndLock(Revision, ProjectAnalyzerInfo) (Manifest, Lock, bool) + + // Store a PackageTree for a given revision. + setPackageTree(Revision, pkgtree.PackageTree) + + // Get the PackageTree for a given revision. + getPackageTree(Revision) (pkgtree.PackageTree, bool) + + // Indicate to the cache that an individual revision is known to exist. + markRevisionExists(r Revision) + + // Store the mappings between a set of PairedVersions' surface versions + // their corresponding revisions. + // + // The existing list of versions will be purged before writing. Revisions + // will have their pairings purged, but record of the revision existing will + // be kept, on the assumption that revisions are immutable and permanent. + setVersionMap(versionList []PairedVersion) + + // Get the list of unpaired versions corresponding to the given revision. + getVersionsFor(Revision) ([]UnpairedVersion, bool) + + // Gets all the version pairs currently known to the cache. + getAllVersions() ([]PairedVersion, bool) + + // Get the revision corresponding to the given unpaired version. + getRevisionFor(UnpairedVersion) (Revision, bool) + + // Attempt to convert the given Version to a Revision, given information + // currently present in the cache, and in the Version itself. + toRevision(v Version) (Revision, bool) + + // Attempt to convert the given Version to an UnpairedVersion, given + // information currently present in the cache, or in the Version itself. + // + // If the input is a revision and multiple UnpairedVersions are associated + // with it, whatever happens to be the first is returned. + toUnpaired(v Version) (UnpairedVersion, bool) +} + +type singleSourceCacheMemory struct { + mut sync.RWMutex // protects all fields + infos map[ProjectAnalyzerInfo]map[Revision]projectInfo + ptrees map[Revision]pkgtree.PackageTree + vList []PairedVersion // replaced, never modified + vMap map[UnpairedVersion]Revision + rMap map[Revision][]UnpairedVersion +} + +func newMemoryCache() singleSourceCache { + return &singleSourceCacheMemory{ + infos: make(map[ProjectAnalyzerInfo]map[Revision]projectInfo), + ptrees: make(map[Revision]pkgtree.PackageTree), + vMap: make(map[UnpairedVersion]Revision), + rMap: make(map[Revision][]UnpairedVersion), + } +} + +type projectInfo struct { + Manifest + Lock +} + +func (c *singleSourceCacheMemory) setManifestAndLock(r Revision, pai ProjectAnalyzerInfo, m Manifest, l Lock) { + c.mut.Lock() + inner, has := c.infos[pai] + if !has { + inner = make(map[Revision]projectInfo) + c.infos[pai] = inner + } + inner[r] = projectInfo{Manifest: m, Lock: l} + + // Ensure there's at least an entry in the rMap so that the rMap always has + // a complete picture of the revisions we know to exist + if _, has = c.rMap[r]; !has { + c.rMap[r] = nil + } + c.mut.Unlock() +} + +func (c *singleSourceCacheMemory) getManifestAndLock(r Revision, pai ProjectAnalyzerInfo) (Manifest, Lock, bool) { + c.mut.Lock() + defer c.mut.Unlock() + + inner, has := c.infos[pai] + if !has { + return nil, nil, false + } + + pi, has := inner[r] + if has { + return pi.Manifest, pi.Lock, true + } + return nil, nil, false +} + +func (c *singleSourceCacheMemory) setPackageTree(r Revision, ptree pkgtree.PackageTree) { + c.mut.Lock() + c.ptrees[r] = ptree + + // Ensure there's at least an entry in the rMap so that the rMap always has + // a complete picture of the revisions we know to exist + if _, has := c.rMap[r]; !has { + c.rMap[r] = nil + } + c.mut.Unlock() +} + +func (c *singleSourceCacheMemory) getPackageTree(r Revision) (pkgtree.PackageTree, bool) { + c.mut.Lock() + ptree, has := c.ptrees[r] + c.mut.Unlock() + return ptree, has +} + +func (c *singleSourceCacheMemory) setVersionMap(versionList []PairedVersion) { + c.mut.Lock() + c.vList = versionList + // TODO(sdboyer) how do we handle cache consistency here - revs that may + // be out of date vis-a-vis the ptrees or infos maps? + for r := range c.rMap { + c.rMap[r] = nil + } + + c.vMap = make(map[UnpairedVersion]Revision, len(versionList)) + + for _, pv := range versionList { + u, r := pv.Unpair(), pv.Revision() + c.vMap[u] = r + c.rMap[r] = append(c.rMap[r], u) + } + c.mut.Unlock() +} + +func (c *singleSourceCacheMemory) markRevisionExists(r Revision) { + c.mut.Lock() + if _, has := c.rMap[r]; !has { + c.rMap[r] = nil + } + c.mut.Unlock() +} + +func (c *singleSourceCacheMemory) getVersionsFor(r Revision) ([]UnpairedVersion, bool) { + c.mut.Lock() + versionList, has := c.rMap[r] + c.mut.Unlock() + return versionList, has +} + +func (c *singleSourceCacheMemory) getAllVersions() ([]PairedVersion, bool) { + c.mut.Lock() + vList := c.vList + c.mut.Unlock() + + if vList == nil { + return nil, false + } + cp := make([]PairedVersion, len(vList)) + copy(cp, vList) + return cp, true +} + +func (c *singleSourceCacheMemory) getRevisionFor(uv UnpairedVersion) (Revision, bool) { + c.mut.Lock() + r, has := c.vMap[uv] + c.mut.Unlock() + return r, has +} + +func (c *singleSourceCacheMemory) toRevision(v Version) (Revision, bool) { + switch t := v.(type) { + case Revision: + return t, true + case PairedVersion: + return t.Revision(), true + case UnpairedVersion: + c.mut.Lock() + r, has := c.vMap[t] + c.mut.Unlock() + return r, has + default: + panic(fmt.Sprintf("Unknown version type %T", v)) + } +} + +func (c *singleSourceCacheMemory) toUnpaired(v Version) (UnpairedVersion, bool) { + switch t := v.(type) { + case UnpairedVersion: + return t, true + case PairedVersion: + return t.Unpair(), true + case Revision: + c.mut.Lock() + upv, has := c.rMap[t] + c.mut.Unlock() + + if has && len(upv) > 0 { + return upv[0], true + } + return nil, false + default: + panic(fmt.Sprintf("unknown version type %T", v)) + } +} diff --git a/vendor/github.com/golang/dep/gps/source_cache_bolt.go b/vendor/github.com/golang/dep/gps/source_cache_bolt.go new file mode 100644 index 00000000..02d70098 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/source_cache_bolt.go @@ -0,0 +1,515 @@ +// Copyright 2017 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 gps + +import ( + "fmt" + "log" + "os" + "path/filepath" + "time" + + "github.com/boltdb/bolt" + "github.com/golang/dep/gps/internal/pb" + "github.com/golang/dep/gps/pkgtree" + "github.com/golang/protobuf/proto" + "github.com/jmank88/nuts" + "github.com/pkg/errors" +) + +// boltCache manages a bolt.DB cache and provides singleSourceCaches. +type boltCache struct { + db *bolt.DB + epoch int64 // getters will not return values older than this unix timestamp + logger *log.Logger // info logging +} + +// newBoltCache returns a new boltCache backed by a BoltDB file under the cache directory. +func newBoltCache(cd string, epoch int64, logger *log.Logger) (*boltCache, error) { + path := sourceCachePath(cd, "bolt") + ".db" + dir := filepath.Dir(path) + if fi, err := os.Stat(dir); os.IsNotExist(err) { + if err := os.MkdirAll(dir, os.ModeDir|os.ModePerm); err != nil { + return nil, errors.Wrapf(err, "failed to create source cache directory: %s", dir) + } + } else if err != nil { + return nil, errors.Wrapf(err, "failed to check source cache directory: ", dir) + } else if !fi.IsDir() { + return nil, errors.Wrapf(err, "source cache path is not directory: %s", dir) + } + db, err := bolt.Open(path, 0600, &bolt.Options{Timeout: 1 * time.Second}) + if err != nil { + return nil, errors.Wrapf(err, "failed to open BoltDB cache file %q", path) + } + return &boltCache{ + db: db, + epoch: epoch, + logger: logger, + }, nil +} + +// newSingleSourceCache returns a new singleSourceCache for pi. +func (c *boltCache) newSingleSourceCache(pi ProjectIdentifier) singleSourceCache { + return &singleSourceCacheBolt{ + boltCache: c, + pi: pi, + sourceName: []byte(pi.normalizedSource()), + } +} + +// close releases all cache resources. +func (c *boltCache) close() error { + return errors.Wrapf(c.db.Close(), "error closing Bolt database %q", c.db.String()) +} + +// singleSourceCacheBolt implements a singleSourceCache backed by a persistent BoltDB file. +// Version mappings are timestamped, and the `epoch` field limits the age of returned values. +// Database access methods are safe for concurrent use. +// +// Implementation: +// +// Each source has a top-level bucket containing sub-buckets for (1) versions and (2) revisions. +// +// 1) Versions buckets hold version keys with revision values: +// +// Bucket: "v" +// Keys: Unpaired Versions serialized via ConstraintMsg +// Values: "" +// +// 2) Revision buckets hold (a) manifest and lock data for various ProjectAnalyzers, +// (b) package trees, and (c) version lists. +// +// Bucket: "r" +// +// a) Manifest and Lock info are stored in buckets derived from ProjectAnalyzer.Info: +// +// Sub-Bucket: ".m", ".l" +// Keys/Values: Manifest or Lock fields +// +// b) Package tree buckets contain package import path keys and package-or-error buckets: +// +// Sub-Bucket: "p" +// Sub-Bucket: "" +// Key/Values: PackageOrErr fields +// +// c) Revision-versions buckets contain lists of version values: +// +// Sub-Bucket: "v" +// Keys: "" +// Values: Unpaired Versions serialized via ConstraintMsg +type singleSourceCacheBolt struct { + *boltCache + pi ProjectIdentifier + sourceName []byte +} + +func (s *singleSourceCacheBolt) setManifestAndLock(rev Revision, ai ProjectAnalyzerInfo, m Manifest, l Lock) { + err := s.updateRevBucket(rev, func(b *bolt.Bucket) error { + info := ai.String() + name := make([]byte, len(info)+1) + copy(name, info) + name[len(info)] = 'm' + + if b.Bucket(name) != nil { + if err := b.DeleteBucket(name); err != nil { + return err + } + } + + // Manifest + mb, err := b.CreateBucket(name) + if err != nil { + return err + } + if err := cachePutManifest(mb, m); err != nil { + return errors.Wrap(err, "failed to put manifest") + } + if l == nil { + return nil + } + + // Lock + name[len(info)] = 'l' + if b.Bucket(name) != nil { + if err := b.DeleteBucket(name); err != nil { + return err + } + } + lb, err := b.CreateBucket(name) + if err != nil { + return err + } + return errors.Wrap(cachePutLock(lb, l), "failed to put lock") + }) + if err != nil { + s.logger.Println(errors.Wrapf(err, "failed to cache manifest/lock for revision %q, analyzer: %v", rev, ai)) + } +} + +func (s *singleSourceCacheBolt) getManifestAndLock(rev Revision, ai ProjectAnalyzerInfo) (m Manifest, l Lock, ok bool) { + err := s.viewRevBucket(rev, func(b *bolt.Bucket) error { + info := ai.String() + name := make([]byte, len(info)+1) + copy(name, info) + name[len(info)] = 'm' + + // Manifest + mb := b.Bucket(name) + if mb == nil { + return nil + } + var err error + m, err = cacheGetManifest(mb) + if err != nil { + return errors.Wrap(err, "failed to get manifest") + } + + // Lock + name[len(info)] = 'l' + lb := b.Bucket(name) + if lb == nil { + ok = true + return nil + } + l, err = cacheGetLock(lb) + if err != nil { + return errors.Wrap(err, "failed to get lock") + } + + ok = true + return nil + }) + if err != nil { + s.logger.Println(errors.Wrapf(err, "failed to get cached manifest/lock for revision %q, analyzer: %v", rev, ai)) + } + return +} + +func (s *singleSourceCacheBolt) setPackageTree(rev Revision, ptree pkgtree.PackageTree) { + err := s.updateRevBucket(rev, func(b *bolt.Bucket) error { + if b.Bucket(cacheKeyPTree) != nil { + if err := b.DeleteBucket(cacheKeyPTree); err != nil { + return err + } + } + ptrees, err := b.CreateBucket(cacheKeyPTree) + if err != nil { + return err + } + + for ip, poe := range ptree.Packages { + pb, err := ptrees.CreateBucket([]byte(ip)) + if err != nil { + return err + } + + if err := cachePutPackageOrErr(pb, poe); err != nil { + return err + } + } + return nil + }) + if err != nil { + s.logger.Println(errors.Wrapf(err, "failed to cache package tree for revision %q", rev)) + } +} + +func (s *singleSourceCacheBolt) getPackageTree(rev Revision) (ptree pkgtree.PackageTree, ok bool) { + err := s.viewRevBucket(rev, func(b *bolt.Bucket) error { + ptrees := b.Bucket(cacheKeyPTree) + if ptrees == nil { + return nil + } + + pkgs := make(map[string]pkgtree.PackageOrErr) + err := ptrees.ForEach(func(ip, _ []byte) error { + poe, err := cacheGetPackageOrErr(ptrees.Bucket(ip)) + if err != nil { + return err + } + if poe.Err == nil { + poe.P.ImportPath = string(ip) + } + pkgs[string(ip)] = poe + return nil + }) + if err != nil { + return err + } + ptree.ImportRoot = string(s.pi.ProjectRoot) + ptree.Packages = pkgs + ok = true + return nil + }) + if err != nil { + s.logger.Println(errors.Wrapf(err, "failed to get cached package tree for revision %q", rev)) + } + return +} + +func (s *singleSourceCacheBolt) markRevisionExists(rev Revision) { + err := s.updateRevBucket(rev, func(versions *bolt.Bucket) error { + return nil + }) + if err != nil { + s.logger.Println(errors.Wrapf(err, "failed to mark revision %q in cache", rev)) + } +} + +func (s *singleSourceCacheBolt) setVersionMap(pvs []PairedVersion) { + err := s.updateSourceBucket(func(src *bolt.Bucket) error { + if err := cachePrefixDelete(src, cacheVersion); err != nil { + return err + } + vk := cacheTimestampedKey(cacheVersion, time.Now()) + versions, err := src.CreateBucket(vk) + if err != nil { + return err + } + + c := src.Cursor() + for k, _ := c.Seek(cacheKeyRevision); len(k) > 0 && k[0] == cacheRevision; k, _ = c.Next() { + rb := src.Bucket(k) + if err := cachePrefixDelete(rb, cacheVersion); err != nil { + return err + } + } + + revVersions := make(map[Revision]*bolt.Bucket) + key := make(nuts.Key, nuts.KeyLen(uint64(len(pvs)-1))) + var msg pb.Constraint + for i, pv := range pvs { + uv, rev := pv.Unpair(), pv.Revision() + uv.copyTo(&msg) + uvB, err := proto.Marshal(&msg) + if err != nil { + return errors.Wrapf(err, "failed to serialize UnpairedVersion: %#v", uv) + } + + if err := versions.Put(uvB, []byte(rev)); err != nil { + return errors.Wrap(err, "failed to put version->revision") + } + + b, err := src.CreateBucketIfNotExists(cacheRevisionName(rev)) + if err != nil { + return errors.Wrapf(err, "failed to create bucket for revision: %s", rev) + } + + var versions *bolt.Bucket + if versions = revVersions[rev]; versions == nil { + err := cachePrefixDelete(b, cacheVersion) + if err != nil { + return err + } + versions, err = b.CreateBucket(vk) + if err != nil { + return errors.Wrapf(err, "failed to create bucket for revision versions: %s", rev) + } + revVersions[rev] = versions + } + + key.Put(uint64(i)) + if err := versions.Put(key, uvB); err != nil { + return errors.Wrap(err, "failed to put revision->version") + } + } + return nil + }) + if err != nil { + s.logger.Println(errors.Wrap(err, "failed to cache version map")) + } +} + +func (s *singleSourceCacheBolt) getVersionsFor(rev Revision) (uvs []UnpairedVersion, ok bool) { + err := s.viewRevBucket(rev, func(b *bolt.Bucket) error { + versions := cacheFindLatestValid(b, cacheVersion, s.epoch) + if versions == nil { + return nil + } + + ok = true + + var msg pb.Constraint + return versions.ForEach(func(_, v []byte) error { + if err := proto.Unmarshal(v, &msg); err != nil { + return err + } + uv, err := unpairedVersionFromCache(&msg) + if err != nil { + return err + } + uvs = append(uvs, uv) + return nil + }) + }) + if err != nil { + s.logger.Println(errors.Wrapf(err, "failed to get cached versions for revision %q", rev)) + return nil, false + } + return +} + +func (s *singleSourceCacheBolt) getAllVersions() (pvs []PairedVersion, ok bool) { + err := s.viewSourceBucket(func(src *bolt.Bucket) error { + versions := cacheFindLatestValid(src, cacheVersion, s.epoch) + if versions == nil { + return nil + } + + var msg pb.Constraint + return versions.ForEach(func(k, v []byte) error { + if err := proto.Unmarshal(k, &msg); err != nil { + return err + } + uv, err := unpairedVersionFromCache(&msg) + if err != nil { + return err + } + pvs = append(pvs, uv.Pair(Revision(v))) + ok = true + return nil + }) + }) + if err != nil { + s.logger.Println(errors.Wrap(err, "failed to get all cached versions")) + return nil, false + } + return +} + +func (s *singleSourceCacheBolt) getRevisionFor(uv UnpairedVersion) (rev Revision, ok bool) { + err := s.viewSourceBucket(func(src *bolt.Bucket) error { + versions := cacheFindLatestValid(src, cacheVersion, s.epoch) + if versions == nil { + return nil + } + + var msg pb.Constraint + uv.copyTo(&msg) + b, err := proto.Marshal(&msg) + if err != nil { + return errors.Wrapf(err, "failed to serialize UnpairedVersion: %#v", uv) + } + + v := versions.Get(b) + if len(v) > 0 { + rev = Revision(v) + ok = true + } + return nil + }) + if err != nil { + s.logger.Println(errors.Wrapf(err, "failed to get cached revision for unpaired version: %v", uv)) + } + return +} + +func (s *singleSourceCacheBolt) toRevision(v Version) (rev Revision, ok bool) { + switch t := v.(type) { + case Revision: + return t, true + case PairedVersion: + return t.Revision(), true + case UnpairedVersion: + return s.getRevisionFor(t) + default: + s.logger.Println(fmt.Sprintf("failed to get cached revision for version %v: unknown type %T", v, v)) + return "", false + } +} + +func (s *singleSourceCacheBolt) toUnpaired(v Version) (uv UnpairedVersion, ok bool) { + const errMsg = "failed to get cached unpaired version for version: %v" + switch t := v.(type) { + case UnpairedVersion: + return t, true + case PairedVersion: + return t.Unpair(), true + case Revision: + err := s.viewRevBucket(t, func(b *bolt.Bucket) error { + versions := cacheFindLatestValid(b, cacheVersion, s.epoch) + if versions == nil { + return nil + } + + _, v := versions.Cursor().First() + if len(v) == 0 { + return nil + } + var msg pb.Constraint + if err := proto.Unmarshal(v, &msg); err != nil { + return err + } + var err error + uv, err = unpairedVersionFromCache(&msg) + if err != nil { + return err + } + + ok = true + return nil + }) + if err != nil { + s.logger.Println(errors.Wrapf(err, errMsg, v)) + } + return + default: + s.logger.Println(fmt.Sprintf(errMsg, v)) + return + } +} + +// cacheRevisionName returns the bucket name for rev. +func cacheRevisionName(rev Revision) []byte { + name := make([]byte, 1+len(rev)) + name[0] = 'r' + copy(name[1:], string(rev)) + return name +} + +// viewSourceBucket executes view with the source bucket, if it exists. +func (s *singleSourceCacheBolt) viewSourceBucket(view func(b *bolt.Bucket) error) error { + return s.db.View(func(tx *bolt.Tx) error { + b := tx.Bucket(s.sourceName) + if b == nil { + return nil + } + return view(b) + }) +} + +// updateSourceBucket executes update (in batch) with the source bucket, creating it first if necessary. +func (s *singleSourceCacheBolt) updateSourceBucket(update func(b *bolt.Bucket) error) error { + return s.db.Batch(func(tx *bolt.Tx) error { + b, err := tx.CreateBucketIfNotExists(s.sourceName) + if err != nil { + return errors.Wrapf(err, "failed to create bucket: %s", s.sourceName) + } + return update(b) + }) +} + +// viewRevBucket executes view with rev's bucket for this source, if it exists. +func (s *singleSourceCacheBolt) viewRevBucket(rev Revision, view func(b *bolt.Bucket) error) error { + return s.viewSourceBucket(func(src *bolt.Bucket) error { + b := src.Bucket(cacheRevisionName(rev)) + if b == nil { + return nil + } + return view(b) + }) +} + +// updateRevBucket executes update with rev's bucket for this source, creating it first if necessary. +func (s *singleSourceCacheBolt) updateRevBucket(rev Revision, update func(b *bolt.Bucket) error) error { + return s.updateSourceBucket(func(src *bolt.Bucket) error { + name := cacheRevisionName(rev) + b, err := src.CreateBucketIfNotExists(name) + if err != nil { + return errors.Wrapf(err, "failed to create bucket: %s", name) + } + return update(b) + }) +} diff --git a/vendor/github.com/golang/dep/gps/source_cache_bolt_encode.go b/vendor/github.com/golang/dep/gps/source_cache_bolt_encode.go new file mode 100644 index 00000000..2851b24b --- /dev/null +++ b/vendor/github.com/golang/dep/gps/source_cache_bolt_encode.go @@ -0,0 +1,465 @@ +// Copyright 2017 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 gps + +import ( + "encoding/binary" + "time" + + "github.com/boltdb/bolt" + "github.com/golang/dep/gps/internal/pb" + "github.com/golang/dep/gps/pkgtree" + "github.com/golang/protobuf/proto" + "github.com/jmank88/nuts" + "github.com/pkg/errors" +) + +var ( + cacheKeyComment = []byte("c") + cacheKeyConstraint = cacheKeyComment + cacheKeyError = []byte("e") + cacheKeyHash = []byte("h") + cacheKeyIgnored = []byte("i") + cacheKeyImport = cacheKeyIgnored + cacheKeyLock = []byte("l") + cacheKeyName = []byte("n") + cacheKeyOverride = []byte("o") + cacheKeyPTree = []byte("p") + cacheKeyRequired = []byte("r") + cacheKeyRevision = cacheKeyRequired + cacheKeyTestImport = []byte("t") + + cacheRevision = byte('r') + cacheVersion = byte('v') +) + +// propertiesFromCache returns a new ProjectRoot and ProjectProperties with the fields from m. +func propertiesFromCache(m *pb.ProjectProperties) (ProjectRoot, ProjectProperties, error) { + ip := ProjectRoot(m.Root) + var pp ProjectProperties + pp.Source = m.Source + + if m.Constraint == nil { + pp.Constraint = Any() + } else { + c, err := constraintFromCache(m.Constraint) + if err != nil { + return "", ProjectProperties{}, err + } + pp.Constraint = c + } + + return ip, pp, nil +} + +// projectPropertiesMsgs is a convenience tuple. +type projectPropertiesMsgs struct { + pp pb.ProjectProperties + c pb.Constraint +} + +// copyFrom sets the ProjectPropertiesMsg fields from ip and pp. +func (ms *projectPropertiesMsgs) copyFrom(ip ProjectRoot, pp ProjectProperties) { + ms.pp.Root = string(ip) + ms.pp.Source = pp.Source + + if pp.Constraint != nil && !IsAny(pp.Constraint) { + pp.Constraint.copyTo(&ms.c) + ms.pp.Constraint = &ms.c + } else { + ms.pp.Constraint = nil + } +} + +// cachePutManifest stores a Manifest in the bolt.Bucket. +func cachePutManifest(b *bolt.Bucket, m Manifest) error { + var ppMsg projectPropertiesMsgs + + constraints := m.DependencyConstraints() + if len(constraints) > 0 { + cs, err := b.CreateBucket(cacheKeyConstraint) + if err != nil { + return err + } + key := make(nuts.Key, nuts.KeyLen(uint64(len(constraints)-1))) + var i uint64 + for ip, pp := range constraints { + ppMsg.copyFrom(ip, pp) + v, err := proto.Marshal(&ppMsg.pp) + if err != nil { + return err + } + key.Put(i) + i++ + if err := cs.Put(key, v); err != nil { + return err + } + } + } + + rm, ok := m.(RootManifest) + if !ok { + return nil + } + + ignored := rm.IgnoredPackages().ToSlice() + if len(ignored) > 0 { + ig, err := b.CreateBucket(cacheKeyIgnored) + if err != nil { + return err + } + key := make(nuts.Key, nuts.KeyLen(uint64(len(ignored)-1))) + var i uint64 + for _, ip := range ignored { + key.Put(i) + i++ + if err := ig.Put(key, []byte(ip)); err != nil { + return err + } + } + } + + overrides := rm.Overrides() + if len(overrides) > 0 { + ovr, err := b.CreateBucket(cacheKeyOverride) + if err != nil { + return err + } + key := make(nuts.Key, nuts.KeyLen(uint64(len(overrides)-1))) + var i uint64 + for ip, pp := range overrides { + ppMsg.copyFrom(ip, pp) + v, err := proto.Marshal(&ppMsg.pp) + if err != nil { + return err + } + key.Put(i) + i++ + if err := ovr.Put(key, v); err != nil { + return err + } + } + } + + required := rm.RequiredPackages() + if len(required) > 0 { + req, err := b.CreateBucket(cacheKeyRequired) + if err != nil { + return err + } + key := make(nuts.Key, nuts.KeyLen(uint64(len(required)-1))) + var i uint64 + for ip, ok := range required { + if ok { + key.Put(i) + i++ + if err := req.Put(key, []byte(ip)); err != nil { + return err + } + } + } + } + + return nil +} + +// cacheGetManifest returns a new RootManifest with the data retrieved from the bolt.Bucket. +func cacheGetManifest(b *bolt.Bucket) (RootManifest, error) { + //TODO consider storing slice/map lens to enable calling make() with capacity + m := &simpleRootManifest{ + c: make(ProjectConstraints), + ovr: make(ProjectConstraints), + req: make(map[string]bool), + } + + // Constraints + if cs := b.Bucket(cacheKeyConstraint); cs != nil { + var msg pb.ProjectProperties + err := cs.ForEach(func(_, v []byte) error { + if err := proto.Unmarshal(v, &msg); err != nil { + return err + } + ip, pp, err := propertiesFromCache(&msg) + if err != nil { + return err + } + m.c[ip] = pp + return nil + }) + if err != nil { + return nil, errors.Wrap(err, "failed to get constraints") + } + } + + // Ignored + if ig := b.Bucket(cacheKeyIgnored); ig != nil { + var igslice []string + err := ig.ForEach(func(_, v []byte) error { + igslice = append(igslice, string(v)) + return nil + }) + m.ig = pkgtree.NewIgnoredRuleset(igslice) + if err != nil { + return nil, errors.Wrap(err, "failed to get ignored") + } + } + + // Overrides + if os := b.Bucket(cacheKeyOverride); os != nil { + var msg pb.ProjectProperties + err := os.ForEach(func(_, v []byte) error { + if err := proto.Unmarshal(v, &msg); err != nil { + return err + } + ip, pp, err := propertiesFromCache(&msg) + if err != nil { + return err + } + m.ovr[ip] = pp + return nil + }) + if err != nil { + return nil, errors.Wrap(err, "failed to get overrides") + } + } + + // Required + if req := b.Bucket(cacheKeyRequired); req != nil { + err := req.ForEach(func(_, v []byte) error { + m.req[string(v)] = true + return nil + }) + if err != nil { + return nil, errors.Wrap(err, "failed to get required") + } + } + + return m, nil +} + +// copyTo returns a serializable representation of lp. +func (lp LockedProject) copyTo(msg *pb.LockedProject, c *pb.Constraint) { + if lp.v == nil { + msg.UnpairedVersion = nil + } else { + lp.v.copyTo(c) + msg.UnpairedVersion = c + } + msg.Root = string(lp.pi.ProjectRoot) + msg.Source = lp.pi.Source + msg.Revision = string(lp.r) + msg.Packages = lp.pkgs +} + +// lockedProjectFromCache returns a new LockedProject with fields from m. +func lockedProjectFromCache(m *pb.LockedProject) (LockedProject, error) { + var uv UnpairedVersion + var err error + if m.UnpairedVersion != nil { + uv, err = unpairedVersionFromCache(m.UnpairedVersion) + if err != nil { + return LockedProject{}, err + } + } + return LockedProject{ + pi: ProjectIdentifier{ + ProjectRoot: ProjectRoot(m.Root), + Source: m.Source, + }, + v: uv, + r: Revision(m.Revision), + pkgs: m.Packages, + }, nil +} + +// cachePutLock stores the Lock as fields in the bolt.Bucket. +func cachePutLock(b *bolt.Bucket, l Lock) error { + // InputHash + if v := l.InputsDigest(); len(v) > 0 { + if err := b.Put(cacheKeyHash, v); err != nil { + return errors.Wrap(err, "failed to put hash") + } + } + + // Projects + if projects := l.Projects(); len(projects) > 0 { + lb, err := b.CreateBucket(cacheKeyLock) + if err != nil { + return err + } + key := make(nuts.Key, nuts.KeyLen(uint64(len(projects)-1))) + var msg pb.LockedProject + var cMsg pb.Constraint + for i, lp := range projects { + lp.copyTo(&msg, &cMsg) + v, err := proto.Marshal(&msg) + if err != nil { + return err + } + key.Put(uint64(i)) + if err := lb.Put(key, v); err != nil { + return err + } + } + } + + return nil +} + +// cacheGetLock returns a new *safeLock with the fields retrieved from the bolt.Bucket. +func cacheGetLock(b *bolt.Bucket) (*safeLock, error) { + l := &safeLock{ + h: b.Get(cacheKeyHash), + } + if locked := b.Bucket(cacheKeyLock); locked != nil { + var msg pb.LockedProject + err := locked.ForEach(func(_, v []byte) error { + if err := proto.Unmarshal(v, &msg); err != nil { + return err + } + lp, err := lockedProjectFromCache(&msg) + if err != nil { + return err + } + l.p = append(l.p, lp) + return nil + }) + if err != nil { + return nil, errors.Wrap(err, "failed to get locked projects") + } + } + return l, nil +} + +// cachePutPackageOrError stores the pkgtree.PackageOrErr as fields in the bolt.Bucket. +func cachePutPackageOrErr(b *bolt.Bucket, poe pkgtree.PackageOrErr) error { + if poe.Err != nil { + err := b.Put(cacheKeyError, []byte(poe.Err.Error())) + return errors.Wrapf(err, "failed to put error: %v", poe.Err) + } + if len(poe.P.CommentPath) > 0 { + err := b.Put(cacheKeyComment, []byte(poe.P.CommentPath)) + if err != nil { + return errors.Wrapf(err, "failed to put package: %v", poe.P) + } + } + if len(poe.P.Imports) > 0 { + ip, err := b.CreateBucket(cacheKeyImport) + if err != nil { + return err + } + key := make(nuts.Key, nuts.KeyLen(uint64(len(poe.P.Imports)-1))) + for i := range poe.P.Imports { + v := []byte(poe.P.Imports[i]) + key.Put(uint64(i)) + if err := ip.Put(key, v); err != nil { + return err + } + } + } + + if len(poe.P.Name) > 0 { + err := b.Put(cacheKeyName, []byte(poe.P.Name)) + if err != nil { + return errors.Wrapf(err, "failed to put package: %v", poe.P) + } + } + + if len(poe.P.TestImports) > 0 { + ip, err := b.CreateBucket(cacheKeyTestImport) + if err != nil { + return err + } + key := make(nuts.Key, nuts.KeyLen(uint64(len(poe.P.TestImports)-1))) + for i := range poe.P.TestImports { + v := []byte(poe.P.TestImports[i]) + key.Put(uint64(i)) + if err := ip.Put(key, v); err != nil { + return err + } + } + } + return nil +} + +// cacheGetPackageOrErr returns a new pkgtree.PackageOrErr with fields retrieved +// from the bolt.Bucket. +func cacheGetPackageOrErr(b *bolt.Bucket) (pkgtree.PackageOrErr, error) { + if v := b.Get(cacheKeyError); len(v) > 0 { + return pkgtree.PackageOrErr{ + Err: errors.New(string(v)), + }, nil + } + + var p pkgtree.Package + p.CommentPath = string(b.Get(cacheKeyComment)) + if ip := b.Bucket(cacheKeyImport); ip != nil { + err := ip.ForEach(func(_, v []byte) error { + p.Imports = append(p.Imports, string(v)) + return nil + }) + if err != nil { + return pkgtree.PackageOrErr{}, err + } + } + p.Name = string(b.Get(cacheKeyName)) + if tip := b.Bucket(cacheKeyTestImport); tip != nil { + err := tip.ForEach(func(_, v []byte) error { + p.TestImports = append(p.TestImports, string(v)) + return nil + }) + if err != nil { + return pkgtree.PackageOrErr{}, err + } + } + return pkgtree.PackageOrErr{P: p}, nil +} + +// cacheTimestampedKey returns a prefixed key with a trailing timestamp. +func cacheTimestampedKey(pre byte, t time.Time) []byte { + b := make([]byte, 9) + b[0] = pre + binary.BigEndian.PutUint64(b[1:], uint64(t.Unix())) + return b +} + +// boltTxOrBucket is a minimal interface satisfied by bolt.Tx and bolt.Bucket. +type boltTxOrBucket interface { + Cursor() *bolt.Cursor + DeleteBucket([]byte) error + Bucket([]byte) *bolt.Bucket +} + +// cachePrefixDelete prefix scans and deletes each bucket. +func cachePrefixDelete(tob boltTxOrBucket, pre byte) error { + c := tob.Cursor() + for k, _ := c.Seek([]byte{pre}); len(k) > 0 && k[0] == pre; k, _ = c.Next() { + if err := tob.DeleteBucket(k); err != nil { + return errors.Wrapf(err, "failed to delete bucket: %s", k) + } + } + return nil +} + +// cacheFindLatestValid prefix scans for the latest bucket which is timestamped >= epoch, +// or returns nil if none exists. +func cacheFindLatestValid(tob boltTxOrBucket, pre byte, epoch int64) *bolt.Bucket { + c := tob.Cursor() + var latest []byte + for k, _ := c.Seek([]byte{pre}); len(k) > 0 && k[0] == pre; k, _ = c.Next() { + latest = k + } + if latest == nil { + return nil + } + ts := latest[1:] + if len(ts) != 8 { + return nil + } + if int64(binary.BigEndian.Uint64(ts)) < epoch { + return nil + } + return tob.Bucket(latest) +} diff --git a/vendor/github.com/golang/dep/gps/source_cache_bolt_encode_test.go b/vendor/github.com/golang/dep/gps/source_cache_bolt_encode_test.go new file mode 100644 index 00000000..c4f7dd2f --- /dev/null +++ b/vendor/github.com/golang/dep/gps/source_cache_bolt_encode_test.go @@ -0,0 +1,78 @@ +// Copyright 2017 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 gps + +import ( + "bytes" + "testing" + "time" + + "github.com/golang/protobuf/proto" +) + +func TestPropertiesFromCache(t *testing.T) { + for _, test := range []struct { + name string + ip ProjectRoot + pp ProjectProperties + }{ + {"defaultBranch", + "root", ProjectProperties{"", newDefaultBranch("test")}}, + {"branch", + "root", ProjectProperties{"source", NewBranch("test")}}, + {"semver", + "root", ProjectProperties{"", testSemverConstraint(t, "^1.0.0")}}, + {"rev", + "root", ProjectProperties{"source", Revision("test")}}, + {"any", + "root", ProjectProperties{"source", Any()}}, + } { + t.Run(test.name, func(t *testing.T) { + var buf projectPropertiesMsgs + buf.copyFrom(test.ip, test.pp) + v, err := proto.Marshal(&buf.pp) + if err != nil { + t.Fatal(err) + } + + if err := proto.Unmarshal(v, &buf.pp); err != nil { + t.Fatal(err) + } else { + ip, pp, err := propertiesFromCache(&buf.pp) + if err != nil { + t.Fatal(err) + } + if ip != test.ip { + t.Errorf("decoded unexpected ProjectRoot:\n\t(GOT): %#v\n\t(WNT): %#v", ip, test.ip) + } + if pp.Source != test.pp.Source { + t.Errorf("decoded unexpected ProjectRoot.Source:\n\t(GOT): %s\n\t (WNT): %s", pp.Source, test.pp.Source) + } + if !pp.Constraint.identical(test.pp.Constraint) { + t.Errorf("decoded non-identical ProjectRoot.Constraint:\n\t(GOT): %#v\n\t(WNT): %#v", pp.Constraint, test.pp.Constraint) + } + } + }) + } +} + +func TestCacheTimestampedKey(t *testing.T) { + pre := byte('p') + for _, test := range []struct { + ts time.Time + suffix []byte + }{ + {time.Unix(0, 0), []byte{0, 0, 0, 0, 0, 0, 0, 0}}, + {time.Unix(100, 0), []byte{0, 0, 0, 0, 0, 0, 0, 100}}, + {time.Unix(255, 0), []byte{0, 0, 0, 0, 0, 0, 0, 255}}, + {time.Unix(1+1<<8+1<<16+1<<24, 0), []byte{0, 0, 0, 0, 1, 1, 1, 1}}, + {time.Unix(255<<48, 0), []byte{0, 255, 0, 0, 0, 0, 0, 0}}, + } { + b := cacheTimestampedKey(pre, test.ts) + if !bytes.Equal(b, append([]byte{pre}, test.suffix...)) { + t.Errorf("unexpected suffix:\n\t(GOT):%v\n\t(WNT):%v", b[4:], test.suffix) + } + } +} diff --git a/vendor/github.com/golang/dep/gps/source_cache_bolt_test.go b/vendor/github.com/golang/dep/gps/source_cache_bolt_test.go new file mode 100644 index 00000000..66a56642 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/source_cache_bolt_test.go @@ -0,0 +1,298 @@ +// Copyright 2017 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 gps + +import ( + "io/ioutil" + "log" + "testing" + "time" + + "github.com/golang/dep/gps/pkgtree" + "github.com/golang/dep/internal/test" +) + +func TestBoltCacheTimeout(t *testing.T) { + const root = "example.com/test" + cpath, err := ioutil.TempDir("", "singlesourcecache") + if err != nil { + t.Fatalf("Failed to create temp cache dir: %s", err) + } + pi := ProjectIdentifier{ProjectRoot: root} + logger := log.New(test.Writer{TB: t}, "", 0) + + start := time.Now() + bc, err := newBoltCache(cpath, start.Unix(), logger) + if err != nil { + t.Fatal(err) + } + defer bc.close() + c := bc.newSingleSourceCache(pi) + + rev := Revision("test") + ai := ProjectAnalyzerInfo{Name: "name", Version: 42} + + manifest := &simpleRootManifest{ + c: ProjectConstraints{ + ProjectRoot("foo"): ProjectProperties{ + Constraint: Any(), + }, + ProjectRoot("bar"): ProjectProperties{ + Source: "whatever", + Constraint: testSemverConstraint(t, "> 1.3"), + }, + }, + ovr: ProjectConstraints{ + ProjectRoot("b"): ProjectProperties{ + Constraint: testSemverConstraint(t, "2.0.0"), + }, + }, + } + + lock := &safeLock{ + h: []byte("test_hash"), + p: []LockedProject{ + NewLockedProject(mkPI("github.com/sdboyer/gps"), NewVersion("v0.10.0"), []string{"gps"}), + NewLockedProject(mkPI("github.com/sdboyer/gps2"), NewVersion("v0.10.0"), nil), + NewLockedProject(mkPI("github.com/sdboyer/gps3"), NewVersion("v0.10.0"), []string{"gps", "flugle"}), + NewLockedProject(mkPI("foo"), NewVersion("nada"), []string{"foo"}), + NewLockedProject(mkPI("github.com/sdboyer/gps4"), NewVersion("v0.10.0"), []string{"flugle", "gps"}), + }, + } + + ptree := pkgtree.PackageTree{ + ImportRoot: root, + Packages: map[string]pkgtree.PackageOrErr{ + "simple": { + P: pkgtree.Package{ + ImportPath: "simple", + CommentPath: "comment", + Name: "simple", + Imports: []string{ + "github.com/golang/dep/gps", + "sort", + }, + }, + }, + "m1p": { + P: pkgtree.Package{ + ImportPath: "m1p", + CommentPath: "", + Name: "m1p", + Imports: []string{ + "github.com/golang/dep/gps", + "os", + "sort", + }, + }, + }, + }, + } + + pvs := []PairedVersion{ + NewBranch("originalbranch").Pair("rev1"), + NewVersion("originalver").Pair("rev2"), + } + + // Write values timestamped > `start`. + { + c.setManifestAndLock(rev, ai, manifest, lock) + c.setPackageTree(rev, ptree) + c.setVersionMap(pvs) + } + // Read back values timestamped > `start`. + { + gotM, gotL, ok := c.getManifestAndLock(rev, ai) + if !ok { + t.Error("no manifest and lock found for revision") + } + compareManifests(t, manifest, gotM) + if dl := DiffLocks(lock, gotL); dl != nil { + t.Errorf("lock differences:\n\t %#v", dl) + } + + got, ok := c.getPackageTree(rev) + if !ok { + t.Errorf("no package tree found:\n\t(WNT): %#v", ptree) + } + comparePackageTree(t, ptree, got) + + gotV, ok := c.getAllVersions() + if !ok || len(gotV) != len(pvs) { + t.Errorf("unexpected versions:\n\t(GOT): %#v\n\t(WNT): %#v", gotV, pvs) + } else { + SortPairedForDowngrade(gotV) + for i := range pvs { + if !pvs[i].identical(gotV[i]) { + t.Errorf("unexpected versions:\n\t(GOT): %#v\n\t(WNT): %#v", gotV, pvs) + break + } + } + } + } + + if err := bc.close(); err != nil { + t.Fatal("failed to close cache:", err) + } + + // Read with a later epoch. Expect no *timestamped* values, since all were < `after`. + { + after := start.Add(1000 * time.Hour) + bc, err = newBoltCache(cpath, after.Unix(), logger) + if err != nil { + t.Fatal(err) + } + c = bc.newSingleSourceCache(pi) + + gotM, gotL, ok := c.getManifestAndLock(rev, ai) + if !ok { + t.Error("no manifest and lock found for revision") + } + compareManifests(t, manifest, gotM) + if dl := DiffLocks(lock, gotL); dl != nil { + t.Errorf("lock differences:\n\t %#v", dl) + } + + gotPtree, ok := c.getPackageTree(rev) + if !ok { + t.Errorf("no package tree found:\n\t(WNT): %#v", ptree) + } + comparePackageTree(t, ptree, gotPtree) + + pvs, ok := c.getAllVersions() + if ok || len(pvs) > 0 { + t.Errorf("expected no cached versions, but got:\n\t%#v", pvs) + } + } + + if err := bc.close(); err != nil { + t.Fatal("failed to close cache:", err) + } + + // Re-connect with the original epoch. + bc, err = newBoltCache(cpath, start.Unix(), logger) + if err != nil { + t.Fatal(err) + } + c = bc.newSingleSourceCache(pi) + // Read values timestamped > `start`. + { + gotM, gotL, ok := c.getManifestAndLock(rev, ai) + if !ok { + t.Error("no manifest and lock found for revision") + } + compareManifests(t, manifest, gotM) + if dl := DiffLocks(lock, gotL); dl != nil { + t.Errorf("lock differences:\n\t %#v", dl) + } + + got, ok := c.getPackageTree(rev) + if !ok { + t.Errorf("no package tree found:\n\t(WNT): %#v", ptree) + } + comparePackageTree(t, ptree, got) + + gotV, ok := c.getAllVersions() + if !ok || len(gotV) != len(pvs) { + t.Errorf("unexpected versions:\n\t(GOT): %#v\n\t(WNT): %#v", gotV, pvs) + } else { + SortPairedForDowngrade(gotV) + for i := range pvs { + if !pvs[i].identical(gotV[i]) { + t.Errorf("unexpected versions:\n\t(GOT): %#v\n\t(WNT): %#v", gotV, pvs) + break + } + } + } + } + + // New values. + newManifest := &simpleRootManifest{ + c: ProjectConstraints{ + ProjectRoot("foo"): ProjectProperties{ + Constraint: NewBranch("master"), + }, + ProjectRoot("bar"): ProjectProperties{ + Source: "whatever", + Constraint: testSemverConstraint(t, "> 1.5"), + }, + }, + } + + newLock := &safeLock{ + h: []byte("new_test_hash"), + p: []LockedProject{ + NewLockedProject(mkPI("github.com/sdboyer/gps"), NewVersion("v1"), []string{"gps"}), + }, + } + + newPtree := pkgtree.PackageTree{ + ImportRoot: root, + Packages: map[string]pkgtree.PackageOrErr{ + "simple": { + P: pkgtree.Package{ + ImportPath: "simple", + CommentPath: "newcomment", + Name: "simple", + Imports: []string{ + "github.com/golang/dep/gps42", + "test", + }, + }, + }, + "m1p": { + P: pkgtree.Package{ + ImportPath: "m1p", + CommentPath: "", + Name: "m1p", + Imports: []string{ + "os", + }, + }, + }, + }, + } + + newPVS := []PairedVersion{ + NewBranch("newbranch").Pair("revA"), + NewVersion("newver").Pair("revB"), + } + // Overwrite with new values, and with timestamps > `after`. + { + c.setManifestAndLock(rev, ai, newManifest, newLock) + c.setPackageTree(rev, newPtree) + c.setVersionMap(newPVS) + } + // Read new values. + { + gotM, gotL, ok := c.getManifestAndLock(rev, ai) + if !ok { + t.Error("no manifest and lock found for revision") + } + compareManifests(t, newManifest, gotM) + if dl := DiffLocks(newLock, gotL); dl != nil { + t.Errorf("lock differences:\n\t %#v", dl) + } + + got, ok := c.getPackageTree(rev) + if !ok { + t.Errorf("no package tree found:\n\t(WNT): %#v", newPtree) + } + comparePackageTree(t, newPtree, got) + + gotV, ok := c.getAllVersions() + if !ok || len(gotV) != len(newPVS) { + t.Errorf("unexpected versions:\n\t(GOT): %#v\n\t(WNT): %#v", gotV, newPVS) + } else { + SortPairedForDowngrade(gotV) + for i := range newPVS { + if !newPVS[i].identical(gotV[i]) { + t.Errorf("unexpected versions:\n\t(GOT): %#v\n\t(WNT): %#v", gotV, newPVS) + break + } + } + } + } +} diff --git a/vendor/github.com/golang/dep/gps/source_cache_multi.go b/vendor/github.com/golang/dep/gps/source_cache_multi.go new file mode 100644 index 00000000..e28a2b1c --- /dev/null +++ b/vendor/github.com/golang/dep/gps/source_cache_multi.go @@ -0,0 +1,120 @@ +// Copyright 2017 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 gps + +import ( + "github.com/golang/dep/gps/pkgtree" +) + +// A multiCache manages two cache levels, ephemeral in-memory and persistent on-disk. +// +// The in-memory cache is always checked first, with the on-disk used as a fallback. +// Values read from disk are set in-memory when an appropriate method exists. +// +// Set values are cached both in-memory and on-disk. +type multiCache struct { + mem, disk singleSourceCache +} + +func (c *multiCache) setManifestAndLock(r Revision, ai ProjectAnalyzerInfo, m Manifest, l Lock) { + c.mem.setManifestAndLock(r, ai, m, l) + c.disk.setManifestAndLock(r, ai, m, l) +} + +func (c *multiCache) getManifestAndLock(r Revision, ai ProjectAnalyzerInfo) (Manifest, Lock, bool) { + m, l, ok := c.mem.getManifestAndLock(r, ai) + if ok { + return m, l, true + } + + m, l, ok = c.disk.getManifestAndLock(r, ai) + if ok { + c.mem.setManifestAndLock(r, ai, m, l) + return m, l, true + } + + return nil, nil, false +} + +func (c *multiCache) setPackageTree(r Revision, ptree pkgtree.PackageTree) { + c.mem.setPackageTree(r, ptree) + c.disk.setPackageTree(r, ptree) +} + +func (c *multiCache) getPackageTree(r Revision) (pkgtree.PackageTree, bool) { + ptree, ok := c.mem.getPackageTree(r) + if ok { + return ptree, true + } + + ptree, ok = c.disk.getPackageTree(r) + if ok { + c.mem.setPackageTree(r, ptree) + return ptree, true + } + + return pkgtree.PackageTree{}, false +} + +func (c *multiCache) markRevisionExists(r Revision) { + c.mem.markRevisionExists(r) + c.disk.markRevisionExists(r) +} + +func (c *multiCache) setVersionMap(pvs []PairedVersion) { + c.mem.setVersionMap(pvs) + c.disk.setVersionMap(pvs) +} + +func (c *multiCache) getVersionsFor(rev Revision) ([]UnpairedVersion, bool) { + uvs, ok := c.mem.getVersionsFor(rev) + if ok { + return uvs, true + } + + return c.disk.getVersionsFor(rev) +} + +func (c *multiCache) getAllVersions() ([]PairedVersion, bool) { + pvs, ok := c.mem.getAllVersions() + if ok { + return pvs, true + } + + pvs, ok = c.disk.getAllVersions() + if ok { + c.mem.setVersionMap(pvs) + return pvs, true + } + + return nil, false +} + +func (c *multiCache) getRevisionFor(uv UnpairedVersion) (Revision, bool) { + rev, ok := c.mem.getRevisionFor(uv) + if ok { + return rev, true + } + + return c.disk.getRevisionFor(uv) +} + +func (c *multiCache) toRevision(v Version) (Revision, bool) { + rev, ok := c.mem.toRevision(v) + if ok { + return rev, true + } + + return c.disk.toRevision(v) +} + +func (c *multiCache) toUnpaired(v Version) (UnpairedVersion, bool) { + uv, ok := c.mem.toUnpaired(v) + if ok { + return uv, true + } + + return c.disk.toUnpaired(v) +} diff --git a/vendor/github.com/golang/dep/gps/source_cache_test.go b/vendor/github.com/golang/dep/gps/source_cache_test.go new file mode 100644 index 00000000..590619da --- /dev/null +++ b/vendor/github.com/golang/dep/gps/source_cache_test.go @@ -0,0 +1,578 @@ +// Copyright 2017 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 gps + +import ( + "io/ioutil" + "log" + "reflect" + "sort" + "testing" + "time" + + "github.com/golang/dep/gps/pkgtree" + "github.com/golang/dep/internal/test" + "github.com/pkg/errors" +) + +func Test_singleSourceCache(t *testing.T) { + newMem := func(*testing.T, string, string) (singleSourceCache, func() error) { + return newMemoryCache(), func() error { return nil } + } + t.Run("mem", singleSourceCacheTest{newCache: newMem}.run) + + epoch := time.Now().Unix() + newBolt := func(t *testing.T, cachedir, root string) (singleSourceCache, func() error) { + pi := mkPI(root).normalize() + bc, err := newBoltCache(cachedir, epoch, log.New(test.Writer{TB: t}, "", 0)) + if err != nil { + t.Fatal(err) + } + return bc.newSingleSourceCache(pi), bc.close + } + t.Run("bolt/keepOpen", singleSourceCacheTest{newCache: newBolt}.run) + t.Run("bolt/reOpen", singleSourceCacheTest{newCache: newBolt, persistent: true}.run) + + newMulti := func(t *testing.T, cachedir, root string) (singleSourceCache, func() error) { + disk, close := newBolt(t, cachedir, root) + return &multiCache{mem: newMemoryCache(), disk: disk}, close + } + t.Run("multi/keepOpen", singleSourceCacheTest{newCache: newMulti}.run) + t.Run("multi/reOpen", singleSourceCacheTest{persistent: true, newCache: newMulti}.run) + + t.Run("multi/keepOpen/noDisk", singleSourceCacheTest{ + newCache: func(*testing.T, string, string) (singleSourceCache, func() error) { + return &multiCache{mem: newMemoryCache(), disk: discardCache{}}, func() error { return nil } + }, + }.run) + + t.Run("multi/reOpen/noMem", singleSourceCacheTest{ + persistent: true, + newCache: func(t *testing.T, cachedir, root string) (singleSourceCache, func() error) { + disk, close := newBolt(t, cachedir, root) + return &multiCache{mem: discardCache{}, disk: disk}, close + }, + }.run) +} + +var testAnalyzerInfo = ProjectAnalyzerInfo{ + Name: "test-analyzer", + Version: 1, +} + +type singleSourceCacheTest struct { + newCache func(*testing.T, string, string) (cache singleSourceCache, close func() error) + persistent bool +} + +// run tests singleSourceCache methods of caches returned by test.newCache. +// For test.persistent caches, test.newCache is periodically called mid-test to ensure persistence. +func (test singleSourceCacheTest) run(t *testing.T) { + const root = "example.com/test" + cpath, err := ioutil.TempDir("", "singlesourcecache") + if err != nil { + t.Fatalf("Failed to create temp cache dir: %s", err) + } + + t.Run("info", func(t *testing.T) { + const rev Revision = "revision" + + c, close := test.newCache(t, cpath, root) + defer func() { + if err := close(); err != nil { + t.Fatal("failed to close cache:", err) + } + }() + + var m Manifest = &simpleRootManifest{ + c: ProjectConstraints{ + ProjectRoot("foo"): ProjectProperties{ + Constraint: Any(), + }, + ProjectRoot("bar"): ProjectProperties{ + Source: "whatever", + Constraint: testSemverConstraint(t, "> 1.3"), + }, + }, + ovr: ProjectConstraints{ + ProjectRoot("b"): ProjectProperties{ + Constraint: testSemverConstraint(t, "2.0.0"), + }, + }, + req: map[string]bool{ + "c": true, + "d": true, + }, + ig: pkgtree.NewIgnoredRuleset([]string{"a", "b"}), + } + var l Lock = &safeLock{ + h: []byte("test_hash"), + p: []LockedProject{ + NewLockedProject(mkPI("github.com/sdboyer/gps"), NewVersion("v0.10.0"), []string{"gps"}), + NewLockedProject(mkPI("github.com/sdboyer/gps2"), NewVersion("v0.10.0"), nil), + NewLockedProject(mkPI("github.com/sdboyer/gps3"), NewVersion("v0.10.0"), []string{"gps", "flugle"}), + NewLockedProject(mkPI("foo"), NewVersion("nada"), []string{"foo"}), + NewLockedProject(mkPI("github.com/sdboyer/gps4"), NewVersion("v0.10.0"), []string{"flugle", "gps"}), + }, + } + c.setManifestAndLock(rev, testAnalyzerInfo, m, l) + + if test.persistent { + if err := close(); err != nil { + t.Fatal("failed to close cache:", err) + } + c, close = test.newCache(t, cpath, root) + } + + gotM, gotL, ok := c.getManifestAndLock(rev, testAnalyzerInfo) + if !ok { + t.Error("no manifest and lock found for revision") + } + compareManifests(t, m, gotM) + if dl := DiffLocks(l, gotL); dl != nil { + t.Errorf("lock differences:\n\t %#v", dl) + } + + m = &simpleRootManifest{ + c: ProjectConstraints{ + ProjectRoot("foo"): ProjectProperties{ + Source: "whatever", + Constraint: Any(), + }, + }, + ovr: ProjectConstraints{ + ProjectRoot("bar"): ProjectProperties{ + Constraint: testSemverConstraint(t, "2.0.0"), + }, + }, + req: map[string]bool{ + "a": true, + "b": true, + }, + ig: pkgtree.NewIgnoredRuleset([]string{"c", "d"}), + } + l = &safeLock{ + h: []byte("different_test_hash"), + p: []LockedProject{ + NewLockedProject(mkPI("github.com/sdboyer/gps"), NewVersion("v0.10.0").Pair("278a227dfc3d595a33a77ff3f841fd8ca1bc8cd0"), []string{"gps"}), + NewLockedProject(mkPI("github.com/sdboyer/gps2"), NewVersion("v0.11.0"), []string{"gps"}), + NewLockedProject(mkPI("github.com/sdboyer/gps3"), Revision("278a227dfc3d595a33a77ff3f841fd8ca1bc8cd0"), []string{"gps"}), + }, + } + c.setManifestAndLock(rev, testAnalyzerInfo, m, l) + + if test.persistent { + if err := close(); err != nil { + t.Fatal("failed to close cache:", err) + } + c, close = test.newCache(t, cpath, root) + } + + gotM, gotL, ok = c.getManifestAndLock(rev, testAnalyzerInfo) + if !ok { + t.Error("no manifest and lock found for revision") + } + compareManifests(t, m, gotM) + if dl := DiffLocks(l, gotL); dl != nil { + t.Errorf("lock differences:\n\t %#v", dl) + } + }) + + t.Run("pkgTree", func(t *testing.T) { + c, close := test.newCache(t, cpath, root) + defer func() { + if err := close(); err != nil { + t.Fatal("failed to close cache:", err) + } + }() + + const rev Revision = "rev_adsfjkl" + + if got, ok := c.getPackageTree(rev); ok { + t.Fatalf("unexpected result before setting package tree: %v", got) + } + + if test.persistent { + if err := close(); err != nil { + t.Fatal("failed to close cache:", err) + } + c, close = test.newCache(t, cpath, root) + } + + pt := pkgtree.PackageTree{ + ImportRoot: root, + Packages: map[string]pkgtree.PackageOrErr{ + "simple": { + P: pkgtree.Package{ + ImportPath: "simple", + CommentPath: "comment", + Name: "simple", + Imports: []string{ + "github.com/golang/dep/gps", + "sort", + }, + }, + }, + "m1p": { + P: pkgtree.Package{ + ImportPath: "m1p", + CommentPath: "", + Name: "m1p", + Imports: []string{ + "github.com/golang/dep/gps", + "os", + "sort", + }, + }, + }, + }, + } + c.setPackageTree(rev, pt) + + if test.persistent { + if err := close(); err != nil { + t.Fatal("failed to close cache:", err) + } + c, close = test.newCache(t, cpath, root) + } + + got, ok := c.getPackageTree(rev) + if !ok { + t.Errorf("no package tree found:\n\t(WNT): %#v", pt) + } + comparePackageTree(t, pt, got) + + if test.persistent { + if err := close(); err != nil { + t.Fatal("failed to close cache:", err) + } + c, close = test.newCache(t, cpath, root) + } + + pt = pkgtree.PackageTree{ + ImportRoot: root, + Packages: map[string]pkgtree.PackageOrErr{ + "test": { + Err: errors.New("error"), + }, + }, + } + c.setPackageTree(rev, pt) + + if test.persistent { + if err := close(); err != nil { + t.Fatal("failed to close cache:", err) + } + c, close = test.newCache(t, cpath, root) + } + + got, ok = c.getPackageTree(rev) + if !ok { + t.Errorf("no package tree found:\n\t(WNT): %#v", pt) + } + comparePackageTree(t, pt, got) + }) + + t.Run("versions", func(t *testing.T) { + c, close := test.newCache(t, cpath, root) + defer func() { + if err := close(); err != nil { + t.Fatal("failed to close cache:", err) + } + }() + + const rev1, rev2 = "rev1", "rev2" + const br, ver = "branch_name", "2.10" + versions := []PairedVersion{ + NewBranch(br).Pair(rev1), + NewVersion(ver).Pair(rev2), + } + SortPairedForDowngrade(versions) + c.setVersionMap(versions) + + if test.persistent { + if err := close(); err != nil { + t.Fatal("failed to close cache:", err) + } + c, close = test.newCache(t, cpath, root) + } + + t.Run("getAllVersions", func(t *testing.T) { + got, ok := c.getAllVersions() + if !ok || len(got) != len(versions) { + t.Errorf("unexpected versions:\n\t(GOT): %#v\n\t(WNT): %#v", got, versions) + } else { + SortPairedForDowngrade(got) + for i := range versions { + if !versions[i].identical(got[i]) { + t.Errorf("unexpected versions:\n\t(GOT): %#v\n\t(WNT): %#v", got, versions) + break + } + } + } + }) + + revToUV := map[Revision]UnpairedVersion{ + rev1: NewBranch(br), + rev2: NewVersion(ver), + } + + t.Run("getVersionsFor", func(t *testing.T) { + for rev, want := range revToUV { + rev, want := rev, want + t.Run(string(rev), func(t *testing.T) { + uvs, ok := c.getVersionsFor(rev) + if !ok { + t.Errorf("no version found:\n\t(WNT) %#v", want) + } else if len(uvs) != 1 { + t.Errorf("expected one result but got %d", len(uvs)) + } else { + uv := uvs[0] + if uv.Type() != want.Type() { + t.Errorf("expected version type %d but got %d", want.Type(), uv.Type()) + } + if uv.String() != want.String() { + t.Errorf("expected version %q but got %q", want.String(), uv.String()) + } + } + }) + } + }) + + t.Run("getRevisionFor", func(t *testing.T) { + for want, uv := range revToUV { + want, uv := want, uv + t.Run(uv.String(), func(t *testing.T) { + rev, ok := c.getRevisionFor(uv) + if !ok { + t.Errorf("expected revision %q but got none", want) + } else if rev != want { + t.Errorf("expected revision %q but got %q", want, rev) + } + }) + } + }) + + t.Run("toRevision", func(t *testing.T) { + for want, uv := range revToUV { + want, uv := want, uv + t.Run(uv.String(), func(t *testing.T) { + rev, ok := c.toRevision(uv) + if !ok { + t.Errorf("expected revision %q but got none", want) + } else if rev != want { + t.Errorf("expected revision %q but got %q", want, rev) + } + }) + } + }) + + t.Run("toUnpaired", func(t *testing.T) { + for rev, want := range revToUV { + rev, want := rev, want + t.Run(want.String(), func(t *testing.T) { + uv, ok := c.toUnpaired(rev) + if !ok { + t.Errorf("no UnpairedVersion found:\n\t(WNT): %#v", uv) + } else if !uv.identical(want) { + t.Errorf("unexpected UnpairedVersion:\n\t(GOT): %#v\n\t(WNT): %#v", uv, want) + } + }) + } + }) + }) +} + +// compareManifests compares two manifests and reports differences as test errors. +func compareManifests(t *testing.T, want, got Manifest) { + if (want == nil || got == nil) && (got != nil || want != nil) { + t.Errorf("one manifest is nil:\n\t(GOT): %#v\n\t(WNT): %#v", got, want) + return + } + { + want, got := want.DependencyConstraints(), got.DependencyConstraints() + if !projectConstraintsEqual(want, got) { + t.Errorf("unexpected constraints:\n\t(GOT): %#v\n\t(WNT): %#v", got, want) + } + } + + wantRM, wantOK := want.(RootManifest) + gotRM, gotOK := got.(RootManifest) + if wantOK && !gotOK { + t.Errorf("expected RootManifest:\n\t(GOT): %#v", got) + return + } + if gotOK && !wantOK { + t.Errorf("didn't expected RootManifest:\n\t(GOT): %#v", got) + return + } + + { + want, got := wantRM.IgnoredPackages(), gotRM.IgnoredPackages() + if !reflect.DeepEqual(want.ToSlice(), got.ToSlice()) { + t.Errorf("unexpected ignored packages:\n\t(GOT): %#v\n\t(WNT): %#v", got, want) + } + } + + { + want, got := wantRM.Overrides(), gotRM.Overrides() + if !projectConstraintsEqual(want, got) { + t.Errorf("unexpected overrides:\n\t(GOT): %#v\n\t(WNT): %#v", got, want) + } + } + + { + want, got := wantRM.RequiredPackages(), gotRM.RequiredPackages() + if !mapStringBoolEqual(want, got) { + t.Errorf("unexpected required packages:\n\t(GOT): %#v\n\t(WNT): %#v", got, want) + } + } +} + +// comparePackageTree compares two pkgtree.PackageTree and reports differences as test errors. +func comparePackageTree(t *testing.T, want, got pkgtree.PackageTree) { + if got.ImportRoot != want.ImportRoot { + t.Errorf("expected package tree root %q but got %q", want.ImportRoot, got.ImportRoot) + } + { + want, got := want.Packages, got.Packages + if len(want) != len(got) { + t.Errorf("unexpected packages:\n\t(GOT): %#v\n\t(WNT): %#v", got, want) + } else { + for k, v := range want { + if v2, ok := got[k]; !ok { + t.Errorf("key %q: expected %v but got none", k, v) + } else if !packageOrErrEqual(v, v2) { + t.Errorf("key %q: expected %v but got %v", k, v, v2) + } + } + } + } +} + +func projectConstraintsEqual(want, got ProjectConstraints) bool { + loop, check := want, got + if len(got) > len(want) { + loop, check = got, want + } + for pr, pp := range loop { + pp2, ok := check[pr] + if !ok { + return false + } + if pp.Source != pp2.Source { + return false + } + if pp.Constraint == nil || pp2.Constraint == nil { + if pp.Constraint != nil || pp2.Constraint != nil { + return false + } + } else if !pp.Constraint.identical(pp2.Constraint) { + return false + } + } + return true +} + +func mapStringBoolEqual(exp, got map[string]bool) bool { + loop, check := exp, got + if len(got) > len(exp) { + loop, check = got, exp + } + for k, v := range loop { + v2, ok := check[k] + if !ok || v != v2 { + return false + } + } + return true +} + +func safeError(err error) string { + if err == nil { + return "" + } + return err.Error() +} + +// packageOrErrEqual return true if the pkgtree.PackageOrErrs are equal. Error equality is +// string based. Imports and TestImports are treated as sets, and will be sorted. +func packageOrErrEqual(a, b pkgtree.PackageOrErr) bool { + if safeError(a.Err) != safeError(b.Err) { + return false + } + if a.P.Name != b.P.Name { + return false + } + if a.P.ImportPath != b.P.ImportPath { + return false + } + if a.P.CommentPath != b.P.CommentPath { + return false + } + + if len(a.P.Imports) != len(b.P.Imports) { + return false + } + sort.Strings(a.P.Imports) + sort.Strings(b.P.Imports) + for i := range a.P.Imports { + if a.P.Imports[i] != b.P.Imports[i] { + return false + } + } + + if len(a.P.TestImports) != len(b.P.TestImports) { + return false + } + sort.Strings(a.P.TestImports) + sort.Strings(b.P.TestImports) + for i := range a.P.TestImports { + if a.P.TestImports[i] != b.P.TestImports[i] { + return false + } + } + + return true +} + +// discardCache discards set values and returns nothing. +type discardCache struct{} + +func (discardCache) setManifestAndLock(Revision, ProjectAnalyzerInfo, Manifest, Lock) {} + +func (discardCache) getManifestAndLock(Revision, ProjectAnalyzerInfo) (Manifest, Lock, bool) { + return nil, nil, false +} + +func (discardCache) setPackageTree(Revision, pkgtree.PackageTree) {} + +func (discardCache) getPackageTree(Revision) (pkgtree.PackageTree, bool) { + return pkgtree.PackageTree{}, false +} + +func (discardCache) markRevisionExists(r Revision) {} + +func (discardCache) setVersionMap(versionList []PairedVersion) {} + +func (discardCache) getVersionsFor(Revision) ([]UnpairedVersion, bool) { + return nil, false +} + +func (discardCache) getAllVersions() ([]PairedVersion, bool) { + return nil, false +} + +func (discardCache) getRevisionFor(UnpairedVersion) (Revision, bool) { + return "", false +} + +func (discardCache) toRevision(v Version) (Revision, bool) { + return "", false +} + +func (discardCache) toUnpaired(v Version) (UnpairedVersion, bool) { + return nil, false +} diff --git a/vendor/github.com/golang/dep/gps/source_errors.go b/vendor/github.com/golang/dep/gps/source_errors.go new file mode 100644 index 00000000..e8aab9a7 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/source_errors.go @@ -0,0 +1,35 @@ +// Copyright 2017 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 gps + +import ( + "github.com/Masterminds/vcs" + "github.com/pkg/errors" +) + +// unwrapVcsErr recognizes *vcs.LocalError and *vsc.RemoteError, and returns a form +// preserving the actual vcs command output and error, in addition to the message. +// All other types pass through unchanged. +func unwrapVcsErr(err error) error { + var cause error + var out, msg string + + switch t := err.(type) { + case *vcs.LocalError: + cause, out, msg = t.Original(), t.Out(), t.Error() + case *vcs.RemoteError: + cause, out, msg = t.Original(), t.Out(), t.Error() + + default: + return err + } + + if cause == nil { + cause = errors.New(out) + } else { + cause = errors.Wrap(cause, out) + } + return errors.Wrap(cause, msg) +} diff --git a/vendor/github.com/golang/dep/gps/source_errors_test.go b/vendor/github.com/golang/dep/gps/source_errors_test.go new file mode 100644 index 00000000..ce6153c2 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/source_errors_test.go @@ -0,0 +1,30 @@ +// Copyright 2017 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 gps + +import ( + "testing" + + "github.com/Masterminds/vcs" +) + +func TestUnwrapVcsErrNonNil(t *testing.T) { + for _, err := range []error{ + vcs.NewRemoteError("msg", nil, "out"), + vcs.NewRemoteError("msg", nil, ""), + vcs.NewRemoteError("", nil, "out"), + vcs.NewRemoteError("", nil, ""), + vcs.NewLocalError("msg", nil, "out"), + vcs.NewLocalError("msg", nil, ""), + vcs.NewLocalError("", nil, "out"), + vcs.NewLocalError("", nil, ""), + &vcs.RemoteError{}, + &vcs.LocalError{}, + } { + if unwrapVcsErr(err) == nil { + t.Errorf("unexpected nil error unwrapping: %#v", err) + } + } +} diff --git a/vendor/github.com/golang/dep/gps/source_manager.go b/vendor/github.com/golang/dep/gps/source_manager.go new file mode 100644 index 00000000..26683979 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/source_manager.go @@ -0,0 +1,783 @@ +// Copyright 2017 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 gps + +import ( + "context" + "fmt" + "io/ioutil" + "log" + "net/url" + "os" + "os/signal" + "path/filepath" + "runtime" + "strings" + "sync" + "sync/atomic" + "time" + + "github.com/golang/dep/gps/pkgtree" + "github.com/golang/dep/internal/fs" + "github.com/nightlyone/lockfile" + "github.com/pkg/errors" + "github.com/sdboyer/constext" +) + +// Used to compute a friendly filepath from a URL-shaped input. +var sanitizer = strings.NewReplacer("-", "--", ":", "-", "/", "-", "+", "-") + +// A locker is responsible for preventing multiple instances of dep from +// interfering with one-another. +// +// Currently, anything that can either TryLock(), Unlock(), or GetOwner() +// satisfies that need. +type locker interface { + TryLock() error + Unlock() error + GetOwner() (*os.Process, error) +} + +// A falselocker adheres to the locker interface and its purpose is to quietly +// fail to lock when the DEPNOLOCK environment variable is set. +// +// This allows dep to run on systems where file locking doesn't work -- +// particularly those that use union mount type filesystems that don't +// implement hard links or fnctl() style locking. +type falseLocker struct{} + +// Always returns an error to indicate there's no current ower PID for our +// lock. +func (fl falseLocker) GetOwner() (*os.Process, error) { + return nil, fmt.Errorf("falseLocker always fails") +} + +// Does nothing and returns a nil error so caller believes locking succeeded. +func (fl falseLocker) TryLock() error { + return nil +} + +// Does nothing and returns a nil error so caller believes unlocking succeeded. +func (fl falseLocker) Unlock() error { + return nil +} + +// A SourceManager is responsible for retrieving, managing, and interrogating +// source repositories. Its primary purpose is to serve the needs of a Solver, +// but it is handy for other purposes, as well. +// +// gps's built-in SourceManager, SourceMgr, is intended to be generic and +// sufficient for any purpose. It provides some additional semantics around the +// methods defined here. +type SourceManager interface { + // SourceExists checks if a repository exists, either upstream or in the + // SourceManager's central repository cache. + SourceExists(ProjectIdentifier) (bool, error) + + // SyncSourceFor will attempt to bring all local information about a source + // fully up to date. + SyncSourceFor(ProjectIdentifier) error + + // ListVersions retrieves a list of the available versions for a given + // repository name. + ListVersions(ProjectIdentifier) ([]PairedVersion, error) + + // RevisionPresentIn indicates whether the provided Version is present in + // the given repository. + RevisionPresentIn(ProjectIdentifier, Revision) (bool, error) + + // ListPackages parses the tree of the Go packages at or below root of the + // provided ProjectIdentifier, at the provided version. + ListPackages(ProjectIdentifier, Version) (pkgtree.PackageTree, error) + + // GetManifestAndLock returns manifest and lock information for the provided + // root import path. + // + // gps currently requires that projects be rooted at their repository root, + // necessitating that the ProjectIdentifier's ProjectRoot must also be a + // repository root. + GetManifestAndLock(ProjectIdentifier, Version, ProjectAnalyzer) (Manifest, Lock, error) + + // ExportProject writes out the tree of the provided import path, at the + // provided version, to the provided directory. + ExportProject(context.Context, ProjectIdentifier, Version, string) error + + // DeduceProjectRoot takes an import path and deduces the corresponding + // project/source root. + DeduceProjectRoot(ip string) (ProjectRoot, error) + + // SourceURLsForPath takes an import path and deduces the set of source URLs + // that may refer to a canonical upstream source. + // In general, these URLs differ only by protocol (e.g. https vs. ssh), not path + SourceURLsForPath(ip string) ([]*url.URL, error) + + // Release lets go of any locks held by the SourceManager. Once called, it is + // no longer safe to call methods against it; all method calls will + // immediately result in errors. + Release() + + // InferConstraint tries to puzzle out what kind of version is given in a string - + // semver, a revision, or as a fallback, a plain tag + InferConstraint(s string, pi ProjectIdentifier) (Constraint, error) +} + +// A ProjectAnalyzer is responsible for analyzing a given path for Manifest and +// Lock information. Tools relying on gps must implement one. +type ProjectAnalyzer interface { + // Perform analysis of the filesystem tree rooted at path, with the + // root import path importRoot, to determine the project's constraints, as + // indicated by a Manifest and Lock. + // + // Note that an error will typically cause the solver to treat the analyzed + // version as unusable. As such, an error should generally only be returned + // if the code tree is somehow malformed, but not if the implementor's + // expected files containing Manifest and Lock data are merely absent. + DeriveManifestAndLock(path string, importRoot ProjectRoot) (Manifest, Lock, error) + + // Info reports this project analyzer's info. + Info() ProjectAnalyzerInfo +} + +// ProjectAnalyzerInfo indicates a ProjectAnalyzer's name and version. +type ProjectAnalyzerInfo struct { + Name string + Version int +} + +// String returns a string like: "." +func (p ProjectAnalyzerInfo) String() string { + return fmt.Sprintf("%s.%d", p.Name, p.Version) +} + +// SourceMgr is the default SourceManager for gps. +// +// There's no (planned) reason why it would need to be reimplemented by other +// tools; control via dependency injection is intended to be sufficient. +type SourceMgr struct { + cachedir string // path to root of cache dir + lf locker // handle for the sm lock file on disk + suprvsr *supervisor // subsystem that supervises running calls/io + cancelAll context.CancelFunc // cancel func to kill all running work + deduceCoord *deductionCoordinator // subsystem that manages import path deduction + srcCoord *sourceCoordinator // subsystem that manages sources + sigmut sync.Mutex // mutex protecting signal handling setup/teardown + qch chan struct{} // quit chan for signal handler + relonce sync.Once // once-er to ensure we only release once + releasing int32 // flag indicating release of sm has begun +} + +var _ SourceManager = &SourceMgr{} + +// ErrSourceManagerIsReleased is the error returned by any SourceManager method +// called after the SourceManager has been released, rendering its methods no +// longer safe to call. +var ErrSourceManagerIsReleased = fmt.Errorf("this SourceManager has been released, its methods can no longer be called") + +// SourceManagerConfig holds configuration information for creating SourceMgrs. +type SourceManagerConfig struct { + Cachedir string // Where to store local instances of upstream sources. + Logger *log.Logger // Optional info/warn logger. Discards if nil. + DisableLocking bool // True if the SourceManager should NOT use a lock file to protect the Cachedir from multiple processes. +} + +// NewSourceManager produces an instance of gps's built-in SourceManager. +// +// The returned SourceManager aggressively caches information wherever possible. +// If tools need to do preliminary work involving upstream repository analysis +// prior to invoking a solve run, it is recommended that they create this +// SourceManager as early as possible and use it to their ends. That way, the +// solver can benefit from any caches that may have already been warmed. +// +// gps's SourceManager is intended to be threadsafe (if it's not, please file a +// bug!). It should be safe to reuse across concurrent solving runs, even on +// unrelated projects. +func NewSourceManager(c SourceManagerConfig) (*SourceMgr, error) { + if c.Logger == nil { + c.Logger = log.New(ioutil.Discard, "", 0) + } + + err := fs.EnsureDir(filepath.Join(c.Cachedir, "sources"), 0777) + if err != nil { + return nil, err + } + + // Fix for #820 + // + // Consult https://godoc.org/github.com/nightlyone/lockfile for the lockfile + // behaviour. It's magic. It deals with stale processes, and if there is + // a process keeping the lock busy, it will pass back a temporary error that + // we can spin on. + + glpath := filepath.Join(c.Cachedir, "sm.lock") + + lockfile, err := func() (locker, error) { + if c.DisableLocking { + return falseLocker{}, nil + } + return lockfile.New(glpath) + }() + + if err != nil { + return nil, CouldNotCreateLockError{ + Path: glpath, + Err: errors.Wrapf(err, "unable to create lock %s", glpath), + } + } + + process, err := lockfile.GetOwner() + if err == nil { + // If we didn't get an error, then the lockfile exists already. We should + // check to see if it's us already: + if process.Pid == os.Getpid() { + return nil, CouldNotCreateLockError{ + Path: glpath, + Err: fmt.Errorf("lockfile %s already locked by this process", glpath), + } + } + + // There is a lockfile, but it's owned by someone else. We'll try to lock + // it anyway. + } + + // If it's a TemporaryError, we retry every second. Otherwise, we fail + // permanently. + // + // TODO: #534 needs to be implemented to provide a better way to log warnings, + // but until then we will just use stderr. + + // Implicit Time of 0. + var lasttime time.Time + err = lockfile.TryLock() + for err != nil { + nowtime := time.Now() + duration := nowtime.Sub(lasttime) + + // The first time this is evaluated, duration will be very large as lasttime is 0. + // Unless time travel is invented and someone travels back to the year 1, we should + // be ok. + if duration > 15*time.Second { + fmt.Fprintf(os.Stderr, "waiting for lockfile %s: %s\n", glpath, err.Error()) + lasttime = nowtime + } + + if t, ok := err.(interface { + Temporary() bool + }); ok && t.Temporary() { + time.Sleep(time.Second * 1) + } else { + return nil, CouldNotCreateLockError{ + Path: glpath, + Err: errors.Wrapf(err, "unable to lock %s", glpath), + } + } + err = lockfile.TryLock() + } + + ctx, cf := context.WithCancel(context.TODO()) + superv := newSupervisor(ctx) + deducer := newDeductionCoordinator(superv) + + sm := &SourceMgr{ + cachedir: c.Cachedir, + lf: lockfile, + suprvsr: superv, + cancelAll: cf, + deduceCoord: deducer, + srcCoord: newSourceCoordinator(superv, deducer, c.Cachedir, c.Logger), + qch: make(chan struct{}), + } + + return sm, nil +} + +// Cachedir returns the location of the cache directory. +func (sm *SourceMgr) Cachedir() string { + return sm.cachedir +} + +// UseDefaultSignalHandling sets up typical os.Interrupt signal handling for a +// SourceMgr. +func (sm *SourceMgr) UseDefaultSignalHandling() { + sigch := make(chan os.Signal, 1) + signal.Notify(sigch, os.Interrupt) + sm.HandleSignals(sigch) +} + +// HandleSignals sets up logic to handle incoming signals with the goal of +// shutting down the SourceMgr safely. +// +// Calling code must provide the signal channel, and is responsible for calling +// signal.Notify() on that channel. +// +// Successive calls to HandleSignals() will deregister the previous handler and +// set up a new one. It is not recommended that the same channel be passed +// multiple times to this method. +// +// SetUpSigHandling() will set up a handler that is appropriate for most +// use cases. +func (sm *SourceMgr) HandleSignals(sigch chan os.Signal) { + sm.sigmut.Lock() + // always start by closing the qch, which will lead to any existing signal + // handler terminating, and deregistering its sigch. + if sm.qch != nil { + close(sm.qch) + } + sm.qch = make(chan struct{}) + + // Run a new goroutine with the input sigch and the fresh qch + go func(sch chan os.Signal, qch <-chan struct{}) { + defer signal.Stop(sch) + select { + case <-sch: + // Set up a timer to uninstall the signal handler after three + // seconds, so that the user can easily force termination with a + // second ctrl-c + time.AfterFunc(3*time.Second, func() { + signal.Stop(sch) + }) + + if opc := sm.suprvsr.count(); opc > 0 { + fmt.Printf("Signal received: waiting for %v ops to complete...\n", opc) + } + + sm.Release() + case <-qch: + // quit channel triggered - deregister our sigch and return + } + }(sigch, sm.qch) + // Try to ensure handler is blocked in for-select before releasing the mutex + runtime.Gosched() + + sm.sigmut.Unlock() +} + +// StopSignalHandling deregisters any signal handler running on this SourceMgr. +// +// It's normally not necessary to call this directly; it will be called as +// needed by Release(). +func (sm *SourceMgr) StopSignalHandling() { + sm.sigmut.Lock() + if sm.qch != nil { + close(sm.qch) + sm.qch = nil + runtime.Gosched() + } + sm.sigmut.Unlock() +} + +// CouldNotCreateLockError describe failure modes in which creating a SourceMgr +// did not succeed because there was an error while attempting to create the +// on-disk lock file. +type CouldNotCreateLockError struct { + Path string + Err error +} + +func (e CouldNotCreateLockError) Error() string { + return e.Err.Error() +} + +// Release lets go of any locks held by the SourceManager. Once called, it is no +// longer safe to call methods against it; all method calls will immediately +// result in errors. +func (sm *SourceMgr) Release() { + atomic.StoreInt32(&sm.releasing, 1) + + sm.relonce.Do(func() { + // Send the signal to the supervisor to cancel all running calls. + sm.cancelAll() + sm.suprvsr.wait() + + // Close the source coordinator. + sm.srcCoord.close() + + // Close the file handle for the lock file and remove it from disk + sm.lf.Unlock() + os.Remove(filepath.Join(sm.cachedir, "sm.lock")) + + // Close the qch, if non-nil, so the signal handlers run out. This will + // also deregister the sig channel, if any has been set up. + if sm.qch != nil { + close(sm.qch) + } + }) +} + +// GetManifestAndLock returns manifest and lock information for the provided +// ProjectIdentifier, at the provided Version. The work of producing the +// manifest and lock is delegated to the provided ProjectAnalyzer's +// DeriveManifestAndLock() method. +func (sm *SourceMgr) GetManifestAndLock(id ProjectIdentifier, v Version, an ProjectAnalyzer) (Manifest, Lock, error) { + if atomic.LoadInt32(&sm.releasing) == 1 { + return nil, nil, ErrSourceManagerIsReleased + } + + srcg, err := sm.srcCoord.getSourceGatewayFor(context.TODO(), id) + if err != nil { + return nil, nil, err + } + + return srcg.getManifestAndLock(context.TODO(), id.ProjectRoot, v, an) +} + +// ListPackages parses the tree of the Go packages at and below the ProjectRoot +// of the given ProjectIdentifier, at the given version. +func (sm *SourceMgr) ListPackages(id ProjectIdentifier, v Version) (pkgtree.PackageTree, error) { + if atomic.LoadInt32(&sm.releasing) == 1 { + return pkgtree.PackageTree{}, ErrSourceManagerIsReleased + } + + srcg, err := sm.srcCoord.getSourceGatewayFor(context.TODO(), id) + if err != nil { + return pkgtree.PackageTree{}, err + } + + return srcg.listPackages(context.TODO(), id.ProjectRoot, v) +} + +// ListVersions retrieves a list of the available versions for a given +// repository name. +// +// The list is not sorted; while it may be returned in the order that the +// underlying VCS reports version information, no guarantee is made. It is +// expected that the caller either not care about order, or sort the result +// themselves. +// +// This list is always retrieved from upstream on the first call. Subsequent +// calls will return a cached version of the first call's results. if upstream +// is not accessible (network outage, access issues, or the resource actually +// went away), an error will be returned. +func (sm *SourceMgr) ListVersions(id ProjectIdentifier) ([]PairedVersion, error) { + if atomic.LoadInt32(&sm.releasing) == 1 { + return nil, ErrSourceManagerIsReleased + } + + srcg, err := sm.srcCoord.getSourceGatewayFor(context.TODO(), id) + if err != nil { + // TODO(sdboyer) More-er proper-er errors + return nil, err + } + + return srcg.listVersions(context.TODO()) +} + +// RevisionPresentIn indicates whether the provided Revision is present in the given +// repository. +func (sm *SourceMgr) RevisionPresentIn(id ProjectIdentifier, r Revision) (bool, error) { + if atomic.LoadInt32(&sm.releasing) == 1 { + return false, ErrSourceManagerIsReleased + } + + srcg, err := sm.srcCoord.getSourceGatewayFor(context.TODO(), id) + if err != nil { + // TODO(sdboyer) More-er proper-er errors + return false, err + } + + return srcg.revisionPresentIn(context.TODO(), r) +} + +// SourceExists checks if a repository exists, either upstream or in the cache, +// for the provided ProjectIdentifier. +func (sm *SourceMgr) SourceExists(id ProjectIdentifier) (bool, error) { + if atomic.LoadInt32(&sm.releasing) == 1 { + return false, ErrSourceManagerIsReleased + } + + srcg, err := sm.srcCoord.getSourceGatewayFor(context.TODO(), id) + if err != nil { + return false, err + } + + ctx := context.TODO() + return srcg.existsInCache(ctx) || srcg.existsUpstream(ctx), nil +} + +// SyncSourceFor will ensure that all local caches and information about a +// source are up to date with any network-acccesible information. +// +// The primary use case for this is prefetching. +func (sm *SourceMgr) SyncSourceFor(id ProjectIdentifier) error { + if atomic.LoadInt32(&sm.releasing) == 1 { + return ErrSourceManagerIsReleased + } + + srcg, err := sm.srcCoord.getSourceGatewayFor(context.TODO(), id) + if err != nil { + return err + } + + return srcg.syncLocal(context.TODO()) +} + +// ExportProject writes out the tree of the provided ProjectIdentifier's +// ProjectRoot, at the provided version, to the provided directory. +func (sm *SourceMgr) ExportProject(ctx context.Context, id ProjectIdentifier, v Version, to string) error { + if atomic.LoadInt32(&sm.releasing) == 1 { + return ErrSourceManagerIsReleased + } + + srcg, err := sm.srcCoord.getSourceGatewayFor(ctx, id) + if err != nil { + return err + } + + return srcg.exportVersionTo(ctx, v, to) +} + +// DeduceProjectRoot takes an import path and deduces the corresponding +// project/source root. +// +// Note that some import paths may require network activity to correctly +// determine the root of the path, such as, but not limited to, vanity import +// paths. (A special exception is written for gopkg.in to minimize network +// activity, as its behavior is well-structured) +func (sm *SourceMgr) DeduceProjectRoot(ip string) (ProjectRoot, error) { + if atomic.LoadInt32(&sm.releasing) == 1 { + return "", ErrSourceManagerIsReleased + } + + // TODO(sdboyer) refactor deduceRootPath() so that this validation can move + // back down below a cache point, rather than executing on every call. + if !pathvld.MatchString(ip) { + return "", errors.Errorf("%q is not a valid import path", ip) + } + + pd, err := sm.deduceCoord.deduceRootPath(context.TODO(), ip) + return ProjectRoot(pd.root), err +} + +// InferConstraint tries to puzzle out what kind of version is given in a +// string. Preference is given first for branches, then semver constraints, then +// plain tags, and then revisions. +func (sm *SourceMgr) InferConstraint(s string, pi ProjectIdentifier) (Constraint, error) { + if s == "" { + return Any(), nil + } + + // Lookup the string in the repository + var version PairedVersion + versions, err := sm.ListVersions(pi) + if err != nil { + return nil, errors.Wrapf(err, "list versions for %s", pi) // means repo does not exist + } + SortPairedForUpgrade(versions) + for _, v := range versions { + if s == v.String() { + version = v + break + } + } + + // Branch + if version != nil && version.Type() == IsBranch { + return version.Unpair(), nil + } + + // Semver Constraint + c, err := NewSemverConstraintIC(s) + if c != nil && err == nil { + return c, nil + } + + // Tag + if version != nil { + return version.Unpair(), nil + } + + // Revision, possibly abbreviated + r, err := sm.disambiguateRevision(context.TODO(), pi, Revision(s)) + if err == nil { + return r, nil + } + + return nil, errors.Errorf("%s is not a valid version for the package %s(%s)", s, pi.ProjectRoot, pi.Source) +} + +// SourceURLsForPath takes an import path and deduces the set of source URLs +// that may refer to a canonical upstream source. +// In general, these URLs differ only by protocol (e.g. https vs. ssh), not path +func (sm *SourceMgr) SourceURLsForPath(ip string) ([]*url.URL, error) { + deduced, err := sm.deduceCoord.deduceRootPath(context.TODO(), ip) + if err != nil { + return nil, err + } + + return deduced.mb.possibleURLs(), nil +} + +// disambiguateRevision looks up a revision in the underlying source, spitting +// it back out in an unabbreviated, disambiguated form. +// +// For example, if pi refers to a git-based project, then rev could be an +// abbreviated git commit hash. disambiguateRevision would return the complete +// hash. +func (sm *SourceMgr) disambiguateRevision(ctx context.Context, pi ProjectIdentifier, rev Revision) (Revision, error) { + srcg, err := sm.srcCoord.getSourceGatewayFor(context.TODO(), pi) + if err != nil { + return "", err + } + return srcg.disambiguateRevision(ctx, rev) +} + +type timeCount struct { + count int + start time.Time +} + +type durCount struct { + count int + dur time.Duration +} + +type supervisor struct { + ctx context.Context + mu sync.Mutex // Guards all maps + cond sync.Cond // Wraps mu so callers can wait until all calls end + running map[callInfo]timeCount + ran map[callType]durCount +} + +func newSupervisor(ctx context.Context) *supervisor { + supv := &supervisor{ + ctx: ctx, + running: make(map[callInfo]timeCount), + ran: make(map[callType]durCount), + } + + supv.cond = sync.Cond{L: &supv.mu} + return supv +} + +// do executes the incoming closure using a conjoined context, and keeps +// counters to ensure the sourceMgr can't finish Release()ing until after all +// calls have returned. +func (sup *supervisor) do(inctx context.Context, name string, typ callType, f func(context.Context) error) error { + ci := callInfo{ + name: name, + typ: typ, + } + + octx, err := sup.start(ci) + if err != nil { + return err + } + + cctx, cancelFunc := constext.Cons(inctx, octx) + err = f(cctx) + sup.done(ci) + cancelFunc() + return err +} + +func (sup *supervisor) start(ci callInfo) (context.Context, error) { + sup.mu.Lock() + defer sup.mu.Unlock() + if err := sup.ctx.Err(); err != nil { + // We've already been canceled; error out. + return nil, err + } + + if existingInfo, has := sup.running[ci]; has { + existingInfo.count++ + sup.running[ci] = existingInfo + } else { + sup.running[ci] = timeCount{ + count: 1, + start: time.Now(), + } + } + + return sup.ctx, nil +} + +func (sup *supervisor) count() int { + sup.mu.Lock() + defer sup.mu.Unlock() + return len(sup.running) +} + +func (sup *supervisor) done(ci callInfo) { + sup.mu.Lock() + + existingInfo, has := sup.running[ci] + if !has { + panic(fmt.Sprintf("sourceMgr: tried to complete a call that had not registered via run()")) + } + + if existingInfo.count > 1 { + // If more than one is pending, don't stop the clock yet. + existingInfo.count-- + sup.running[ci] = existingInfo + } else { + // Last one for this particular key; update metrics with info. + durCnt := sup.ran[ci.typ] + durCnt.count++ + durCnt.dur += time.Since(existingInfo.start) + sup.ran[ci.typ] = durCnt + delete(sup.running, ci) + + if len(sup.running) == 0 { + // This is the only place where we signal the cond, as it's the only + // time that the number of running calls could become zero. + sup.cond.Signal() + } + } + sup.mu.Unlock() +} + +// wait until all active calls have terminated. +// +// Assumes something else has already canceled the supervisor via its context. +func (sup *supervisor) wait() { + sup.cond.L.Lock() + for len(sup.running) > 0 { + sup.cond.Wait() + } + sup.cond.L.Unlock() +} + +type callType uint + +const ( + ctHTTPMetadata callType = iota + ctListVersions + ctGetManifestAndLock + ctListPackages + ctSourcePing + ctSourceInit + ctSourceFetch + ctExportTree + ctValidateLocal +) + +func (ct callType) String() string { + switch ct { + case ctHTTPMetadata: + return "Retrieving go get metadata" + case ctListVersions: + return "Retrieving latest version list" + case ctGetManifestAndLock: + return "Reading manifest and lock data" + case ctListPackages: + return "Parsing PackageTree" + case ctSourcePing: + return "Checking for upstream existence" + case ctSourceInit: + return "Initializing local source cache" + case ctSourceFetch: + return "Fetching latest data into local source cache" + case ctExportTree: + return "Writing code tree out to disk" + default: + panic("unknown calltype") + } +} + +// callInfo provides metadata about an ongoing call. +type callInfo struct { + name string + typ callType +} diff --git a/vendor/github.com/golang/dep/gps/source_manager_test.go b/vendor/github.com/golang/dep/gps/source_manager_test.go new file mode 100644 index 00000000..05667121 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/source_manager_test.go @@ -0,0 +1,114 @@ +// Copyright 2017 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 gps + +import ( + "log" + "reflect" + "testing" + + "github.com/golang/dep/internal/test" +) + +func TestSourceManager_InferConstraint(t *testing.T) { + if testing.Short() { + t.Skip("Skipping slow test in short mode") + } + + t.Parallel() + + // Used in git subtests: + v081, err := NewSemverConstraintIC("v0.8.1") + if err != nil { + t.Fatal(err) + } + v012, err := NewSemverConstraintIC("v0.12.0-12-de4dcafe0") + if err != nil { + t.Fatal(err) + } + + // Used in hg and bzr subtests: + v1, err := NewSemverConstraintIC("v1.0.0") + if err != nil { + t.Fatal(err) + } + + var ( + gitProj = ProjectIdentifier{ProjectRoot: "github.com/carolynvs/deptest"} + bzrProj = ProjectIdentifier{ProjectRoot: "launchpad.net/govcstestbzrrepo"} + hgProj = ProjectIdentifier{ProjectRoot: "bitbucket.org/golang-dep/dep-test"} + + testcases = []struct { + project ProjectIdentifier + name string + str string + want Constraint + }{ + {gitProj, "empty", "", Any()}, + {gitProj, "semver-short", "v0.8.1", v081}, + {gitProj, "long semver constraint", "v0.12.0-12-de4dcafe0", v012}, + {gitProj, "branch v2", "v2", NewBranch("v2")}, + {gitProj, "branch master", "master", NewBranch("master")}, + {gitProj, "long revision", "3f4c3bea144e112a69bbe5d8d01c1b09a544253f", + Revision("3f4c3bea144e112a69bbe5d8d01c1b09a544253f")}, + {gitProj, "short revision", "3f4c3bea", + Revision("3f4c3bea144e112a69bbe5d8d01c1b09a544253f")}, + + {bzrProj, "empty", "", Any()}, + {bzrProj, "semver", "v1.0.0", v1}, + {bzrProj, "revision", "matt@mattfarina.com-20150731135137-pbphasfppmygpl68", + Revision("matt@mattfarina.com-20150731135137-pbphasfppmygpl68")}, + + {hgProj, "empty", "", Any()}, + {hgProj, "semver", "v1.0.0", v1}, + {hgProj, "default branch", "default", NewBranch("default")}, + {hgProj, "revision", "6f55e1f03d91f8a7cce35d1968eb60a2352e4d59", + Revision("6f55e1f03d91f8a7cce35d1968eb60a2352e4d59")}, + {hgProj, "short revision", "6f55e1f03d91", + Revision("6f55e1f03d91f8a7cce35d1968eb60a2352e4d59")}, + } + ) + + for _, tc := range testcases { + var subtestName string + switch tc.project { + case gitProj: + subtestName = "git-" + tc.name + case bzrProj: + subtestName = "bzr-" + tc.name + case hgProj: + subtestName = "hg-" + tc.name + default: + subtestName = tc.name + } + + t.Run(subtestName, func(t *testing.T) { + t.Parallel() + h := test.NewHelper(t) + defer h.Cleanup() + + cacheDir := "gps-repocache" + h.TempDir(cacheDir) + + sm, err := NewSourceManager(SourceManagerConfig{ + Cachedir: h.Path(cacheDir), + Logger: log.New(test.Writer{TB: t}, "", 0), + }) + h.Must(err) + + got, err := sm.InferConstraint(tc.str, tc.project) + h.Must(err) + + wantT := reflect.TypeOf(tc.want) + gotT := reflect.TypeOf(got) + if wantT != gotT { + t.Errorf("expected type: %s, got %s, for input %s", wantT, gotT, tc.str) + } + if got.String() != tc.want.String() { + t.Errorf("expected value: %s, got %s for input %s", tc.want, got, tc.str) + } + }) + } +} diff --git a/vendor/github.com/golang/dep/gps/source_test.go b/vendor/github.com/golang/dep/gps/source_test.go new file mode 100644 index 00000000..f2c86726 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/source_test.go @@ -0,0 +1,180 @@ +// Copyright 2017 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 gps + +import ( + "context" + "fmt" + "io/ioutil" + "log" + "os" + "path/filepath" + "reflect" + "testing" + + "github.com/golang/dep/gps/pkgtree" + "github.com/golang/dep/internal/test" +) + +// Executed in parallel by TestSlowVcs +func testSourceGateway(t *testing.T) { + t.Parallel() + + if testing.Short() { + t.Skip("Skipping gateway testing in short mode") + } + requiresBins(t, "git") + + cachedir, err := ioutil.TempDir("", "smcache") + if err != nil { + t.Fatalf("failed to create temp dir: %s", err) + } + bgc := context.Background() + ctx, cancelFunc := context.WithCancel(bgc) + defer func() { + os.RemoveAll(cachedir) + cancelFunc() + }() + os.Mkdir(filepath.Join(cachedir, "sources"), 0777) + + do := func(wantstate sourceState) func(t *testing.T) { + return func(t *testing.T) { + superv := newSupervisor(ctx) + sc := newSourceCoordinator(superv, newDeductionCoordinator(superv), cachedir, log.New(test.Writer{TB: t}, "", 0)) + + id := mkPI("github.com/sdboyer/deptest") + sg, err := sc.getSourceGatewayFor(ctx, id) + if err != nil { + t.Fatal(err) + } + + if _, ok := sg.src.(*gitSource); !ok { + t.Fatalf("Expected a gitSource, got a %T", sg.src) + } + + if sg.srcState != wantstate { + t.Fatalf("expected state on initial create to be %v, got %v", wantstate, sg.srcState) + } + + if err := sg.syncLocal(ctx); err != nil { + t.Fatalf("error on cloning git repo: %s", err) + } + + cvlist, ok := sg.cache.getAllVersions() + if !ok || len(cvlist) != 4 { + t.Fatalf("repo setup should've cached four versions, got %v: %s", len(cvlist), cvlist) + } + + wanturl := "https://" + id.normalizedSource() + goturl, err := sg.sourceURL(ctx) + if err != nil { + t.Fatalf("got err from sourceURL: %s", err) + } + if wanturl != goturl { + t.Fatalf("Expected %s as source URL, got %s", wanturl, goturl) + } + + vlist, err := sg.listVersions(ctx) + if err != nil { + t.Fatalf("Unexpected error getting version pairs from git repo: %s", err) + } + + if len(vlist) != 4 { + t.Fatalf("git test repo should've produced four versions, got %v: vlist was %s", len(vlist), vlist) + } else { + SortPairedForUpgrade(vlist) + evl := []PairedVersion{ + NewVersion("v1.0.0").Pair(Revision("ff2948a2ac8f538c4ecd55962e919d1e13e74baf")), + NewVersion("v0.8.1").Pair(Revision("3f4c3bea144e112a69bbe5d8d01c1b09a544253f")), + NewVersion("v0.8.0").Pair(Revision("ff2948a2ac8f538c4ecd55962e919d1e13e74baf")), + newDefaultBranch("master").Pair(Revision("3f4c3bea144e112a69bbe5d8d01c1b09a544253f")), + } + if !reflect.DeepEqual(vlist, evl) { + t.Fatalf("Version list was not what we expected:\n\t(GOT): %s\n\t(WNT): %s", vlist, evl) + } + } + + rev := Revision("c575196502940c07bf89fd6d95e83b999162e051") + // check that an expected rev is not in cache + _, has := sg.cache.getVersionsFor(rev) + if has { + t.Fatal("shouldn't have bare revs in cache without specifically requesting them") + } + + is, err := sg.revisionPresentIn(ctx, Revision("c575196502940c07bf89fd6d95e83b999162e051")) + if err != nil { + t.Fatalf("unexpected error while checking revision presence: %s", err) + } else if !is { + t.Fatalf("revision that should exist was not present") + } + + // check that an expected rev is not in cache + _, has = sg.cache.getVersionsFor(rev) + if !has { + t.Fatal("bare rev should be in cache after specific request for it") + } + + // Ensure that a bad rev doesn't work on any method that takes + // versions + badver := NewVersion("notexist") + wanterr := fmt.Errorf("version %q does not exist in source", badver) + + _, _, err = sg.getManifestAndLock(ctx, ProjectRoot("github.com/sdboyer/deptest"), badver, naiveAnalyzer{}) + if err == nil { + t.Fatal("wanted err on nonexistent version") + } else if err.Error() != wanterr.Error() { + t.Fatalf("wanted nonexistent err when passing bad version, got: %s", err) + } + + _, err = sg.listPackages(ctx, ProjectRoot("github.com/sdboyer/deptest"), badver) + if err == nil { + t.Fatal("wanted err on nonexistent version") + } else if err.Error() != wanterr.Error() { + t.Fatalf("wanted nonexistent err when passing bad version, got: %s", err) + } + + err = sg.exportVersionTo(ctx, badver, cachedir) + if err == nil { + t.Fatal("wanted err on nonexistent version") + } else if err.Error() != wanterr.Error() { + t.Fatalf("wanted nonexistent err when passing bad version, got: %s", err) + } + + wantptree := pkgtree.PackageTree{ + ImportRoot: "github.com/sdboyer/deptest", + Packages: map[string]pkgtree.PackageOrErr{ + "github.com/sdboyer/deptest": { + P: pkgtree.Package{ + ImportPath: "github.com/sdboyer/deptest", + Name: "deptest", + Imports: []string{}, + }, + }, + }, + } + + ptree, err := sg.listPackages(ctx, ProjectRoot("github.com/sdboyer/deptest"), Revision("ff2948a2ac8f538c4ecd55962e919d1e13e74baf")) + if err != nil { + t.Fatalf("unexpected err when getting package tree with known rev: %s", err) + } + if !reflect.DeepEqual(wantptree, ptree) { + t.Fatalf("got incorrect PackageTree:\n\t(GOT): %#v\n\t(WNT): %#v", ptree, wantptree) + } + + ptree, err = sg.listPackages(ctx, ProjectRoot("github.com/sdboyer/deptest"), NewVersion("v1.0.0")) + if err != nil { + t.Fatalf("unexpected err when getting package tree with unpaired good version: %s", err) + } + if !reflect.DeepEqual(wantptree, ptree) { + t.Fatalf("got incorrect PackageTree:\n\t(GOT): %#v\n\t(WNT): %#v", ptree, wantptree) + } + } + } + + // Run test twice so that we cover both the existing and non-existing case; + // only difference in results is the initial setup state. + t.Run("empty", do(sourceIsSetUp|sourceExistsUpstream|sourceHasLatestVersionList)) + t.Run("exists", do(sourceIsSetUp|sourceExistsLocally|sourceExistsUpstream|sourceHasLatestVersionList)) +} diff --git a/vendor/github.com/golang/dep/gps/strings.go b/vendor/github.com/golang/dep/gps/strings.go new file mode 100644 index 00000000..6ca7b3d9 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/strings.go @@ -0,0 +1,51 @@ +// Copyright 2017 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 gps + +import ( + "bytes" + "unicode" + "unicode/utf8" +) + +// toFold returns a string with the property that strings.EqualFold(s, t) iff +// ToFold(s) == ToFold(t) This lets us test a large set of strings for +// fold-equivalent duplicates without making a quadratic number of calls to +// EqualFold. Note that strings.ToUpper and strings.ToLower do not have the +// desired property in some corner cases. +// +// This is hoisted from toolchain internals: src/cmd/go/internal/str/str.go +func toFold(s string) string { + // Fast path: all ASCII, no upper case. + // Most paths look like this already. + for i := 0; i < len(s); i++ { + c := s[i] + if c >= utf8.RuneSelf || 'A' <= c && c <= 'Z' { + goto Slow + } + } + return s + +Slow: + var buf bytes.Buffer + for _, r := range s { + // SimpleFold(x) cycles to the next equivalent rune > x + // or wraps around to smaller values. Iterate until it wraps, + // and we've found the minimum value. + for { + r0 := r + r = unicode.SimpleFold(r0) + if r <= r0 { + break + } + } + // Exception to allow fast path above: A-Z => a-z + if 'A' <= r && r <= 'Z' { + r += 'a' - 'A' + } + buf.WriteRune(r) + } + return buf.String() +} diff --git a/vendor/github.com/golang/dep/gps/trace.go b/vendor/github.com/golang/dep/gps/trace.go new file mode 100644 index 00000000..4c579d30 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/trace.go @@ -0,0 +1,205 @@ +// Copyright 2017 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 gps + +import ( + "fmt" + "strconv" + "strings" + + "github.com/golang/dep/gps/pkgtree" +) + +const ( + successChar = "✓" + successCharSp = successChar + " " + failChar = "✗" + failCharSp = failChar + " " + backChar = "←" + innerIndent = " " +) + +func (s *solver) traceCheckPkgs(bmi bimodalIdentifier) { + if s.tl == nil { + return + } + + prefix := getprei(len(s.vqs) + 1) + s.tl.Printf("%s\n", tracePrefix(fmt.Sprintf("? revisit %s to add %v pkgs", bmi.id, len(bmi.pl)), prefix, prefix)) +} + +func (s *solver) traceCheckQueue(q *versionQueue, bmi bimodalIdentifier, cont bool, offset int) { + if s.tl == nil { + return + } + + prefix := getprei(len(s.vqs) + offset) + vlen := strconv.Itoa(len(q.pi)) + if !q.allLoaded { + vlen = "at least " + vlen + } + + // TODO(sdboyer) how...to list the packages in the limited space we have? + var verb string + indent := "" + if cont { + // Continue is an "inner" message.. indenting + verb = "continue" + vlen = vlen + " more" + indent = innerIndent + } else { + verb = "attempt" + } + + s.tl.Printf("%s\n", tracePrefix(fmt.Sprintf("%s? %s %s with %v pkgs; %s versions to try", indent, verb, bmi.id, len(bmi.pl), vlen), prefix, prefix)) +} + +// traceStartBacktrack is called with the bmi that first failed, thus initiating +// backtracking +func (s *solver) traceStartBacktrack(bmi bimodalIdentifier, err error, pkgonly bool) { + if s.tl == nil { + return + } + + var msg string + if pkgonly { + msg = fmt.Sprintf("%s%s could not add %v pkgs to %s; begin backtrack", innerIndent, backChar, len(bmi.pl), bmi.id) + } else { + msg = fmt.Sprintf("%s%s no more versions of %s to try; begin backtrack", innerIndent, backChar, bmi.id) + } + + prefix := getprei(len(s.sel.projects)) + s.tl.Printf("%s\n", tracePrefix(msg, prefix, prefix)) +} + +// traceBacktrack is called when a package or project is poppped off during +// backtracking +func (s *solver) traceBacktrack(bmi bimodalIdentifier, pkgonly bool) { + if s.tl == nil { + return + } + + var msg string + if pkgonly { + msg = fmt.Sprintf("%s backtrack: popped %v pkgs from %s", backChar, len(bmi.pl), bmi.id) + } else { + msg = fmt.Sprintf("%s backtrack: no more versions of %s to try", backChar, bmi.id) + } + + prefix := getprei(len(s.sel.projects)) + s.tl.Printf("%s\n", tracePrefix(msg, prefix, prefix)) +} + +// Called just once after solving has finished, whether success or not +func (s *solver) traceFinish(sol solution, err error) { + if s.tl == nil { + return + } + + if err == nil { + var pkgcount int + for _, lp := range sol.Projects() { + pkgcount += len(lp.pkgs) + } + s.tl.Printf("%s%s found solution with %v packages from %v projects", innerIndent, successChar, pkgcount, len(sol.Projects())) + } else { + s.tl.Printf("%s%s solving failed", innerIndent, failChar) + } +} + +// traceSelectRoot is called just once, when the root project is selected +func (s *solver) traceSelectRoot(ptree pkgtree.PackageTree, cdeps []completeDep) { + if s.tl == nil { + return + } + + // This duplicates work a bit, but we're in trace mode and it's only once, + // so who cares + rm, _ := ptree.ToReachMap(true, true, false, s.rd.ir) + + s.tl.Printf("Root project is %q", s.rd.rpt.ImportRoot) + + var expkgs int + for _, cdep := range cdeps { + expkgs += len(cdep.pl) + } + + // TODO(sdboyer) include info on ignored pkgs/imports, etc. + s.tl.Printf(" %v transitively valid internal packages", len(rm)) + s.tl.Printf(" %v external packages imported from %v projects", expkgs, len(cdeps)) + s.tl.Printf("(0) " + successCharSp + "select (root)") +} + +// traceSelect is called when an atom is successfully selected +func (s *solver) traceSelect(awp atomWithPackages, pkgonly bool) { + if s.tl == nil { + return + } + + var msg string + if pkgonly { + msg = fmt.Sprintf("%s%s include %v more pkgs from %s", innerIndent, successChar, len(awp.pl), a2vs(awp.a)) + } else { + msg = fmt.Sprintf("%s select %s w/%v pkgs", successChar, a2vs(awp.a), len(awp.pl)) + } + + prefix := getprei(len(s.sel.projects) - 1) + s.tl.Printf("%s\n", tracePrefix(msg, prefix, prefix)) +} + +func (s *solver) traceInfo(args ...interface{}) { + if s.tl == nil { + return + } + + if len(args) == 0 { + panic("must pass at least one param to traceInfo") + } + + preflen := len(s.sel.projects) + var msg string + switch data := args[0].(type) { + case string: + msg = tracePrefix(innerIndent+fmt.Sprintf(data, args[1:]...), " ", " ") + case traceError: + preflen++ + // We got a special traceError, use its custom method + msg = tracePrefix(innerIndent+data.traceString(), " ", failCharSp) + case error: + // Regular error; still use the x leader but default Error() string + msg = tracePrefix(innerIndent+data.Error(), " ", failCharSp) + default: + // panic here because this can *only* mean a stupid internal bug + panic(fmt.Sprintf("canary - unknown type passed as first param to traceInfo %T", data)) + } + + prefix := getprei(preflen) + s.tl.Printf("%s\n", tracePrefix(msg, prefix, prefix)) +} + +func getprei(i int) string { + var s string + if i < 10 { + s = fmt.Sprintf("(%d) ", i) + } else if i < 100 { + s = fmt.Sprintf("(%d) ", i) + } else { + s = fmt.Sprintf("(%d) ", i) + } + return s +} + +func tracePrefix(msg, sep, fsep string) string { + parts := strings.Split(strings.TrimSuffix(msg, "\n"), "\n") + for k, str := range parts { + if k == 0 { + parts[k] = fsep + str + } else { + parts[k] = sep + str + } + } + + return strings.Join(parts, "\n") +} diff --git a/vendor/github.com/golang/dep/gps/typed_radix.go b/vendor/github.com/golang/dep/gps/typed_radix.go new file mode 100644 index 00000000..615f297e --- /dev/null +++ b/vendor/github.com/golang/dep/gps/typed_radix.go @@ -0,0 +1,92 @@ +// Copyright 2017 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 gps + +import ( + "strings" + "sync" + + "github.com/armon/go-radix" +) + +// Typed implementations of radix trees. These are just simple wrappers that let +// us avoid having to type assert anywhere else, cleaning up other code a bit. +// +// Some of the more annoying things to implement (like walks) aren't +// implemented. They can be added if/when we actually need them. +// +// Oh generics, where art thou... + +type deducerTrie struct { + sync.RWMutex + t *radix.Tree +} + +func newDeducerTrie() *deducerTrie { + return &deducerTrie{ + t: radix.New(), + } +} + +// Suppress unused warning. +var _ = (*deducerTrie)(nil).Delete + +// Delete is used to delete a key, returning the previous value and if it was deleted +func (t *deducerTrie) Delete(s string) (pathDeducer, bool) { + t.Lock() + defer t.Unlock() + if d, had := t.t.Delete(s); had { + return d.(pathDeducer), had + } + return nil, false +} + +// Insert is used to add a newentry or update an existing entry. Returns if updated. +func (t *deducerTrie) Insert(s string, d pathDeducer) (pathDeducer, bool) { + t.Lock() + defer t.Unlock() + if d2, had := t.t.Insert(s, d); had { + return d2.(pathDeducer), had + } + return nil, false +} + +// LongestPrefix is like Get, but instead of an exact match, it will return the +// longest prefix match. +func (t *deducerTrie) LongestPrefix(s string) (string, pathDeducer, bool) { + t.RLock() + defer t.RUnlock() + if p, d, has := t.t.LongestPrefix(s); has { + return p, d.(pathDeducer), has + } + return "", nil, false +} + +// isPathPrefixOrEqual is an additional helper check to ensure that the literal +// string prefix returned from a radix tree prefix match is also a path tree +// match. +// +// The radix tree gets it mostly right, but we have to guard against +// possibilities like this: +// +// github.com/sdboyer/foo +// github.com/sdboyer/foobar/baz +// +// The latter would incorrectly be conflated with the former. As we know we're +// operating on strings that describe import paths, guard against this case by +// verifying that either the input is the same length as the match (in which +// case we know they're equal), or that the next character is a "/". (Import +// paths are defined to always use "/", not the OS-specific path separator.) +func isPathPrefixOrEqual(pre, path string) bool { + prflen, pathlen := len(pre), len(path) + if pathlen == prflen+1 { + // this can never be the case + return false + } + + // we assume something else (a trie) has done equality check up to the point + // of the prefix, so we just check len + return prflen == pathlen || strings.Index(path[prflen:], "/") == 0 +} diff --git a/vendor/github.com/golang/dep/gps/typed_radix_test.go b/vendor/github.com/golang/dep/gps/typed_radix_test.go new file mode 100644 index 00000000..38f60648 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/typed_radix_test.go @@ -0,0 +1,26 @@ +// Copyright 2017 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 gps + +import "testing" + +// basically a regression test +func TestPathPrefixOrEqual(t *testing.T) { + if !isPathPrefixOrEqual("foo", "foo") { + t.Error("Same path should return true") + } + + if isPathPrefixOrEqual("foo", "fooer") { + t.Error("foo is not a path-type prefix of fooer") + } + + if !isPathPrefixOrEqual("foo", "foo/bar") { + t.Error("foo is a path prefix of foo/bar") + } + + if isPathPrefixOrEqual("foo", "foo/") { + t.Error("special case - foo is not a path prefix of foo/") + } +} diff --git a/vendor/github.com/golang/dep/gps/vcs_repo.go b/vendor/github.com/golang/dep/gps/vcs_repo.go new file mode 100644 index 00000000..cb500a5a --- /dev/null +++ b/vendor/github.com/golang/dep/gps/vcs_repo.go @@ -0,0 +1,387 @@ +// Copyright 2017 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 gps + +import ( + "context" + "encoding/xml" + "fmt" + "os" + "path/filepath" + "runtime" + "strings" + "time" + + "github.com/Masterminds/vcs" + "github.com/pkg/errors" +) + +type ctxRepo interface { + vcs.Repo + get(context.Context) error + fetch(context.Context) error + updateVersion(context.Context, string) error + //ping(context.Context) (bool, error) +} + +func newCtxRepo(s vcs.Type, ustr, path string) (ctxRepo, error) { + r, err := getVCSRepo(s, ustr, path) + if err != nil { + // if vcs could not initialize the repo due to a local error + // then the local repo is in an incorrect state. Remove and + // treat it as a new not-yet-cloned repo. + + // TODO(marwan-at-work): warn/give progress of the above comment. + os.RemoveAll(path) + r, err = getVCSRepo(s, ustr, path) + } + + return r, err +} + +func getVCSRepo(s vcs.Type, ustr, path string) (ctxRepo, error) { + switch s { + case vcs.Git: + repo, err := vcs.NewGitRepo(ustr, path) + return &gitRepo{repo}, err + case vcs.Bzr: + repo, err := vcs.NewBzrRepo(ustr, path) + return &bzrRepo{repo}, err + case vcs.Hg: + repo, err := vcs.NewHgRepo(ustr, path) + return &hgRepo{repo}, err + case vcs.Svn: + repo, err := vcs.NewSvnRepo(ustr, path) + return &svnRepo{repo}, err + default: + panic(fmt.Sprintf("Unrecognized format: %v", s)) + } +} + +// original implementation of these methods come from +// https://github.com/Masterminds/vcs + +type gitRepo struct { + *vcs.GitRepo +} + +func newVcsRemoteErrorOr(err error, args []string, out, msg string) error { + if err == context.Canceled || err == context.DeadlineExceeded { + return err + } + return vcs.NewRemoteError(msg, errors.Wrapf(err, "command failed: %v", args), out) +} + +func newVcsLocalErrorOr(err error, args []string, out, msg string) error { + if err == context.Canceled || err == context.DeadlineExceeded { + return err + } + return vcs.NewLocalError(msg, errors.Wrapf(err, "command failed: %v", args), out) +} + +func (r *gitRepo) get(ctx context.Context) error { + cmd := commandContext( + ctx, + "git", + "clone", + "--recursive", + "-v", + "--progress", + r.Remote(), + r.LocalPath(), + ) + // Ensure no prompting for PWs + cmd.SetEnv(append([]string{"GIT_ASKPASS=", "GIT_TERMINAL_PROMPT=0"}, os.Environ()...)) + if out, err := cmd.CombinedOutput(); err != nil { + return newVcsRemoteErrorOr(err, cmd.Args(), string(out), + "unable to get repository") + } + + return nil +} + +func (r *gitRepo) fetch(ctx context.Context) error { + cmd := commandContext( + ctx, + "git", + "fetch", + "--tags", + "--prune", + r.RemoteLocation, + ) + cmd.SetDir(r.LocalPath()) + // Ensure no prompting for PWs + cmd.SetEnv(append([]string{"GIT_ASKPASS=", "GIT_TERMINAL_PROMPT=0"}, os.Environ()...)) + if out, err := cmd.CombinedOutput(); err != nil { + return newVcsRemoteErrorOr(err, cmd.Args(), string(out), + "unable to update repository") + } + return nil +} + +func (r *gitRepo) updateVersion(ctx context.Context, v string) error { + cmd := commandContext(ctx, "git", "checkout", v) + cmd.SetDir(r.LocalPath()) + if out, err := cmd.CombinedOutput(); err != nil { + return newVcsLocalErrorOr(err, cmd.Args(), string(out), + "unable to update checked out version") + } + + return r.defendAgainstSubmodules(ctx) +} + +// defendAgainstSubmodules tries to keep repo state sane in the event of +// submodules. Or nested submodules. What a great idea, submodules. +func (r *gitRepo) defendAgainstSubmodules(ctx context.Context) error { + // First, update them to whatever they should be, if there should happen to be any. + { + cmd := commandContext( + ctx, + "git", + "submodule", + "update", + "--init", + "--recursive", + ) + cmd.SetDir(r.LocalPath()) + // Ensure no prompting for PWs + cmd.SetEnv(append([]string{"GIT_ASKPASS=", "GIT_TERMINAL_PROMPT=0"}, os.Environ()...)) + if out, err := cmd.CombinedOutput(); err != nil { + return newVcsLocalErrorOr(err, cmd.Args(), string(out), + "unexpected error while defensively updating submodules") + } + } + + // Now, do a special extra-aggressive clean in case changing versions caused + // one or more submodules to go away. + { + cmd := commandContext(ctx, "git", "clean", "-x", "-d", "-f", "-f") + cmd.SetDir(r.LocalPath()) + if out, err := cmd.CombinedOutput(); err != nil { + return newVcsLocalErrorOr(err, cmd.Args(), string(out), + "unexpected error while defensively cleaning up after possible derelict submodule directories") + } + } + + // Then, repeat just in case there are any nested submodules that went away. + { + cmd := commandContext( + ctx, + "git", + "submodule", + "foreach", + "--recursive", + "git", + "clean", "-x", "-d", "-f", "-f", + ) + cmd.SetDir(r.LocalPath()) + if out, err := cmd.CombinedOutput(); err != nil { + return newVcsLocalErrorOr(err, cmd.Args(), string(out), + "unexpected error while defensively cleaning up after possible derelict nested submodule directories") + } + } + + return nil +} + +type bzrRepo struct { + *vcs.BzrRepo +} + +func (r *bzrRepo) get(ctx context.Context) error { + basePath := filepath.Dir(filepath.FromSlash(r.LocalPath())) + if _, err := os.Stat(basePath); os.IsNotExist(err) { + err = os.MkdirAll(basePath, 0755) + if err != nil { + return newVcsLocalErrorOr(err, nil, "", "unable to create directory") + } + } + + cmd := commandContext(ctx, "bzr", "branch", r.Remote(), r.LocalPath()) + if out, err := cmd.CombinedOutput(); err != nil { + return newVcsRemoteErrorOr(err, cmd.Args(), string(out), + "unable to get repository") + } + + return nil +} + +func (r *bzrRepo) fetch(ctx context.Context) error { + cmd := commandContext(ctx, "bzr", "pull") + cmd.SetDir(r.LocalPath()) + if out, err := cmd.CombinedOutput(); err != nil { + return newVcsRemoteErrorOr(err, cmd.Args(), string(out), + "unable to update repository") + } + return nil +} + +func (r *bzrRepo) updateVersion(ctx context.Context, version string) error { + cmd := commandContext(ctx, "bzr", "update", "-r", version) + cmd.SetDir(r.LocalPath()) + if out, err := cmd.CombinedOutput(); err != nil { + return newVcsLocalErrorOr(err, cmd.Args(), string(out), + "unable to update checked out version") + } + return nil +} + +type hgRepo struct { + *vcs.HgRepo +} + +func (r *hgRepo) get(ctx context.Context) error { + cmd := commandContext(ctx, "hg", "clone", r.Remote(), r.LocalPath()) + if out, err := cmd.CombinedOutput(); err != nil { + return newVcsRemoteErrorOr(err, cmd.Args(), string(out), + "unable to get repository") + } + + return nil +} + +func (r *hgRepo) fetch(ctx context.Context) error { + cmd := commandContext(ctx, "hg", "pull") + cmd.SetDir(r.LocalPath()) + if out, err := cmd.CombinedOutput(); err != nil { + return newVcsRemoteErrorOr(err, cmd.Args(), string(out), + "unable to fetch latest changes") + } + return nil +} + +func (r *hgRepo) updateVersion(ctx context.Context, version string) error { + cmd := commandContext(ctx, "hg", "update", version) + cmd.SetDir(r.LocalPath()) + if out, err := cmd.CombinedOutput(); err != nil { + return newVcsRemoteErrorOr(err, cmd.Args(), string(out), + "unable to update checked out version") + } + + return nil +} + +type svnRepo struct { + *vcs.SvnRepo +} + +func (r *svnRepo) get(ctx context.Context) error { + remote := r.Remote() + if strings.HasPrefix(remote, "/") { + remote = "file://" + remote + } else if runtime.GOOS == "windows" && filepath.VolumeName(remote) != "" { + remote = "file:///" + remote + } + + cmd := commandContext(ctx, "svn", "checkout", remote, r.LocalPath()) + if out, err := cmd.CombinedOutput(); err != nil { + return newVcsRemoteErrorOr(err, cmd.Args(), string(out), + "unable to get repository") + } + + return nil +} + +func (r *svnRepo) fetch(ctx context.Context) error { + cmd := commandContext(ctx, "svn", "update") + cmd.SetDir(r.LocalPath()) + if out, err := cmd.CombinedOutput(); err != nil { + return newVcsRemoteErrorOr(err, cmd.Args(), string(out), + "unable to update repository") + } + + return nil +} + +func (r *svnRepo) updateVersion(ctx context.Context, version string) error { + cmd := commandContext(ctx, "svn", "update", "-r", version) + cmd.SetDir(r.LocalPath()) + if out, err := cmd.CombinedOutput(); err != nil { + return newVcsRemoteErrorOr(err, cmd.Args(), string(out), + "unable to update checked out version") + } + + return nil +} + +func (r *svnRepo) CommitInfo(id string) (*vcs.CommitInfo, error) { + ctx := context.TODO() + // There are cases where Svn log doesn't return anything for HEAD or BASE. + // svn info does provide details for these but does not have elements like + // the commit message. + if id == "HEAD" || id == "BASE" { + type commit struct { + Revision string `xml:"revision,attr"` + } + + type info struct { + Commit commit `xml:"entry>commit"` + } + + cmd := commandContext(ctx, "svn", "info", "-r", id, "--xml") + cmd.SetDir(r.LocalPath()) + out, err := cmd.CombinedOutput() + if err != nil { + return nil, newVcsLocalErrorOr(err, cmd.Args(), string(out), + "unable to retrieve commit information") + } + + infos := new(info) + if err := xml.Unmarshal(out, &infos); err != nil { + return nil, newVcsLocalErrorOr(err, cmd.Args(), string(out), + "unable to retrieve commit information") + } + + id = infos.Commit.Revision + if id == "" { + return nil, vcs.ErrRevisionUnavailable + } + } + + cmd := commandContext(ctx, "svn", "log", "-r", id, "--xml") + cmd.SetDir(r.LocalPath()) + out, err := cmd.CombinedOutput() + if err != nil { + return nil, newVcsRemoteErrorOr(err, cmd.Args(), string(out), + "unable to retrieve commit information") + } + + type logentry struct { + Author string `xml:"author"` + Date string `xml:"date"` + Msg string `xml:"msg"` + } + + type log struct { + XMLName xml.Name `xml:"log"` + Logs []logentry `xml:"logentry"` + } + + logs := new(log) + if err := xml.Unmarshal(out, &logs); err != nil { + return nil, newVcsLocalErrorOr(err, cmd.Args(), string(out), + "unable to retrieve commit information") + } + + if len(logs.Logs) == 0 { + return nil, vcs.ErrRevisionUnavailable + } + + ci := &vcs.CommitInfo{ + Commit: id, + Author: logs.Logs[0].Author, + Message: logs.Logs[0].Msg, + } + + if len(logs.Logs[0].Date) > 0 { + ci.Date, err = time.Parse(time.RFC3339Nano, logs.Logs[0].Date) + if err != nil { + return nil, newVcsLocalErrorOr(err, cmd.Args(), string(out), + "unable to retrieve commit information") + } + } + + return ci, nil +} diff --git a/vendor/github.com/golang/dep/gps/vcs_repo_test.go b/vendor/github.com/golang/dep/gps/vcs_repo_test.go new file mode 100644 index 00000000..2f281f20 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/vcs_repo_test.go @@ -0,0 +1,462 @@ +// Copyright 2017 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 gps + +import ( + "archive/tar" + "compress/gzip" + "context" + "errors" + "io" + "io/ioutil" + "os" + "path/filepath" + "testing" + "time" + + "github.com/Masterminds/vcs" +) + +// original implementation of these test files come from +// https://github.com/Masterminds/vcs test files + +const gitRemoteTestRepo = "https://github.com/Masterminds/VCSTestRepo" + +func TestErrs(t *testing.T) { + err := newVcsLocalErrorOr(context.Canceled, nil, "", "") + if err != context.Canceled { + t.Errorf("context errors should always pass through, got %s", err) + } + err = newVcsRemoteErrorOr(context.Canceled, nil, "", "") + if err != context.Canceled { + t.Errorf("context errors should always pass through, got %s", err) + } + err = newVcsLocalErrorOr(context.DeadlineExceeded, nil, "", "") + if err != context.DeadlineExceeded { + t.Errorf("context errors should always pass through, got %s", err) + } + err = newVcsRemoteErrorOr(context.DeadlineExceeded, nil, "", "") + if err != context.DeadlineExceeded { + t.Errorf("context errors should always pass through, got %s", err) + } + + err = newVcsLocalErrorOr(errors.New("bar"), nil, "foo", "baz") + if _, is := err.(*vcs.LocalError); !is { + t.Errorf("should have gotten local error, got %T %v", err, err) + } + err = newVcsRemoteErrorOr(errors.New("bar"), nil, "foo", "baz") + if _, is := err.(*vcs.RemoteError); !is { + t.Errorf("should have gotten remote error, got %T %v", err, err) + } +} + +func TestNewCtxRepoHappyPath(t *testing.T) { + t.Parallel() + + tempDir, err := ioutil.TempDir("", "go-ctx-repo-happy-test") + if err != nil { + t.Fatal(err) + } + defer func() { + err = os.RemoveAll(tempDir) + if err != nil { + t.Error(err) + } + }() + + _, err = newCtxRepo(vcs.Git, gitRemoteTestRepo, tempDir) + if err != nil { + t.Fatal(err) + } +} + +func TestNewCtxRepoRecovery(t *testing.T) { + t.Parallel() + + tempDir, err := ioutil.TempDir("", "go-ctx-repo-recovery-test") + if err != nil { + t.Fatal(err) + } + defer func() { + err = os.RemoveAll(tempDir) + if err != nil { + t.Error(err) + } + }() + + cwd, err := os.Getwd() + if err != nil { + t.Fatal(err) + } + + src := filepath.Join(cwd, "_testdata", "badrepo", "corrupt_dot_git_directory.tar") + f, err := os.Open(src) + if err != nil { + t.Fatal(err) + } + defer f.Close() + + dest := filepath.Join(tempDir, ".git") + err = untar(dest, f) + if err != nil { + t.Fatalf("could not untar corrupt repo into temp folder: %v\n", err) + } + + _, err = getVCSRepo(vcs.Git, gitRemoteTestRepo, tempDir) + if err != nil { + if _, ok := err.(*vcs.LocalError); !ok { + t.Fatalf("expected a local error but got: %v\n", err) + } + } else { + t.Fatal("expected getVCSRepo to fail when pointing to a corrupt local path. It is possible that vcs.GitNewRepo updated to gracefully handle this test scenario. Check the return of vcs.GitNewRepo.") + } + + _, err = newCtxRepo(vcs.Git, gitRemoteTestRepo, tempDir) + if err != nil { + t.Fatal(err) + } +} + +func testSvnRepo(t *testing.T) { + t.Parallel() + + if testing.Short() { + t.Skip("Skipping slow test in short mode") + } + + ctx := context.Background() + tempDir, err := ioutil.TempDir("", "go-vcs-svn-tests") + if err != nil { + t.Fatal(err) + } + defer func() { + err = os.RemoveAll(tempDir) + if err != nil { + t.Error(err) + } + }() + + rep, err := vcs.NewSvnRepo("https://github.com/Masterminds/VCSTestRepo/trunk", tempDir+string(os.PathSeparator)+"VCSTestRepo") + if err != nil { + t.Fatal(err) + } + repo := &svnRepo{rep} + + // Do an initial checkout. + err = repo.get(ctx) + if err != nil { + t.Fatalf("Unable to checkout SVN repo. Err was %s", err) + } + + // Verify SVN repo is a SVN repo + if !repo.CheckLocal() { + t.Fatal("Problem checking out repo or SVN CheckLocal is not working") + } + + // Update the version to a previous version. + err = repo.updateVersion(ctx, "r2") + if err != nil { + t.Fatalf("Unable to update SVN repo version. Err was %s", err) + } + + // Use Version to verify we are on the right version. + v, err := repo.Version() + if err != nil { + t.Fatal(err) + } + if v != "2" { + t.Fatal("Error checking checked SVN out version") + } + + // Perform an update which should take up back to the latest version. + err = repo.fetch(ctx) + if err != nil { + t.Fatal(err) + } + + // Make sure we are on a newer version because of the update. + v, err = repo.Version() + if err != nil { + t.Fatal(err) + } + if v == "2" { + t.Fatal("Error with version. Still on old version. Update failed") + } + + ci, err := repo.CommitInfo("2") + if err != nil { + t.Fatal(err) + } + if ci.Commit != "2" { + t.Error("Svn.CommitInfo wrong commit id") + } + if ci.Author != "matt.farina" { + t.Error("Svn.CommitInfo wrong author") + } + if ci.Message != "Update README.md" { + t.Error("Svn.CommitInfo wrong message") + } + ti, err := time.Parse(time.RFC3339Nano, "2015-07-29T13:46:20.000000Z") + if err != nil { + t.Fatal(err) + } + if !ti.Equal(ci.Date) { + t.Error("Svn.CommitInfo wrong date") + } + + _, err = repo.CommitInfo("555555555") + if err != vcs.ErrRevisionUnavailable { + t.Error("Svn didn't return expected ErrRevisionUnavailable") + } +} + +func testHgRepo(t *testing.T) { + t.Parallel() + + if testing.Short() { + t.Skip("Skipping slow test in short mode") + } + + ctx := context.Background() + tempDir, err := ioutil.TempDir("", "go-vcs-hg-tests") + if err != nil { + t.Fatal(err) + } + + defer func() { + err = os.RemoveAll(tempDir) + if err != nil { + t.Error(err) + } + }() + + rep, err := vcs.NewHgRepo("https://bitbucket.org/mattfarina/testhgrepo", tempDir+"/testhgrepo") + if err != nil { + t.Fatal(err) + } + + repo := &hgRepo{rep} + + // Do an initial clone. + err = repo.get(ctx) + if err != nil { + t.Fatalf("Unable to clone Hg repo. Err was %s", err) + } + + // Verify Hg repo is a Hg repo + if !repo.CheckLocal() { + t.Fatal("Problem checking out repo or Hg CheckLocal is not working") + } + + // Set the version using the short hash. + err = repo.updateVersion(ctx, "a5494ba2177f") + if err != nil { + t.Fatalf("Unable to update Hg repo version. Err was %s", err) + } + + // Use Version to verify we are on the right version. + v, err := repo.Version() + if err != nil { + t.Fatal(err) + } + if v != "a5494ba2177ff9ef26feb3c155dfecc350b1a8ef" { + t.Fatalf("Error checking checked out Hg version: %s", v) + } + + // Perform an update. + err = repo.fetch(ctx) + if err != nil { + t.Fatal(err) + } +} + +func testGitRepo(t *testing.T) { + t.Parallel() + + if testing.Short() { + t.Skip("Skipping slow test in short mode") + } + + ctx := context.Background() + tempDir, err := ioutil.TempDir("", "go-vcs-git-tests") + if err != nil { + t.Fatal(err) + } + + defer func() { + err = os.RemoveAll(tempDir) + if err != nil { + t.Error(err) + } + }() + + rep, err := vcs.NewGitRepo(gitRemoteTestRepo, tempDir+"/VCSTestRepo") + if err != nil { + t.Fatal(err) + } + + repo := &gitRepo{rep} + + // Do an initial clone. + err = repo.get(ctx) + if err != nil { + t.Fatalf("Unable to clone Git repo. Err was %s", err) + } + + // Verify Git repo is a Git repo + if !repo.CheckLocal() { + t.Fatal("Problem checking out repo or Git CheckLocal is not working") + } + + // Perform an update. + err = repo.fetch(ctx) + if err != nil { + t.Fatal(err) + } + + v, err := repo.Current() + if err != nil { + t.Fatalf("Error trying Git Current: %s", err) + } + if v != "master" { + t.Fatalf("Current failed to detect Git on tip of master. Got version: %s", v) + } + + // Set the version using the short hash. + err = repo.updateVersion(ctx, "806b07b") + if err != nil { + t.Fatalf("Unable to update Git repo version. Err was %s", err) + } + + // Once a ref has been checked out the repo is in a detached head state. + // Trying to pull in an update in this state will cause an error. Update + // should cleanly handle this. Pulling on a branch (tested elsewhere) and + // skipping that here. + err = repo.fetch(ctx) + if err != nil { + t.Fatal(err) + } + + // Use Version to verify we are on the right version. + v, err = repo.Version() + if err != nil { + t.Fatal(err) + } + if v != "806b07b08faa21cfbdae93027904f80174679402" { + t.Fatal("Error checking checked out Git version") + } +} + +func testBzrRepo(t *testing.T) { + t.Parallel() + + if testing.Short() { + t.Skip("Skipping slow test in short mode") + } + + ctx := context.Background() + tempDir, err := ioutil.TempDir("", "go-vcs-bzr-tests") + if err != nil { + t.Fatal(err) + } + + defer func() { + err = os.RemoveAll(tempDir) + if err != nil { + t.Error(err) + } + }() + + rep, err := vcs.NewBzrRepo("https://launchpad.net/govcstestbzrrepo", tempDir+"/govcstestbzrrepo") + if err != nil { + t.Fatal(err) + } + + repo := &bzrRepo{rep} + + // Do an initial clone. + err = repo.get(ctx) + if err != nil { + t.Fatalf("Unable to clone Bzr repo. Err was %s", err) + } + + // Verify Bzr repo is a Bzr repo + if !repo.CheckLocal() { + t.Fatal("Problem checking out repo or Bzr CheckLocal is not working") + } + + v, err := repo.Current() + if err != nil { + t.Fatalf("Error trying Bzr Current: %s", err) + } + if v != "-1" { + t.Fatalf("Current failed to detect Bzr on tip of branch. Got version: %s", v) + } + + err = repo.updateVersion(ctx, "2") + if err != nil { + t.Fatalf("Unable to update Bzr repo version. Err was %s", err) + } + + // Use Version to verify we are on the right version. + v, err = repo.Version() + if err != nil { + t.Fatal(err) + } + if v != "2" { + t.Fatal("Error checking checked out Bzr version") + } + + v, err = repo.Current() + if err != nil { + t.Fatalf("Error trying Bzr Current: %s", err) + } + if v != "2" { + t.Fatalf("Current failed to detect Bzr on rev 2 of branch. Got version: %s", v) + } +} + +func untar(dst string, r io.Reader) error { + gzr, err := gzip.NewReader(r) + if err != nil { + return err + } + defer gzr.Close() + + tr := tar.NewReader(gzr) + + for { + header, err := tr.Next() + + switch { + case err == io.EOF: + return nil + case err != nil: + return err + case header == nil: + continue + } + + target := filepath.Join(dst, header.Name) + switch header.Typeflag { + case tar.TypeDir: + if _, err := os.Stat(target); err != nil { + if err := os.MkdirAll(target, 0755); err != nil { + return err + } + } + case tar.TypeReg: + f, err := os.OpenFile(target, os.O_CREATE|os.O_RDWR, os.FileMode(header.Mode)) + if err != nil { + return err + } + defer f.Close() + + if _, err := io.Copy(f, tr); err != nil { + return err + } + } + } +} diff --git a/vendor/github.com/golang/dep/gps/vcs_source.go b/vendor/github.com/golang/dep/gps/vcs_source.go new file mode 100644 index 00000000..f6b7aef1 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/vcs_source.go @@ -0,0 +1,690 @@ +// Copyright 2017 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 gps + +import ( + "bytes" + "context" + "fmt" + "os" + "path/filepath" + "regexp" + "strings" + + "github.com/Masterminds/semver" + "github.com/golang/dep/gps/pkgtree" + "github.com/golang/dep/internal/fs" + "github.com/pkg/errors" +) + +type baseVCSSource struct { + repo ctxRepo +} + +func (bs *baseVCSSource) sourceType() string { + return string(bs.repo.Vcs()) +} + +func (bs *baseVCSSource) existsLocally(ctx context.Context) bool { + return bs.repo.CheckLocal() +} + +// TODO reimpl for git +func (bs *baseVCSSource) existsUpstream(ctx context.Context) bool { + return !bs.repo.Ping() +} + +func (bs *baseVCSSource) upstreamURL() string { + return bs.repo.Remote() +} + +func (bs *baseVCSSource) disambiguateRevision(ctx context.Context, r Revision) (Revision, error) { + ci, err := bs.repo.CommitInfo(string(r)) + if err != nil { + return "", err + } + return Revision(ci.Commit), nil +} + +func (bs *baseVCSSource) getManifestAndLock(ctx context.Context, pr ProjectRoot, r Revision, an ProjectAnalyzer) (Manifest, Lock, error) { + err := bs.repo.updateVersion(ctx, r.String()) + if err != nil { + return nil, nil, unwrapVcsErr(err) + } + + m, l, err := an.DeriveManifestAndLock(bs.repo.LocalPath(), pr) + if err != nil { + return nil, nil, err + } + + if l != nil && l != Lock(nil) { + l = prepLock(l) + } + + return prepManifest(m), l, nil +} + +func (bs *baseVCSSource) revisionPresentIn(r Revision) (bool, error) { + return bs.repo.IsReference(string(r)), nil +} + +// initLocal clones/checks out the upstream repository to disk for the first +// time. +func (bs *baseVCSSource) initLocal(ctx context.Context) error { + err := bs.repo.get(ctx) + + if err != nil { + return unwrapVcsErr(err) + } + return nil +} + +// updateLocal ensures the local data (versions and code) we have about the +// source is fully up to date with that of the canonical upstream source. +func (bs *baseVCSSource) updateLocal(ctx context.Context) error { + err := bs.repo.fetch(ctx) + + if err != nil { + return unwrapVcsErr(err) + } + return nil +} + +func (bs *baseVCSSource) listPackages(ctx context.Context, pr ProjectRoot, r Revision) (ptree pkgtree.PackageTree, err error) { + err = bs.repo.updateVersion(ctx, r.String()) + + if err != nil { + err = unwrapVcsErr(err) + } else { + ptree, err = pkgtree.ListPackages(bs.repo.LocalPath(), string(pr)) + } + + return +} + +func (bs *baseVCSSource) exportRevisionTo(ctx context.Context, r Revision, to string) error { + // Only make the parent dir, as CopyDir will balk on trying to write to an + // empty but existing dir. + if err := os.MkdirAll(filepath.Dir(to), 0777); err != nil { + return err + } + + if err := bs.repo.updateVersion(ctx, r.String()); err != nil { + return unwrapVcsErr(err) + } + + return fs.CopyDir(bs.repo.LocalPath(), to) +} + +var ( + gitHashRE = regexp.MustCompile(`^[a-f0-9]{40}$`) +) + +// gitSource is a generic git repository implementation that should work with +// all standard git remotes. +type gitSource struct { + baseVCSSource +} + +// ensureClean sees to it that a git repository is clean and in working order, +// or returns an error if the adaptive recovery attempts fail. +func (s *gitSource) ensureClean(ctx context.Context) error { + r := s.repo.(*gitRepo) + cmd := commandContext( + ctx, + "git", + "status", + "--porcelain", + ) + cmd.SetDir(r.LocalPath()) + + out, err := cmd.CombinedOutput() + if err != nil { + // An error on simple git status indicates some aggressive repository + // corruption, outside of the purview that we can deal with here. + return err + } + + if len(bytes.TrimSpace(out)) == 0 { + // No output from status indicates a clean tree, without any modified or + // untracked files - we're in good shape. + return nil + } + + // We could be more parsimonious about this, but it's probably not worth it + // - it's a rare case to have to do any cleanup anyway, so when we do, we + // might as well just throw the kitchen sink at it. + cmd = commandContext( + ctx, + "git", + "reset", + "--hard", + ) + cmd.SetDir(r.LocalPath()) + _, err = cmd.CombinedOutput() + if err != nil { + return err + } + + // We also need to git clean -df; just reuse defendAgainstSubmodules here, + // even though it's a bit layer-breaky. + err = r.defendAgainstSubmodules(ctx) + if err != nil { + return err + } + + // Check status one last time. If it's still not clean, give up. + cmd = commandContext( + ctx, + "git", + "status", + "--porcelain", + ) + cmd.SetDir(r.LocalPath()) + + out, err = cmd.CombinedOutput() + if err != nil { + return err + } + + if len(bytes.TrimSpace(out)) != 0 { + return errors.Errorf("failed to clean up git repository at %s - dirty? corrupted? status output: \n%s", r.LocalPath(), string(out)) + } + + return nil +} + +func (s *gitSource) exportRevisionTo(ctx context.Context, rev Revision, to string) error { + r := s.repo + + if err := os.MkdirAll(to, 0777); err != nil { + return err + } + + // Back up original index + idx, bak := filepath.Join(r.LocalPath(), ".git", "index"), filepath.Join(r.LocalPath(), ".git", "origindex") + err := fs.RenameWithFallback(idx, bak) + if err != nil { + return err + } + + // could have an err here...but it's hard to imagine how? + defer fs.RenameWithFallback(bak, idx) + + { + cmd := commandContext(ctx, "git", "read-tree", rev.String()) + cmd.SetDir(r.LocalPath()) + if out, err := cmd.CombinedOutput(); err != nil { + return errors.Wrap(err, string(out)) + } + } + + // Ensure we have exactly one trailing slash + to = strings.TrimSuffix(to, string(os.PathSeparator)) + string(os.PathSeparator) + // Checkout from our temporary index to the desired target location on + // disk; now it's git's job to make it fast. + // + // Sadly, this approach *does* also write out vendor dirs. There doesn't + // appear to be a way to make checkout-index respect sparse checkout + // rules (-a supersedes it). The alternative is using plain checkout, + // though we have a bunch of housekeeping to do to set up, then tear + // down, the sparse checkout controls, as well as restore the original + // index and HEAD. + { + cmd := commandContext(ctx, "git", "checkout-index", "-a", "--prefix="+to) + cmd.SetDir(r.LocalPath()) + if out, err := cmd.CombinedOutput(); err != nil { + return errors.Wrap(err, string(out)) + } + } + + return nil +} + +func (s *gitSource) isValidHash(hash []byte) bool { + return gitHashRE.Match(hash) +} + +func (s *gitSource) listVersions(ctx context.Context) (vlist []PairedVersion, err error) { + r := s.repo + + cmd := commandContext(ctx, "git", "ls-remote", r.Remote()) + // We want to invoke from a place where it's not possible for there to be a + // .git file instead of a .git directory, as git ls-remote will choke on the + // former and erroneously quit. However, we can't be sure that the repo + // exists on disk yet at this point; if it doesn't, then instead use the + // parent of the local path, as that's still likely a good bet. + if r.CheckLocal() { + cmd.SetDir(r.LocalPath()) + } else { + cmd.SetDir(filepath.Dir(r.LocalPath())) + } + // Ensure no prompting for PWs + cmd.SetEnv(append([]string{"GIT_ASKPASS=", "GIT_TERMINAL_PROMPT=0"}, os.Environ()...)) + out, err := cmd.CombinedOutput() + if err != nil { + return nil, errors.Wrap(err, string(out)) + } + + all := bytes.Split(bytes.TrimSpace(out), []byte("\n")) + if len(all) == 1 && len(all[0]) == 0 { + return nil, fmt.Errorf("no data returned from ls-remote") + } + + // Pull out the HEAD rev (it's always first) so we know what branches to + // mark as default. This is, perhaps, not the best way to glean this, but it + // was good enough for git itself until 1.8.5. Also, the alternative is + // sniffing data out of the pack protocol, which is a separate request, and + // also waaaay more than we want to do right now. + // + // The cost is that we could potentially have multiple branches marked as + // the default. If that does occur, a later check (again, emulating git + // <1.8.5 behavior) further narrows the failure mode by choosing master as + // the sole default branch if a) master exists and b) master is one of the + // branches marked as a default. + // + // This all reduces the failure mode to a very narrow range of + // circumstances. Nevertheless, if we do end up emitting multiple + // default branches, it is possible that a user could end up following a + // non-default branch, IF: + // + // * Multiple branches match the HEAD rev + // * None of them are master + // * The solver makes it into the branch list in the version queue + // * The user/tool has provided no constraint (so, anyConstraint) + // * A branch that is not actually the default, but happens to share the + // rev, is lexicographically less than the true default branch + // + // If all of those conditions are met, then the user would end up with an + // erroneous non-default branch in their lock file. + var headrev Revision + var onedef, multidef, defmaster bool + + smap := make(map[string]int) + uniq := 0 + vlist = make([]PairedVersion, len(all)) + for _, pair := range all { + var v PairedVersion + // Valid `git ls-remote` output should start with hash, be at least + // 45 chars long and 40th character should be '\t' + // + // See: https://github.com/golang/dep/pull/1160#issuecomment-328843519 + if len(pair) < 45 || pair[40] != '\t' || !s.isValidHash(pair[:40]) { + continue + } + if string(pair[41:]) == "HEAD" { + // If HEAD is present, it's always first + headrev = Revision(pair[:40]) + } else if string(pair[46:51]) == "heads" { + rev := Revision(pair[:40]) + + isdef := rev == headrev + n := string(pair[52:]) + if isdef { + if onedef { + multidef = true + } + onedef = true + if n == "master" { + defmaster = true + } + } + v = branchVersion{ + name: n, + isDefault: isdef, + }.Pair(rev).(PairedVersion) + + vlist[uniq] = v + uniq++ + } else if string(pair[46:50]) == "tags" { + vstr := string(pair[51:]) + if strings.HasSuffix(vstr, "^{}") { + // If the suffix is there, then we *know* this is the rev of + // the underlying commit object that we actually want + vstr = strings.TrimSuffix(vstr, "^{}") + if i, ok := smap[vstr]; ok { + v = NewVersion(vstr).Pair(Revision(pair[:40])) + vlist[i] = v + continue + } + } else if _, ok := smap[vstr]; ok { + // Already saw the deref'd version of this tag, if one + // exists, so skip this. + continue + // Can only hit this branch if we somehow got the deref'd + // version first. Which should be impossible, but this + // covers us in case of weirdness, anyway. + } + v = NewVersion(vstr).Pair(Revision(pair[:40])) + smap[vstr] = uniq + vlist[uniq] = v + uniq++ + } + } + + // Trim off excess from the slice + vlist = vlist[:uniq] + + // There were multiple default branches, but one was master. So, go through + // and strip the default flag from all the non-master branches. + if multidef && defmaster { + for k, v := range vlist { + pv := v.(PairedVersion) + if bv, ok := pv.Unpair().(branchVersion); ok { + if bv.name != "master" && bv.isDefault { + bv.isDefault = false + vlist[k] = bv.Pair(pv.Revision()) + } + } + } + } + + return +} + +// gopkginSource is a specialized git source that performs additional filtering +// according to the input URL. +type gopkginSource struct { + gitSource + major uint64 + unstable bool + // The aliased URL we report as being the one we talk to, even though we're + // actually talking directly to GitHub. + aliasURL string +} + +func (s *gopkginSource) upstreamURL() string { + return s.aliasURL +} + +func (s *gopkginSource) listVersions(ctx context.Context) ([]PairedVersion, error) { + ovlist, err := s.gitSource.listVersions(ctx) + if err != nil { + return nil, err + } + + // Apply gopkg.in's filtering rules + vlist := make([]PairedVersion, len(ovlist)) + k := 0 + var dbranch int // index of branch to be marked default + var bsv semver.Version + var defaultBranch PairedVersion + tryDefaultAsV0 := s.major == 0 + for _, v := range ovlist { + // all git versions will always be paired + pv := v.(versionPair) + switch tv := pv.v.(type) { + case semVersion: + tryDefaultAsV0 = false + if tv.sv.Major() == s.major && !s.unstable { + vlist[k] = v + k++ + } + case branchVersion: + if tv.isDefault && defaultBranch == nil { + defaultBranch = pv + } + + // The semver lib isn't exactly the same as gopkg.in's logic, but + // it's close enough that it's probably fine to use. We can be more + // exact if real problems crop up. + sv, err := semver.NewVersion(tv.name) + if err != nil { + continue + } + tryDefaultAsV0 = false + + if sv.Major() != s.major { + // not the same major version as specified in the import path constraint + continue + } + + // Gopkg.in has a special "-unstable" suffix which we need to handle + // separately. + if s.unstable != strings.HasSuffix(tv.name, gopkgUnstableSuffix) { + continue + } + + // Turn off the default branch marker unconditionally; we can't know + // which one to mark as default until we've seen them all + tv.isDefault = false + // Figure out if this is the current leader for default branch + if bsv == (semver.Version{}) || bsv.LessThan(sv) { + bsv = sv + dbranch = k + } + pv.v = tv + vlist[k] = pv + k++ + } + // The switch skips plainVersions because they cannot possibly meet + // gopkg.in's requirements + } + + vlist = vlist[:k] + if bsv != (semver.Version{}) { + dbv := vlist[dbranch].(versionPair) + vlist[dbranch] = branchVersion{ + name: dbv.v.(branchVersion).name, + isDefault: true, + }.Pair(dbv.r) + } + + // Treat the default branch as v0 only when no other semver branches/tags exist + // See http://labix.org/gopkg.in#VersionZero + if tryDefaultAsV0 && defaultBranch != nil { + vlist = append(vlist, defaultBranch) + } + + return vlist, nil +} + +// bzrSource is a generic bzr repository implementation that should work with +// all standard bazaar remotes. +type bzrSource struct { + baseVCSSource +} + +func (s *bzrSource) exportRevisionTo(ctx context.Context, rev Revision, to string) error { + if err := s.baseVCSSource.exportRevisionTo(ctx, rev, to); err != nil { + return err + } + + return os.RemoveAll(filepath.Join(to, ".bzr")) +} + +func (s *bzrSource) listVersions(ctx context.Context) ([]PairedVersion, error) { + r := s.repo + + // TODO(sdboyer) this should be handled through the gateway's FSM + if !r.CheckLocal() { + err := s.initLocal(ctx) + if err != nil { + return nil, err + } + } + + // Now, list all the tags + tagsCmd := commandContext(ctx, "bzr", "tags", "--show-ids", "-v") + tagsCmd.SetDir(r.LocalPath()) + out, err := tagsCmd.CombinedOutput() + if err != nil { + return nil, errors.Wrap(err, string(out)) + } + + all := bytes.Split(bytes.TrimSpace(out), []byte("\n")) + + viCmd := commandContext(ctx, "bzr", "version-info", "--custom", "--template={revision_id}", "--revision=branch:.") + viCmd.SetDir(r.LocalPath()) + branchrev, err := viCmd.CombinedOutput() + if err != nil { + return nil, errors.Wrap(err, string(branchrev)) + } + + vlist := make([]PairedVersion, 0, len(all)+1) + + // Now, all the tags. + for _, line := range all { + idx := bytes.IndexByte(line, 32) // space + v := NewVersion(string(line[:idx])) + r := Revision(bytes.TrimSpace(line[idx:])) + vlist = append(vlist, v.Pair(r)) + } + + // Last, add the default branch, hardcoding the visual representation of it + // that bzr uses when operating in the workflow mode we're using. + v := newDefaultBranch("(default)") + vlist = append(vlist, v.Pair(Revision(string(branchrev)))) + + return vlist, nil +} + +func (s *bzrSource) disambiguateRevision(ctx context.Context, r Revision) (Revision, error) { + // If we used the default baseVCSSource behavior here, we would return the + // bazaar revision number, which is not a globally unique identifier - it is + // only unique within a branch. This is just the way that + // github.com/Masterminds/vcs chooses to handle bazaar. We want a + // disambiguated unique ID, though, so we need slightly different behavior: + // check whether r doesn't error when we try to look it up. If so, trust that + // it's a revision. + _, err := s.repo.CommitInfo(string(r)) + if err != nil { + return "", err + } + return r, nil +} + +// hgSource is a generic hg repository implementation that should work with +// all standard mercurial servers. +type hgSource struct { + baseVCSSource +} + +func (s *hgSource) exportRevisionTo(ctx context.Context, rev Revision, to string) error { + // TODO: use hg instead of the generic approach in + // baseVCSSource.exportRevisionTo to make it faster. + if err := s.baseVCSSource.exportRevisionTo(ctx, rev, to); err != nil { + return err + } + + return os.RemoveAll(filepath.Join(to, ".hg")) +} + +func (s *hgSource) listVersions(ctx context.Context) ([]PairedVersion, error) { + var vlist []PairedVersion + + r := s.repo + // TODO(sdboyer) this should be handled through the gateway's FSM + if !r.CheckLocal() { + err := s.initLocal(ctx) + if err != nil { + return nil, err + } + } + + // Now, list all the tags + tagsCmd := commandContext(ctx, "hg", "tags", "--debug", "--verbose") + tagsCmd.SetDir(r.LocalPath()) + out, err := tagsCmd.CombinedOutput() + if err != nil { + return nil, errors.Wrap(err, string(out)) + } + + all := bytes.Split(bytes.TrimSpace(out), []byte("\n")) + lbyt := []byte("local") + nulrev := []byte("0000000000000000000000000000000000000000") + for _, line := range all { + if bytes.Equal(lbyt, line[len(line)-len(lbyt):]) { + // Skip local tags + continue + } + + // tip is magic, don't include it + if bytes.HasPrefix(line, []byte("tip")) { + continue + } + + // Split on colon; this gets us the rev and the tag plus local revno + pair := bytes.Split(line, []byte(":")) + if bytes.Equal(nulrev, pair[1]) { + // null rev indicates this tag is marked for deletion + continue + } + + idx := bytes.IndexByte(pair[0], 32) // space + v := NewVersion(string(pair[0][:idx])).Pair(Revision(pair[1])).(PairedVersion) + vlist = append(vlist, v) + } + + // bookmarks next, because the presence of the magic @ bookmark has to + // determine how we handle the branches + var magicAt bool + bookmarksCmd := commandContext(ctx, "hg", "bookmarks", "--debug") + bookmarksCmd.SetDir(r.LocalPath()) + out, err = bookmarksCmd.CombinedOutput() + if err != nil { + // better nothing than partial and misleading + return nil, errors.Wrap(err, string(out)) + } + + out = bytes.TrimSpace(out) + if !bytes.Equal(out, []byte("no bookmarks set")) { + all = bytes.Split(out, []byte("\n")) + for _, line := range all { + // Trim leading spaces, and * marker if present + line = bytes.TrimLeft(line, " *") + pair := bytes.Split(line, []byte(":")) + // if this doesn't split exactly once, we have something weird + if len(pair) != 2 { + continue + } + + // Split on colon; this gets us the rev and the branch plus local revno + idx := bytes.IndexByte(pair[0], 32) // space + // if it's the magic @ marker, make that the default branch + str := string(pair[0][:idx]) + var v PairedVersion + if str == "@" { + magicAt = true + v = newDefaultBranch(str).Pair(Revision(pair[1])).(PairedVersion) + } else { + v = NewBranch(str).Pair(Revision(pair[1])).(PairedVersion) + } + vlist = append(vlist, v) + } + } + + cmd := commandContext(ctx, "hg", "branches", "-c", "--debug") + cmd.SetDir(r.LocalPath()) + out, err = cmd.CombinedOutput() + if err != nil { + // better nothing than partial and misleading + return nil, errors.Wrap(err, string(out)) + } + + all = bytes.Split(bytes.TrimSpace(out), []byte("\n")) + for _, line := range all { + // Trim inactive and closed suffixes, if present; we represent these + // anyway + line = bytes.TrimSuffix(line, []byte(" (inactive)")) + line = bytes.TrimSuffix(line, []byte(" (closed)")) + + // Split on colon; this gets us the rev and the branch plus local revno + pair := bytes.Split(line, []byte(":")) + idx := bytes.IndexByte(pair[0], 32) // space + str := string(pair[0][:idx]) + // if there was no magic @ bookmark, and this is mercurial's magic + // "default" branch, then mark it as default branch + var v PairedVersion + if !magicAt && str == "default" { + v = newDefaultBranch(str).Pair(Revision(pair[1])).(PairedVersion) + } else { + v = NewBranch(str).Pair(Revision(pair[1])).(PairedVersion) + } + vlist = append(vlist, v) + } + + return vlist, nil +} diff --git a/vendor/github.com/golang/dep/gps/vcs_source_test.go b/vendor/github.com/golang/dep/gps/vcs_source_test.go new file mode 100644 index 00000000..ee39ecba --- /dev/null +++ b/vendor/github.com/golang/dep/gps/vcs_source_test.go @@ -0,0 +1,897 @@ +// Copyright 2017 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 gps + +import ( + "context" + "io/ioutil" + "log" + "net/url" + "os" + "os/exec" + "path/filepath" + "reflect" + "runtime" + "strings" + "sync" + "testing" + + "github.com/golang/dep/internal/test" +) + +// Parent test that executes all the slow vcs interaction tests in parallel. +func TestSlowVcs(t *testing.T) { + t.Run("write-deptree", testWriteDepTree) + t.Run("source-gateway", testSourceGateway) + t.Run("bzr-repo", testBzrRepo) + t.Run("bzr-source", testBzrSourceInteractions) + t.Run("svn-repo", testSvnRepo) + // TODO(sdboyer) svn-source + t.Run("hg-repo", testHgRepo) + t.Run("hg-source", testHgSourceInteractions) + t.Run("git-repo", testGitRepo) + t.Run("git-source", testGitSourceInteractions) + t.Run("gopkgin-source", testGopkginSourceInteractions) +} + +func testGitSourceInteractions(t *testing.T) { + t.Parallel() + + // This test is slowish, skip it on -short + if testing.Short() { + t.Skip("Skipping git source version fetching test in short mode") + } + requiresBins(t, "git") + + cpath, err := ioutil.TempDir("", "smcache") + if err != nil { + t.Errorf("Failed to create temp dir: %s", err) + } + defer func() { + if err := os.RemoveAll(cpath); err != nil { + t.Errorf("removeAll failed: %s", err) + } + }() + os.Mkdir(filepath.Join(cpath, "sources"), 0777) + + n := "github.com/sdboyer/gpkt" + un := "https://" + n + u, err := url.Parse(un) + if err != nil { + t.Fatalf("Error parsing URL %s: %s", un, err) + } + mb := maybeGitSource{ + url: u, + } + + ctx := context.Background() + superv := newSupervisor(ctx) + isrc, state, err := mb.try(ctx, cpath, newMemoryCache(), superv) + if err != nil { + t.Fatalf("Unexpected error while setting up gitSource for test repo: %s", err) + } + + wantstate := sourceIsSetUp | sourceExistsUpstream | sourceHasLatestVersionList + if state != wantstate { + t.Errorf("Expected return state to be %v, got %v", wantstate, state) + } + + err = isrc.initLocal(ctx) + if err != nil { + t.Fatalf("Error on cloning git repo: %s", err) + } + + src, ok := isrc.(*gitSource) + if !ok { + t.Fatalf("Expected a gitSource, got a %T", isrc) + } + + if un != src.upstreamURL() { + t.Errorf("Expected %s as source URL, got %s", un, src.upstreamURL()) + } + + pvlist, err := src.listVersions(ctx) + if err != nil { + t.Fatalf("Unexpected error getting version pairs from git repo: %s", err) + } + + vlist := hidePair(pvlist) + // check that an expected rev is present + is, err := src.revisionPresentIn(Revision("4a54adf81c75375d26d376459c00d5ff9b703e5e")) + if err != nil { + t.Errorf("Unexpected error while checking revision presence: %s", err) + } else if !is { + t.Errorf("Revision that should exist was not present") + } + + if len(vlist) != 7 { + t.Errorf("git test repo should've produced seven versions, got %v: vlist was %s", len(vlist), vlist) + } else { + SortForUpgrade(vlist) + evl := []Version{ + NewVersion("v2.0.0").Pair(Revision("4a54adf81c75375d26d376459c00d5ff9b703e5e")), + NewVersion("v1.1.0").Pair(Revision("b2cb48dda625f6640b34d9ffb664533359ac8b91")), + NewVersion("v1.0.0").Pair(Revision("bf85021c0405edbc4f3648b0603818d641674f72")), + newDefaultBranch("master").Pair(Revision("bf85021c0405edbc4f3648b0603818d641674f72")), + NewBranch("v1").Pair(Revision("e3777f683305eafca223aefe56b4e8ecf103f467")), + NewBranch("v1.1").Pair(Revision("f1fbc520489a98306eb28c235204e39fa8a89c84")), + NewBranch("v3").Pair(Revision("4a54adf81c75375d26d376459c00d5ff9b703e5e")), + } + if !reflect.DeepEqual(vlist, evl) { + t.Errorf("Version list was not what we expected:\n\t(GOT): %s\n\t(WNT): %s", vlist, evl) + } + } + + // recheck that rev is present, this time interacting with cache differently + is, err = src.revisionPresentIn(Revision("30605f6ac35fcb075ad0bfa9296f90a7d891523e")) + if err != nil { + t.Errorf("Unexpected error while re-checking revision presence: %s", err) + } else if !is { + t.Errorf("Revision that should exist was not present on re-check") + } +} + +func testGopkginSourceInteractions(t *testing.T) { + t.Parallel() + + // This test is slowish, skip it on -short + if testing.Short() { + t.Skip("Skipping gopkg.in source version fetching test in short mode") + } + requiresBins(t, "git") + + cpath, err := ioutil.TempDir("", "smcache") + if err != nil { + t.Errorf("Failed to create temp dir: %s", err) + } + defer func() { + if err := os.RemoveAll(cpath); err != nil { + t.Errorf("removeAll failed: %s", err) + } + }() + os.Mkdir(filepath.Join(cpath, "sources"), 0777) + + tfunc := func(opath, n string, major uint64, evl []Version) { + un := "https://" + opath + u, err := url.Parse("https://" + n) + if err != nil { + t.Errorf("URL was bad, lolwut? errtext: %s", err) + return + } + unstable := strings.HasSuffix(opath, gopkgUnstableSuffix) + mb := maybeGopkginSource{ + opath: opath, + url: u, + major: major, + unstable: unstable, + } + + ctx := context.Background() + superv := newSupervisor(ctx) + isrc, state, err := mb.try(ctx, cpath, newMemoryCache(), superv) + if err != nil { + t.Errorf("Unexpected error while setting up gopkginSource for test repo: %s", err) + return + } + + wantstate := sourceIsSetUp | sourceExistsUpstream | sourceHasLatestVersionList + if state != wantstate { + t.Errorf("Expected return state to be %v, got %v", wantstate, state) + } + + err = isrc.initLocal(ctx) + if err != nil { + t.Fatalf("Error on cloning git repo: %s", err) + } + + src, ok := isrc.(*gopkginSource) + if !ok { + t.Errorf("Expected a gopkginSource, got a %T", isrc) + return + } + + if un != src.upstreamURL() { + t.Errorf("Expected %s as source URL, got %s", un, src.upstreamURL()) + } + if src.major != major { + t.Errorf("Expected %v as major version filter on gopkginSource, got %v", major, src.major) + } + + // check that an expected rev is present + rev := evl[0].(PairedVersion).Revision() + is, err := src.revisionPresentIn(rev) + if err != nil { + t.Errorf("Unexpected error while checking revision presence: %s", err) + } else if !is { + t.Errorf("Revision %s that should exist was not present", rev) + } + + pvlist, err := src.listVersions(ctx) + if err != nil { + t.Errorf("Unexpected error getting version pairs from hg repo: %s", err) + } + + vlist := hidePair(pvlist) + if len(vlist) != len(evl) { + t.Errorf("gopkgin test repo (%s) should've produced %v versions, got %v.\n%v", un, len(evl), len(vlist), vlist) + } else { + SortForUpgrade(vlist) + if !reflect.DeepEqual(vlist, evl) { + t.Errorf("Version list for %s was not what we expected:\n\t(GOT): %#v\n\t(WNT): %#v", un, vlist, evl) + } + } + + // Run again, this time to ensure cache outputs correctly + pvlist, err = src.listVersions(ctx) + if err != nil { + t.Errorf("Unexpected error getting version pairs from hg repo: %s", err) + } + + vlist = hidePair(pvlist) + if len(vlist) != len(evl) { + t.Errorf("gopkgin test repo should've produced %v versions, got %v", len(evl), len(vlist)) + } else { + SortForUpgrade(vlist) + if !reflect.DeepEqual(vlist, evl) { + t.Errorf("Version list for %s was not what we expected:\n\t(GOT): %#v\n\t(WNT): %#v", un, vlist, evl) + } + } + + // recheck that rev is present, this time interacting with cache differently + is, err = src.revisionPresentIn(rev) + if err != nil { + t.Errorf("Unexpected error while re-checking revision presence: %s", err) + } else if !is { + t.Errorf("Revision that should exist was not present on re-check") + } + } + + // simultaneously run for v1, v2, and v3 filters of the target repo + wg := &sync.WaitGroup{} + wg.Add(6) + + go func() { + // Treat master as v0 when no other branches/tags exist that match gopkg.in's rules + tfunc("gopkg.in/carolynvs/deptest-gopkgin-implicit-v0.v0", "github.com/carolynvs/deptest-gopkgin-implicit-v0", 0, []Version{ + newDefaultBranch("notmaster").Pair(Revision("94ee631b9833cd805d15f50a52e0533124ec0292")), + }) + wg.Done() + }() + + go func() { + // Use the existing v0 branch for v0, not master + tfunc("gopkg.in/carolynvs/deptest-gopkgin-explicit-v0.v0", "github.com/carolynvs/deptest-gopkgin-explicit-v0", 0, []Version{ + newDefaultBranch("v0").Pair(Revision("ec73e84554fb28f08dba630e48dbec868e77f734")), + }) + wg.Done() + }() + + go func() { + tfunc("gopkg.in/sdboyer/gpkt.v1", "github.com/sdboyer/gpkt", 1, []Version{ + NewVersion("v1.1.0").Pair(Revision("b2cb48dda625f6640b34d9ffb664533359ac8b91")), + NewVersion("v1.0.0").Pair(Revision("bf85021c0405edbc4f3648b0603818d641674f72")), + newDefaultBranch("v1.1").Pair(Revision("f1fbc520489a98306eb28c235204e39fa8a89c84")), + NewBranch("v1").Pair(Revision("e3777f683305eafca223aefe56b4e8ecf103f467")), + }) + wg.Done() + }() + + go func() { + tfunc("gopkg.in/sdboyer/gpkt.v2", "github.com/sdboyer/gpkt", 2, []Version{ + NewVersion("v2.0.0").Pair(Revision("4a54adf81c75375d26d376459c00d5ff9b703e5e")), + }) + wg.Done() + }() + + go func() { + tfunc("gopkg.in/sdboyer/gpkt.v3", "github.com/sdboyer/gpkt", 3, []Version{ + newDefaultBranch("v3").Pair(Revision("4a54adf81c75375d26d376459c00d5ff9b703e5e")), + }) + wg.Done() + }() + + go func() { + tfunc("github.com/sdboyer/gpkt2.v1-unstable", "github.com/sdboyer/gpkt2", 1, []Version{ + newDefaultBranch("v1-unstable").Pair(Revision("24de0be8f4a0b8a44321562117749b257bfcef69")), + }) + wg.Done() + }() + + wg.Wait() +} + +func testBzrSourceInteractions(t *testing.T) { + t.Parallel() + + // This test is quite slow (ugh bzr), so skip it on -short + if testing.Short() { + t.Skip("Skipping bzr source version fetching test in short mode") + } + if runtime.GOOS == "windows" { + // TODO bzr on Windows is sometimes weirdly reporting different + // "revision-id" (with mention of git), and it's breaking tests. Maybe + // this also breaks our model of bzr on Windows; maybe it breaks our + // model of bzr in general. But use of bzr is rare and dwindling, so for + // now it's least harmful to turn off the test on Windows, as the + // alternative is a DEEP dive and possible refactor. + t.Skip("TODO: Windows bzr reporting of underlying object ids is confusing") + } + requiresBins(t, "bzr") + + cpath, err := ioutil.TempDir("", "smcache") + if err != nil { + t.Errorf("Failed to create temp dir: %s", err) + } + defer func() { + if err := os.RemoveAll(cpath); err != nil { + t.Errorf("removeAll failed: %s", err) + } + }() + + n := "launchpad.net/govcstestbzrrepo" + un := "https://" + n + u, err := url.Parse(un) + if err != nil { + t.Fatalf("Error parsing URL %s: %s", un, err) + } + mb := maybeBzrSource{ + url: u, + } + + ctx := context.Background() + superv := newSupervisor(ctx) + isrc, state, err := mb.try(ctx, cpath, newMemoryCache(), superv) + if err != nil { + t.Fatalf("Unexpected error while setting up bzrSource for test repo: %s", err) + } + + wantstate := sourceIsSetUp | sourceExistsUpstream + if state != wantstate { + t.Errorf("Expected return state to be %v, got %v", wantstate, state) + } + + err = isrc.initLocal(ctx) + if err != nil { + t.Fatalf("Error on cloning bzr repo: %s", err) + } + + src, ok := isrc.(*bzrSource) + if !ok { + t.Fatalf("Expected a bzrSource, got a %T", isrc) + } + + if state != wantstate { + t.Errorf("Expected return state to be %v, got %v", wantstate, state) + } + if un != src.upstreamURL() { + t.Errorf("Expected %s as source URL, got %s", un, src.upstreamURL()) + } + evl := []Version{ + NewVersion("1.0.0").Pair(Revision("matt@mattfarina.com-20150731135137-pbphasfppmygpl68")), + newDefaultBranch("(default)").Pair(Revision("matt@mattfarina.com-20150731135137-pbphasfppmygpl68")), + } + + // check that an expected rev is present + is, err := src.revisionPresentIn(Revision("matt@mattfarina.com-20150731135137-pbphasfppmygpl68")) + if err != nil { + t.Errorf("Unexpected error while checking revision presence: %s", err) + } else if !is { + t.Errorf("Revision that should exist was not present") + } + + pvlist, err := src.listVersions(ctx) + if err != nil { + t.Errorf("Unexpected error getting version pairs from bzr repo: %s", err) + } + + vlist := hidePair(pvlist) + if len(vlist) != 2 { + t.Errorf("bzr test repo should've produced two versions, got %v", len(vlist)) + } else { + SortForUpgrade(vlist) + if !reflect.DeepEqual(vlist, evl) { + t.Errorf("bzr version list was not what we expected:\n\t(GOT): %s\n\t(WNT): %s", vlist, evl) + } + } + + // Run again, this time to ensure cache outputs correctly + pvlist, err = src.listVersions(ctx) + if err != nil { + t.Errorf("Unexpected error getting version pairs from bzr repo: %s", err) + } + + vlist = hidePair(pvlist) + if len(vlist) != 2 { + t.Errorf("bzr test repo should've produced two versions, got %v", len(vlist)) + } else { + SortForUpgrade(vlist) + if !reflect.DeepEqual(vlist, evl) { + t.Errorf("bzr version list was not what we expected:\n\t(GOT): %s\n\t(WNT): %s", vlist, evl) + } + } + + // recheck that rev is present, this time interacting with cache differently + is, err = src.revisionPresentIn(Revision("matt@mattfarina.com-20150731135137-pbphasfppmygpl68")) + if err != nil { + t.Errorf("Unexpected error while re-checking revision presence: %s", err) + } else if !is { + t.Errorf("Revision that should exist was not present on re-check") + } +} + +func testHgSourceInteractions(t *testing.T) { + t.Parallel() + + // This test is slow, so skip it on -short + if testing.Short() { + t.Skip("Skipping hg source version fetching test in short mode") + } + requiresBins(t, "hg") + + cpath, err := ioutil.TempDir("", "smcache") + if err != nil { + t.Errorf("Failed to create temp dir: %s", err) + } + defer func() { + if err := os.RemoveAll(cpath); err != nil { + t.Errorf("removeAll failed: %s", err) + } + }() + + tfunc := func(n string, evl []Version) { + un := "https://" + n + u, err := url.Parse(un) + if err != nil { + t.Errorf("URL was bad, lolwut? errtext: %s", err) + return + } + mb := maybeHgSource{ + url: u, + } + + ctx := context.Background() + superv := newSupervisor(ctx) + isrc, state, err := mb.try(ctx, cpath, newMemoryCache(), superv) + if err != nil { + t.Errorf("Unexpected error while setting up hgSource for test repo: %s", err) + return + } + + wantstate := sourceIsSetUp | sourceExistsUpstream + if state != wantstate { + t.Errorf("Expected return state to be %v, got %v", wantstate, state) + } + + err = isrc.initLocal(ctx) + if err != nil { + t.Fatalf("Error on cloning hg repo: %s", err) + } + + src, ok := isrc.(*hgSource) + if !ok { + t.Errorf("Expected a hgSource, got a %T", isrc) + return + } + + if state != wantstate { + t.Errorf("Expected return state to be %v, got %v", wantstate, state) + } + if un != src.upstreamURL() { + t.Errorf("Expected %s as source URL, got %s", un, src.upstreamURL()) + } + + // check that an expected rev is present + is, err := src.revisionPresentIn(Revision("103d1bddef2199c80aad7c42041223083d613ef9")) + if err != nil { + t.Errorf("Unexpected error while checking revision presence: %s", err) + } else if !is { + t.Errorf("Revision that should exist was not present") + } + + pvlist, err := src.listVersions(ctx) + if err != nil { + t.Errorf("Unexpected error getting version pairs from hg repo: %s", err) + } + + vlist := hidePair(pvlist) + if len(vlist) != len(evl) { + t.Errorf("hg test repo should've produced %v versions, got %v", len(evl), len(vlist)) + } else { + SortForUpgrade(vlist) + if !reflect.DeepEqual(vlist, evl) { + t.Errorf("Version list was not what we expected:\n\t(GOT): %s\n\t(WNT): %s", vlist, evl) + } + } + + // Run again, this time to ensure cache outputs correctly + pvlist, err = src.listVersions(ctx) + if err != nil { + t.Errorf("Unexpected error getting version pairs from hg repo: %s", err) + } + + vlist = hidePair(pvlist) + if len(vlist) != len(evl) { + t.Errorf("hg test repo should've produced %v versions, got %v", len(evl), len(vlist)) + } else { + SortForUpgrade(vlist) + if !reflect.DeepEqual(vlist, evl) { + t.Errorf("Version list was not what we expected:\n\t(GOT): %s\n\t(WNT): %s", vlist, evl) + } + } + + // recheck that rev is present, this time interacting with cache differently + is, err = src.revisionPresentIn(Revision("103d1bddef2199c80aad7c42041223083d613ef9")) + if err != nil { + t.Errorf("Unexpected error while re-checking revision presence: %s", err) + } else if !is { + t.Errorf("Revision that should exist was not present on re-check") + } + } + + // simultaneously run for both the repo with and without the magic bookmark + donech := make(chan struct{}) + go func() { + tfunc("bitbucket.org/sdboyer/withbm", []Version{ + NewVersion("v1.0.0").Pair(Revision("aa110802a0c64195d0a6c375c9f66668827c90b4")), + newDefaultBranch("@").Pair(Revision("b10d05d581e5401f383e48ccfeb84b48fde99d06")), + NewBranch("another").Pair(Revision("b10d05d581e5401f383e48ccfeb84b48fde99d06")), + NewBranch("default").Pair(Revision("3d466f437f6616da594bbab6446cc1cb4328d1bb")), + NewBranch("newbranch").Pair(Revision("5e2a01be9aee942098e44590ae545c7143da9675")), + }) + close(donech) + }() + + tfunc("bitbucket.org/sdboyer/nobm", []Version{ + NewVersion("v1.0.0").Pair(Revision("aa110802a0c64195d0a6c375c9f66668827c90b4")), + newDefaultBranch("default").Pair(Revision("3d466f437f6616da594bbab6446cc1cb4328d1bb")), + NewBranch("another").Pair(Revision("b10d05d581e5401f383e48ccfeb84b48fde99d06")), + NewBranch("newbranch").Pair(Revision("5e2a01be9aee942098e44590ae545c7143da9675")), + }) + + <-donech +} + +func TestGitSourceListVersionsNoHEAD(t *testing.T) { + // t.Parallel() + + requiresBins(t, "git") + + h := test.NewHelper(t) + defer h.Cleanup() + h.TempDir("smcache") + cpath := h.Path("smcache") + os.Mkdir(filepath.Join(cpath, "sources"), 0777) + + h.TempDir("repo") + repoPath := h.Path("repo") + + // Create test repo with a single commit on the master branch + h.RunGit(repoPath, "init") + h.RunGit(repoPath, "config", "--local", "user.email", "test@example.com") + h.RunGit(repoPath, "config", "--local", "user.name", "Test author") + h.RunGit(repoPath, "commit", "--allow-empty", `--message="Initial commit"`) + + // Make HEAD point at a nonexistent branch (deleting it is not allowed) + // The `git ls-remote` that listVersions() calls will not return a HEAD ref + // because it points at a nonexistent branch + h.RunGit(repoPath, "symbolic-ref", "HEAD", "refs/heads/nonexistent") + + un := "file://" + filepath.ToSlash(repoPath) + u, err := url.Parse(un) + if err != nil { + t.Fatalf("Error parsing URL %s: %s", un, err) + } + mb := maybeGitSource{u} + + ctx := context.Background() + superv := newSupervisor(ctx) + isrc, _, err := mb.try(ctx, cpath, newMemoryCache(), superv) + if err != nil { + t.Fatalf("Unexpected error while setting up gitSource for test repo: %s", err) + } + + err = isrc.initLocal(ctx) + if err != nil { + t.Fatalf("Error on cloning git repo: %s", err) + } + + src, ok := isrc.(*gitSource) + if !ok { + t.Fatalf("Expected a gitSource, got a %T", isrc) + } + + pvlist, err := src.listVersions(ctx) + if err != nil { + t.Fatalf("Unexpected error getting version pairs from git repo: %s", err) + } + + if len(pvlist) != 1 { + t.Errorf("Unexpected version pair length:\n\t(GOT): %d\n\t(WNT): %d", len(pvlist), 1) + } +} + +func TestGitSourceListVersionsNoDupes(t *testing.T) { + // t.Parallel() + + // This test is slowish, skip it on -short + if testing.Short() { + t.Skip("Skipping git source version fetching test in short mode") + } + requiresBins(t, "git") + + cpath, err := ioutil.TempDir("", "smcache") + if err != nil { + t.Errorf("Failed to create temp dir: %s", err) + } + defer func() { + if err := os.RemoveAll(cpath); err != nil { + t.Errorf("removeAll failed: %s", err) + } + }() + os.Mkdir(filepath.Join(cpath, "sources"), 0777) + + n := "github.com/carolynvs/deptest-importers" + un := "https://" + n + u, err := url.Parse(un) + if err != nil { + t.Fatalf("Error parsing URL %s: %s", un, err) + } + mb := maybeGitSource{ + url: u, + } + + ctx := context.Background() + superv := newSupervisor(ctx) + src, state, err := mb.try(ctx, cpath, newMemoryCache(), superv) + if err != nil { + t.Fatalf("Unexpected error while setting up gitSource for test repo: %s", err) + } + + wantstate := sourceIsSetUp | sourceExistsUpstream | sourceHasLatestVersionList + if state != wantstate { + t.Errorf("Expected return state to be %v, got %v", wantstate, state) + } + + err = src.initLocal(ctx) + if err != nil { + t.Fatalf("Error on cloning git repo: %s", err) + } + + pvlist, err := src.listVersions(ctx) + if err != nil { + t.Fatalf("Unexpected error getting version pairs from git repo: %s", err) + } + + for i := range pvlist { + pv1 := pvlist[i] + uv1 := pv1.Unpair() + for j := range pvlist { + if i == j { + continue + } + pv2 := pvlist[j] + uv2 := pv2.Unpair() + if uv1 == uv2 { + t.Errorf("duplicate version pair mapping from %#v to both %q and %q", uv1, pv1.Revision(), pv2.Revision()) + } + } + } +} + +func TestGitSourceAdaptiveCleanup(t *testing.T) { + // t.Parallel() + + // This test is slowish, skip it on -short + if testing.Short() { + t.Skip("Skipping git adaptive failure recovery test in short mode") + } + requiresBins(t, "git") + + cpath, err := ioutil.TempDir("", "smcache") + if err != nil { + t.Fatalf("Failed to create temp dir: %s", err) + } + + var sm *SourceMgr + mkSM := func() { + // If sm is already set, make sure it's released, then create a new one. + if sm != nil { + sm.Release() + } + + var err error + sm, err = NewSourceManager(SourceManagerConfig{ + Cachedir: cpath, + Logger: log.New(test.Writer{TB: t}, "", 0), + }) + if err != nil { + t.Fatalf("Unexpected error on SourceManager creation: %s", err) + } + } + + mkSM() + id := mkPI("github.com/sdboyer/gpkt") + err = sm.SyncSourceFor(id) + if err != nil { + t.Fatal(err) + } + + repodir := filepath.Join(sm.cachedir, "sources", "https---github.com-sdboyer-gpkt") + if _, err := os.Stat(repodir); err != nil { + if os.IsNotExist(err) { + t.Fatalf("expected location for repodir did not exist: %q", repodir) + } else { + t.Fatal(err) + } + } + + // Create a file that git will see as untracked. + untrackedPath := filepath.Join(repodir, "untrackedfile") + err = ioutil.WriteFile(untrackedPath, []byte("foo"), 0644) + if err != nil { + t.Fatal(err) + } + + mkSM() + err = sm.SyncSourceFor(id) + if err != nil { + t.Fatalf("choked after adding dummy file: %q", err) + } + + if _, err := os.Stat(untrackedPath); err == nil { + t.Fatal("untracked file still existed after cleanup should've been triggered") + } + + // Remove a file that we know exists, which `git status` checks should catch. + readmePath := filepath.Join(repodir, "README.md") + os.Remove(readmePath) + + mkSM() + err = sm.SyncSourceFor(id) + if err != nil { + t.Fatalf("choked after removing known file: %q", err) + } + + if _, err := os.Stat(readmePath); err != nil { + t.Fatal("README was still absent after cleanup should've been triggered") + } + + // Remove .git/objects directory, which should make git bite it. + err = os.RemoveAll(filepath.Join(repodir, ".git", "objects")) + if err != nil { + t.Fatal(err) + } + + mkSM() + err = sm.SyncSourceFor(id) + if err != nil { + t.Fatalf("choked after removing .git/objects directory: %q", err) + } + + sm.Release() + os.RemoveAll(cpath) +} + +func Test_bzrSource_exportRevisionTo_removeVcsFiles(t *testing.T) { + t.Parallel() + + // This test is slow, so skip it on -short + if testing.Short() { + t.Skip("Skipping hg source version fetching test in short mode") + } + if runtime.GOOS == "windows" { + // TODO see todo in TestBzrSourceInteractions + t.Skip("TODO: Windows bzr reporting of underlying object ids is confusing") + } + requiresBins(t, "bzr") + + h := test.NewHelper(t) + defer h.Cleanup() + h.TempDir("smcache") + cpath := h.Path("smcache") + repoPath := filepath.Join(h.Path("."), "repo") + + rev := Revision("matt@mattfarina.com-20150731135137-pbphasfppmygpl68") + n := "launchpad.net/govcstestbzrrepo" + un := "https://" + n + u, err := url.Parse(un) + if err != nil { + t.Errorf("URL was bad, lolwut? errtext: %s", err) + return + } + mb := maybeBzrSource{u} + + ctx := context.Background() + superv := newSupervisor(ctx) + isrc, _, err := mb.try(ctx, cpath, newMemoryCache(), superv) + if err != nil { + t.Fatalf("unexpected error while setting up hgSource for test repo: %s", err) + } + + err = isrc.initLocal(ctx) + if err != nil { + t.Fatalf("Error on cloning bzr repo: %s", err) + } + + src, ok := isrc.(*bzrSource) + if !ok { + t.Fatalf("expected a bzrSource, got a %T", isrc) + } + + if err := src.exportRevisionTo(ctx, rev, repoPath); err != nil { + t.Fatalf("unexpected error: %v", err) + } + + _, err = os.Stat(filepath.Join(repoPath, ".bzr")) + if err == nil { + t.Fatal("expected .bzr/ to not exists") + } else if !os.IsNotExist(err) { + t.Fatalf("unexpected error: %v", err) + } +} + +func Test_hgSource_exportRevisionTo_removeVcsFiles(t *testing.T) { + t.Parallel() + + // This test is slow, so skip it on -short + if testing.Short() { + t.Skip("Skipping hg source version fetching test in short mode") + } + requiresBins(t, "hg") + + h := test.NewHelper(t) + defer h.Cleanup() + h.TempDir("smcache") + cpath := h.Path("smcache") + repoPath := filepath.Join(h.Path("."), "repo") + + rev := Revision("6f55e1f03d91f8a7cce35d1968eb60a2352e4d59") + n := "bitbucket.org/golang-dep/dep-test" + un := "https://" + n + u, err := url.Parse(un) + if err != nil { + t.Errorf("URL was bad, lolwut? errtext: %s", err) + return + } + mb := maybeHgSource{u} + + ctx := context.Background() + superv := newSupervisor(ctx) + isrc, _, err := mb.try(ctx, cpath, newMemoryCache(), superv) + if err != nil { + t.Fatalf("unexpected error while setting up hgSource for test repo: %s", err) + } + + err = isrc.initLocal(ctx) + if err != nil { + t.Fatalf("Error on cloning hg repo: %s", err) + } + + src, ok := isrc.(*hgSource) + if !ok { + t.Fatalf("expected a hgSource, got a %T", isrc) + } + + if err := src.exportRevisionTo(ctx, rev, repoPath); err != nil { + t.Fatalf("unexpected error: %v", err) + } + + _, err = os.Stat(filepath.Join(repoPath, ".hg")) + if err == nil { + t.Fatal("expected .hg/ to not exists") + } else if !os.IsNotExist(err) { + t.Fatalf("unexpected error: %v", err) + } +} + +// Fail a test if the specified binaries aren't installed. +func requiresBins(t *testing.T, bins ...string) { + for _, b := range bins { + _, err := exec.LookPath(b) + if err != nil { + t.Fatalf("%s is not installed", b) + } + } +} diff --git a/vendor/github.com/golang/dep/gps/vcs_version.go b/vendor/github.com/golang/dep/gps/vcs_version.go new file mode 100644 index 00000000..1009337d --- /dev/null +++ b/vendor/github.com/golang/dep/gps/vcs_version.go @@ -0,0 +1,67 @@ +// Copyright 2017 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 gps + +import ( + "strings" + + "github.com/Masterminds/vcs" + "github.com/pkg/errors" +) + +// VCSVersion returns the current project version for an absolute path. +func VCSVersion(path string) (Version, error) { + repo, err := vcs.NewRepo("", path) + if err != nil { + return nil, errors.Wrapf(err, "creating new repo for root: %s", path) + } + + ver, err := repo.Current() + if err != nil { + return nil, errors.Wrapf(err, "finding current branch/version for root: %s", path) + } + + rev, err := repo.Version() + if err != nil { + return nil, errors.Wrapf(err, "getting repo version for root: %s", path) + } + + // First look through tags. + tags, err := repo.Tags() + if err != nil { + return nil, errors.Wrapf(err, "getting repo tags for root: %s", path) + } + // Try to match the current version to a tag. + if contains(tags, ver) { + // Assume semver if it starts with a v. + if strings.HasPrefix(ver, "v") { + return NewVersion(ver).Pair(Revision(rev)), nil + } + + return nil, errors.Errorf("version for root %s does not start with a v: %q", path, ver) + } + + // Look for the current branch. + branches, err := repo.Branches() + if err != nil { + return nil, errors.Wrapf(err, "getting repo branch for root: %s") + } + // Try to match the current version to a branch. + if contains(branches, ver) { + return NewBranch(ver).Pair(Revision(rev)), nil + } + + return Revision(rev), nil +} + +// contains checks if a array of strings contains a value +func contains(a []string, b string) bool { + for _, v := range a { + if b == v { + return true + } + } + return false +} diff --git a/vendor/github.com/golang/dep/gps/vcs_version_test.go b/vendor/github.com/golang/dep/gps/vcs_version_test.go new file mode 100644 index 00000000..2d85b60f --- /dev/null +++ b/vendor/github.com/golang/dep/gps/vcs_version_test.go @@ -0,0 +1,59 @@ +// Copyright 2017 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 gps + +import ( + "path/filepath" + "testing" + + "github.com/golang/dep/internal/test" +) + +func TestVCSVersion(t *testing.T) { + if testing.Short() { + t.Skip("Skipping slow test in short mode") + } + + h := test.NewHelper(t) + defer h.Cleanup() + requiresBins(t, "git") + + h.TempDir("src") + gopath := h.Path(".") + h.Setenv("GOPATH", gopath) + + importPaths := map[string]struct { + rev Version + checkout bool + }{ + "github.com/pkg/errors": { + rev: NewVersion("v0.8.0").Pair("645ef00459ed84a119197bfb8d8205042c6df63d"), // semver + checkout: true, + }, + "github.com/sirupsen/logrus": { + rev: Revision("42b84f9ec624953ecbf81a94feccb3f5935c5edf"), // random sha + checkout: true, + }, + "github.com/rsc/go-get-default-branch": { + rev: NewBranch("another-branch").Pair("8e6902fdd0361e8fa30226b350e62973e3625ed5"), + }, + } + + // checkout the specified revisions + for ip, info := range importPaths { + h.RunGo("get", ip) + repoDir := h.Path("src/" + ip) + if info.checkout { + h.RunGit(repoDir, "checkout", info.rev.String()) + } + abs := filepath.FromSlash(filepath.Join(gopath, "src", ip)) + got, err := VCSVersion(abs) + h.Must(err) + + if got != info.rev { + t.Fatalf("expected %q, got %q", got.String(), info.rev.String()) + } + } +} diff --git a/vendor/github.com/golang/dep/gps/version.go b/vendor/github.com/golang/dep/gps/version.go new file mode 100644 index 00000000..22f12ef9 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/version.go @@ -0,0 +1,875 @@ +// Copyright 2017 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 gps + +import ( + "fmt" + "sort" + + "github.com/Masterminds/semver" + "github.com/golang/dep/gps/internal/pb" +) + +// VersionType indicates a type for a Version that conveys some additional +// semantics beyond that which is literally embedded on the Go type. +type VersionType uint8 + +// VersionTypes for the four major classes of version we deal with +const ( + IsRevision VersionType = iota + IsVersion + IsSemver + IsBranch +) + +// Version represents one of the different types of versions used by gps. +// +// Version composes Constraint, because all versions can be used as a constraint +// (where they allow one, and only one, version - themselves), but constraints +// are not necessarily discrete versions. +// +// Version is an interface, but it contains private methods, which restricts it +// to gps's own internal implementations. We do this for the confluence of +// two reasons: the implementation of Versions is complete (there is no case in +// which we'd need other types), and the implementation relies on type magic +// under the hood, which would be unsafe to do if other dynamic types could be +// hiding behind the interface. +type Version interface { + Constraint + + // Indicates the type of version - Revision, Branch, Version, or Semver + Type() VersionType +} + +// PairedVersion represents a normal Version, but paired with its corresponding, +// underlying Revision. +type PairedVersion interface { + Version + + // Revision returns the immutable Revision that identifies this Version. + Revision() Revision + + // Unpair returns the surface-level UnpairedVersion that half of the pair. + // + // It does NOT modify the original PairedVersion + Unpair() UnpairedVersion + + // Ensures it is impossible to be both a PairedVersion and an + // UnpairedVersion + _pair(int) +} + +// UnpairedVersion represents a normal Version, with a method for creating a +// VersionPair by indicating the version's corresponding, underlying Revision. +type UnpairedVersion interface { + Version + // Pair takes the underlying Revision that this UnpairedVersion corresponds + // to and unites them into a PairedVersion. + Pair(Revision) PairedVersion + // Ensures it is impossible to be both a PairedVersion and an + // UnpairedVersion + _pair(bool) +} + +// types are weird +func (branchVersion) _pair(bool) {} +func (plainVersion) _pair(bool) {} +func (semVersion) _pair(bool) {} +func (versionPair) _pair(int) {} + +// NewBranch creates a new Version to represent a floating version (in +// general, a branch). +func NewBranch(body string) UnpairedVersion { + return branchVersion{ + name: body, + // We always set isDefault to false here, because the property is + // specifically designed to be internal-only: only the SourceManager + // gets to mark it. This is OK because nothing that client code is + // responsible for needs to care about has to touch it it. + // + // TODO(sdboyer) ...maybe. this just ugly. + isDefault: false, + } +} + +func newDefaultBranch(body string) UnpairedVersion { + return branchVersion{ + name: body, + isDefault: true, + } +} + +// NewVersion creates a Semver-typed Version if the provided version string is +// valid semver, and a plain/non-semver version if not. +func NewVersion(body string) UnpairedVersion { + sv, err := semver.NewVersion(body) + + if err != nil { + return plainVersion(body) + } + return semVersion{sv: sv} +} + +// A Revision represents an immutable versioning identifier. +type Revision string + +// String converts the Revision back into a string. +func (r Revision) String() string { + return string(r) +} + +// ImpliedCaretString follows the same rules as String(), but in accordance with +// the Constraint interface will always print a leading "=", as all Versions, +// when acting as a Constraint, act as exact matches. +func (r Revision) ImpliedCaretString() string { + return r.String() +} + +func (r Revision) typedString() string { + return "r-" + string(r) +} + +// Type indicates the type of version - for revisions, "revision". +func (r Revision) Type() VersionType { + return IsRevision +} + +// Matches is the Revision acting as a constraint; it checks to see if the provided +// version is the same Revision as itself. +func (r Revision) Matches(v Version) bool { + switch tv := v.(type) { + case versionTypeUnion: + return tv.Matches(r) + case Revision: + return r == tv + case versionPair: + return r == tv.r + } + + return false +} + +// MatchesAny is the Revision acting as a constraint; it checks to see if the provided +// version is the same Revision as itself. +func (r Revision) MatchesAny(c Constraint) bool { + switch tc := c.(type) { + case anyConstraint: + return true + case noneConstraint: + return false + case versionTypeUnion: + return tc.MatchesAny(r) + case Revision: + return r == tc + case versionPair: + return r == tc.r + } + + return false +} + +// Intersect computes the intersection of the Constraint with the provided +// Constraint. For Revisions, this can only be another, exactly equal +// Revision, or a PairedVersion whose underlying Revision is exactly equal. +func (r Revision) Intersect(c Constraint) Constraint { + switch tc := c.(type) { + case anyConstraint: + return r + case noneConstraint: + return none + case versionTypeUnion: + return tc.Intersect(r) + case Revision: + if r == tc { + return r + } + case versionPair: + if r == tc.r { + return r + } + } + + return none +} + +func (r Revision) identical(c Constraint) bool { + r2, ok := c.(Revision) + if !ok { + return false + } + return r == r2 +} + +func (r Revision) copyTo(msg *pb.Constraint) { + msg.Type = pb.Constraint_Revision + msg.Value = string(r) +} + +type branchVersion struct { + name string + isDefault bool +} + +func (v branchVersion) String() string { + return string(v.name) +} + +func (v branchVersion) ImpliedCaretString() string { + return v.String() +} + +func (v branchVersion) typedString() string { + return fmt.Sprintf("b-%s", v.String()) +} + +func (v branchVersion) Type() VersionType { + return IsBranch +} + +func (v branchVersion) Matches(v2 Version) bool { + switch tv := v2.(type) { + case versionTypeUnion: + return tv.Matches(v) + case branchVersion: + return v.name == tv.name + case versionPair: + if tv2, ok := tv.v.(branchVersion); ok { + return tv2.name == v.name + } + } + return false +} + +func (v branchVersion) MatchesAny(c Constraint) bool { + switch tc := c.(type) { + case anyConstraint: + return true + case noneConstraint: + return false + case versionTypeUnion: + return tc.MatchesAny(v) + case branchVersion: + return v.name == tc.name + case versionPair: + if tc2, ok := tc.v.(branchVersion); ok { + return tc2.name == v.name + } + } + + return false +} + +func (v branchVersion) Intersect(c Constraint) Constraint { + switch tc := c.(type) { + case anyConstraint: + return v + case noneConstraint: + return none + case versionTypeUnion: + return tc.Intersect(v) + case branchVersion: + if v.name == tc.name { + return v + } + case versionPair: + if tc2, ok := tc.v.(branchVersion); ok { + if v.name == tc2.name { + return v + } + } + } + + return none +} + +func (v branchVersion) Pair(r Revision) PairedVersion { + return versionPair{ + v: v, + r: r, + } +} + +func (v branchVersion) identical(c Constraint) bool { + v2, ok := c.(branchVersion) + if !ok { + return false + } + return v == v2 +} + +func (v branchVersion) copyTo(msg *pb.Constraint) { + if v.isDefault { + msg.Type = pb.Constraint_DefaultBranch + } else { + msg.Type = pb.Constraint_Branch + } + msg.Value = v.name +} + +type plainVersion string + +func (v plainVersion) String() string { + return string(v) +} + +func (v plainVersion) ImpliedCaretString() string { + return v.String() +} + +func (v plainVersion) typedString() string { + return fmt.Sprintf("pv-%s", v.String()) +} + +func (v plainVersion) Type() VersionType { + return IsVersion +} + +func (v plainVersion) Matches(v2 Version) bool { + switch tv := v2.(type) { + case versionTypeUnion: + return tv.Matches(v) + case plainVersion: + return v == tv + case versionPair: + if tv2, ok := tv.v.(plainVersion); ok { + return tv2 == v + } + } + return false +} + +func (v plainVersion) MatchesAny(c Constraint) bool { + switch tc := c.(type) { + case anyConstraint: + return true + case noneConstraint: + return false + case versionTypeUnion: + return tc.MatchesAny(v) + case plainVersion: + return v == tc + case versionPair: + if tc2, ok := tc.v.(plainVersion); ok { + return tc2 == v + } + } + + return false +} + +func (v plainVersion) Intersect(c Constraint) Constraint { + switch tc := c.(type) { + case anyConstraint: + return v + case noneConstraint: + return none + case versionTypeUnion: + return tc.Intersect(v) + case plainVersion: + if v == tc { + return v + } + case versionPair: + if tc2, ok := tc.v.(plainVersion); ok { + if v == tc2 { + return v + } + } + } + + return none +} + +func (v plainVersion) Pair(r Revision) PairedVersion { + return versionPair{ + v: v, + r: r, + } +} + +func (v plainVersion) identical(c Constraint) bool { + v2, ok := c.(plainVersion) + if !ok { + return false + } + return v == v2 +} + +func (v plainVersion) copyTo(msg *pb.Constraint) { + msg.Type = pb.Constraint_Version + msg.Value = string(v) +} + +type semVersion struct { + sv semver.Version +} + +func (v semVersion) String() string { + str := v.sv.Original() + if str == "" { + str = v.sv.String() + } + return str +} + +func (v semVersion) ImpliedCaretString() string { + return v.sv.ImpliedCaretString() +} + +func (v semVersion) typedString() string { + return fmt.Sprintf("sv-%s", v.String()) +} + +func (v semVersion) Type() VersionType { + return IsSemver +} + +func (v semVersion) Matches(v2 Version) bool { + switch tv := v2.(type) { + case versionTypeUnion: + return tv.Matches(v) + case semVersion: + return v.sv.Equal(tv.sv) + case versionPair: + if tv2, ok := tv.v.(semVersion); ok { + return tv2.sv.Equal(v.sv) + } + } + return false +} + +func (v semVersion) MatchesAny(c Constraint) bool { + switch tc := c.(type) { + case anyConstraint: + return true + case noneConstraint: + return false + case versionTypeUnion: + return tc.MatchesAny(v) + case semVersion: + return v.sv.Equal(tc.sv) + case semverConstraint: + return tc.Intersect(v) != none + case versionPair: + if tc2, ok := tc.v.(semVersion); ok { + return tc2.sv.Equal(v.sv) + } + } + + return false +} + +func (v semVersion) Intersect(c Constraint) Constraint { + switch tc := c.(type) { + case anyConstraint: + return v + case noneConstraint: + return none + case versionTypeUnion: + return tc.Intersect(v) + case semVersion: + if v.sv.Equal(tc.sv) { + return v + } + case semverConstraint: + return tc.Intersect(v) + case versionPair: + if tc2, ok := tc.v.(semVersion); ok { + if v.sv.Equal(tc2.sv) { + return v + } + } + } + + return none +} + +func (v semVersion) Pair(r Revision) PairedVersion { + return versionPair{ + v: v, + r: r, + } +} + +func (v semVersion) identical(c Constraint) bool { + v2, ok := c.(semVersion) + if !ok { + return false + } + return v == v2 +} + +func (v semVersion) copyTo(msg *pb.Constraint) { + msg.Type = pb.Constraint_Semver + msg.Value = v.String() //TODO better encoding which doesn't require re-parsing +} + +type versionPair struct { + v UnpairedVersion + r Revision +} + +func (v versionPair) String() string { + return v.v.String() +} + +func (v versionPair) ImpliedCaretString() string { + return v.v.ImpliedCaretString() +} + +func (v versionPair) typedString() string { + return fmt.Sprintf("%s-%s", v.Unpair().typedString(), v.Revision().typedString()) +} + +func (v versionPair) Type() VersionType { + return v.v.Type() +} + +func (v versionPair) Revision() Revision { + return v.r +} + +func (v versionPair) Unpair() UnpairedVersion { + return v.v +} + +func (v versionPair) Matches(v2 Version) bool { + switch tv2 := v2.(type) { + case versionTypeUnion: + return tv2.Matches(v) + case versionPair: + return v.r == tv2.r + case Revision: + return v.r == tv2 + } + + switch tv := v.v.(type) { + case plainVersion, branchVersion: + if tv.Matches(v2) { + return true + } + case semVersion: + if tv2, ok := v2.(semVersion); ok { + if tv.sv.Equal(tv2.sv) { + return true + } + } + } + + return false +} + +func (v versionPair) MatchesAny(c2 Constraint) bool { + return c2.Matches(v) +} + +func (v versionPair) Intersect(c2 Constraint) Constraint { + switch tc := c2.(type) { + case anyConstraint: + return v + case noneConstraint: + return none + case versionTypeUnion: + return tc.Intersect(v) + case versionPair: + if v.r == tc.r { + return v.r + } + case Revision: + if v.r == tc { + return v.r + } + case semverConstraint: + if tv, ok := v.v.(semVersion); ok { + if tc.Intersect(tv) == v.v { + return v + } + } + // If the semver intersection failed, we know nothing could work + return none + } + + switch tv := v.v.(type) { + case plainVersion, branchVersion: + if c2.Matches(v) { + return v + } + case semVersion: + if tv2, ok := c2.(semVersion); ok { + if tv.sv.Equal(tv2.sv) { + return v + } + } + } + + return none +} + +func (v versionPair) identical(c Constraint) bool { + v2, ok := c.(versionPair) + if !ok { + return false + } + if v.r != v2.r { + return false + } + return v.v.identical(v2.v) +} + +func (v versionPair) copyTo(*pb.Constraint) { + panic("versionPair should never be serialized; it is solver internal-only") +} + +// compareVersionType is a sort func helper that makes a coarse-grained sorting +// decision based on version type. +// +// Make sure that l and r have already been converted from versionPair (if +// applicable). +func compareVersionType(l, r Version) int { + // Big fugly double type switch. No reflect, because this can be smack in a hot loop + switch l.(type) { + case Revision: + switch r.(type) { + case Revision: + return 0 + case branchVersion, plainVersion, semVersion: + return 1 + } + + case plainVersion: + switch r.(type) { + case Revision: + return -1 + case plainVersion: + return 0 + case branchVersion, semVersion: + return 1 + } + + case branchVersion: + switch r.(type) { + case Revision, plainVersion: + return -1 + case branchVersion: + return 0 + case semVersion: + return 1 + } + + case semVersion: + switch r.(type) { + case Revision, branchVersion, plainVersion: + return -1 + case semVersion: + return 0 + } + } + panic("unknown version type") +} + +// SortForUpgrade sorts a slice of []Version in roughly descending order, so +// that presumably newer versions are visited first. The rules are: +// +// - All semver versions come first, and sort mostly according to the semver +// 2.0 spec (as implemented by github.com/Masterminds/semver lib), with one +// exception: +// - Semver versions with a prerelease are after *all* non-prerelease semver. +// Within this subset they are sorted first by their numerical component, then +// lexicographically by their prerelease version. +// - The default branch(es) is next; the exact semantics of that are specific +// to the underlying source. +// - All other branches come next, sorted lexicographically. +// - All non-semver versions (tags) are next, sorted lexicographically. +// - Revisions, if any, are last, sorted lexicographically. Revisions do not +// typically appear in version lists, so the only invariant we maintain is +// determinism - deeper semantics, like chronology or topology, do not matter. +// +// So, given a slice of the following versions: +// +// - Branch: master devel +// - Semver tags: v1.0.0, v1.1.0, v1.1.0-alpha1 +// - Non-semver tags: footag +// - Revision: f6e74e8d +// +// Sorting for upgrade will result in the following slice. +// +// [v1.1.0 v1.0.0 v1.1.0-alpha1 footag devel master f6e74e8d] +func SortForUpgrade(vl []Version) { + sort.Sort(upgradeVersionSorter(vl)) +} + +// SortPairedForUpgrade has the same behavior as SortForUpgrade, but operates on +// []PairedVersion types. +func SortPairedForUpgrade(vl []PairedVersion) { + sort.Sort(pvupgradeVersionSorter(vl)) +} + +// SortForDowngrade sorts a slice of []Version in roughly ascending order, so +// that presumably older versions are visited first. +// +// This is *not* the same as reversing SortForUpgrade (or you could simply +// sort.Reverse()). The type precedence is the same, including the semver vs. +// semver-with-prerelease relation. Lexicographical comparisons within +// non-semver tags, branches, and revisions remains the same as well; because we +// treat these domains as having no ordering relation, there can be no real +// concept of "upgrade" vs "downgrade", so there is no reason to reverse them. +// +// Thus, the only binary relation that is reversed for downgrade is within-type +// comparisons for semver. +// +// So, given a slice of the following versions: +// +// - Branch: master devel +// - Semver tags: v1.0.0, v1.1.0, v1.1.0-alpha1 +// - Non-semver tags: footag +// - Revision: f6e74e8d +// +// Sorting for downgrade will result in the following slice. +// +// [v1.0.0 v1.1.0 v1.1.0-alpha1 footag devel master f6e74e8d] +func SortForDowngrade(vl []Version) { + sort.Sort(downgradeVersionSorter(vl)) +} + +// SortPairedForDowngrade has the same behavior as SortForDowngrade, but +// operates on []PairedVersion types. +func SortPairedForDowngrade(vl []PairedVersion) { + sort.Sort(pvdowngradeVersionSorter(vl)) +} + +type upgradeVersionSorter []Version + +func (vs upgradeVersionSorter) Len() int { + return len(vs) +} + +func (vs upgradeVersionSorter) Swap(i, j int) { + vs[i], vs[j] = vs[j], vs[i] +} + +func (vs upgradeVersionSorter) Less(i, j int) bool { + l, r := vs[i], vs[j] + return vLess(l, r, false) +} + +type pvupgradeVersionSorter []PairedVersion + +func (vs pvupgradeVersionSorter) Len() int { + return len(vs) +} + +func (vs pvupgradeVersionSorter) Swap(i, j int) { + vs[i], vs[j] = vs[j], vs[i] +} +func (vs pvupgradeVersionSorter) Less(i, j int) bool { + l, r := vs[i], vs[j] + return vLess(l, r, false) +} + +type downgradeVersionSorter []Version + +func (vs downgradeVersionSorter) Len() int { + return len(vs) +} + +func (vs downgradeVersionSorter) Swap(i, j int) { + vs[i], vs[j] = vs[j], vs[i] +} + +func (vs downgradeVersionSorter) Less(i, j int) bool { + l, r := vs[i], vs[j] + return vLess(l, r, true) +} + +type pvdowngradeVersionSorter []PairedVersion + +func (vs pvdowngradeVersionSorter) Len() int { + return len(vs) +} + +func (vs pvdowngradeVersionSorter) Swap(i, j int) { + vs[i], vs[j] = vs[j], vs[i] +} +func (vs pvdowngradeVersionSorter) Less(i, j int) bool { + l, r := vs[i], vs[j] + return vLess(l, r, true) +} + +func vLess(l, r Version, down bool) bool { + if tl, ispair := l.(versionPair); ispair { + l = tl.v + } + if tr, ispair := r.(versionPair); ispair { + r = tr.v + } + + switch compareVersionType(l, r) { + case -1: + return true + case 1: + return false + case 0: + break + default: + panic("unreachable") + } + + switch tl := l.(type) { + case branchVersion: + tr := r.(branchVersion) + if tl.isDefault != tr.isDefault { + // If they're not both defaults, then return the left val: if left + // is the default, then it is "less" (true) b/c we want it earlier. + // Else the right is the default, and so the left should be later + // (false). + return tl.isDefault + } + return l.String() < r.String() + case Revision, plainVersion: + // All that we can do now is alpha sort + return l.String() < r.String() + } + + // This ensures that pre-release versions are always sorted after ALL + // full-release versions + lsv, rsv := l.(semVersion).sv, r.(semVersion).sv + lpre, rpre := lsv.Prerelease() == "", rsv.Prerelease() == "" + if (lpre && !rpre) || (!lpre && rpre) { + return lpre + } + + if down { + return lsv.LessThan(rsv) + } + return lsv.GreaterThan(rsv) +} + +func hidePair(pvl []PairedVersion) []Version { + vl := make([]Version, 0, len(pvl)) + for _, v := range pvl { + vl = append(vl, v) + } + return vl +} + +// VersionComponentStrings decomposes a Version into the underlying number, branch and revision +func VersionComponentStrings(v Version) (revision string, branch string, version string) { + switch tv := v.(type) { + case UnpairedVersion: + case Revision: + revision = tv.String() + case PairedVersion: + revision = tv.Revision().String() + } + + switch v.Type() { + case IsBranch: + branch = v.String() + case IsSemver, IsVersion: + version = v.String() + } + + return +} diff --git a/vendor/github.com/golang/dep/gps/version_queue.go b/vendor/github.com/golang/dep/gps/version_queue.go new file mode 100644 index 00000000..6e23ba4f --- /dev/null +++ b/vendor/github.com/golang/dep/gps/version_queue.go @@ -0,0 +1,158 @@ +// Copyright 2017 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 gps + +import ( + "fmt" + "strings" +) + +type failedVersion struct { + v Version + f error +} + +type versionQueue struct { + id ProjectIdentifier + pi []Version + lockv, prefv Version + fails []failedVersion + b sourceBridge + failed bool + allLoaded bool + adverr error +} + +func newVersionQueue(id ProjectIdentifier, lockv, prefv Version, b sourceBridge) (*versionQueue, error) { + vq := &versionQueue{ + id: id, + b: b, + } + + // Lock goes in first, if present + if lockv != nil { + vq.lockv = lockv + vq.pi = append(vq.pi, lockv) + } + + // Preferred version next + if prefv != nil { + vq.prefv = prefv + vq.pi = append(vq.pi, prefv) + } + + if len(vq.pi) == 0 { + var err error + vq.pi, err = vq.b.listVersions(vq.id) + if err != nil { + // TODO(sdboyer) pushing this error this early entails that we + // unconditionally deep scan (e.g. vendor), as well as hitting the + // network. + return nil, err + } + vq.allLoaded = true + } + + return vq, nil +} + +func (vq *versionQueue) current() Version { + if len(vq.pi) > 0 { + return vq.pi[0] + } + + return nil +} + +// advance moves the versionQueue forward to the next available version, +// recording the failure that eliminated the current version. +func (vq *versionQueue) advance(fail error) error { + // Nothing in the queue means...nothing in the queue, nicely enough + if vq.adverr != nil || len(vq.pi) == 0 { // should be a redundant check, but just in case + return vq.adverr + } + + // Record the fail reason and pop the queue + vq.fails = append(vq.fails, failedVersion{ + v: vq.pi[0], + f: fail, + }) + vq.pi = vq.pi[1:] + + // *now*, if the queue is empty, ensure all versions have been loaded + if len(vq.pi) == 0 { + if vq.allLoaded { + // This branch gets hit when the queue is first fully exhausted, + // after a previous advance() already called ListVersions(). + return nil + } + vq.allLoaded = true + + var vltmp []Version + vltmp, vq.adverr = vq.b.listVersions(vq.id) + if vq.adverr != nil { + return vq.adverr + } + // defensive copy - calling listVersions here means slice contents may + // be modified when removing prefv/lockv. + vq.pi = make([]Version, len(vltmp)) + copy(vq.pi, vltmp) + + // search for and remove lockv and prefv, in a pointer GC-safe manner + // + // could use the version comparator for binary search here to avoid + // O(n) each time...if it matters + var delkeys []int + for k, pi := range vq.pi { + if pi == vq.lockv || pi == vq.prefv { + delkeys = append(delkeys, k) + } + } + + for k, dk := range delkeys { + dk -= k + copy(vq.pi[dk:], vq.pi[dk+1:]) + // write nil to final position for GC safety + vq.pi[len(vq.pi)-1] = nil + vq.pi = vq.pi[:len(vq.pi)-1] + } + + if len(vq.pi) == 0 { + // If listing versions added nothing (new), then return now + return nil + } + } + + // We're finally sure that there's something in the queue. Remove the + // failure marker, as the current version may have failed, but the next one + // hasn't yet + vq.failed = false + + // If all have been loaded and the queue is empty, we're definitely out + // of things to try. Return empty, though, because vq semantics dictate + // that we don't explicitly indicate the end of the queue here. + return nil +} + +// isExhausted indicates whether or not the queue has definitely been exhausted, +// in which case it will return true. +// +// It may return false negatives - suggesting that there is more in the queue +// when a subsequent call to current() will be empty. Plan accordingly. +func (vq *versionQueue) isExhausted() bool { + if !vq.allLoaded { + return false + } + return len(vq.pi) == 0 +} + +func (vq *versionQueue) String() string { + var vs []string + + for _, v := range vq.pi { + vs = append(vs, v.String()) + } + return fmt.Sprintf("[%s]", strings.Join(vs, ", ")) +} diff --git a/vendor/github.com/golang/dep/gps/version_queue_test.go b/vendor/github.com/golang/dep/gps/version_queue_test.go new file mode 100644 index 00000000..b2ea8788 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/version_queue_test.go @@ -0,0 +1,259 @@ +// Copyright 2017 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 gps + +import ( + "testing" + + "github.com/pkg/errors" +) + +// just need a listVersions method +type fakeBridge struct { + *bridge + vl []Version +} + +var fakevl = []Version{ + NewVersion("v2.0.0").Pair("200rev"), + NewVersion("v1.1.1").Pair("111rev"), + NewVersion("v1.1.0").Pair("110rev"), + NewVersion("v1.0.0").Pair("100rev"), + NewBranch("master").Pair("masterrev"), +} + +func init() { + SortForUpgrade(fakevl) +} + +func (fb *fakeBridge) listVersions(id ProjectIdentifier) ([]Version, error) { + // it's a fixture, we only ever do the one, regardless of id + return fb.vl, nil +} + +type fakeFailBridge struct { + *bridge +} + +var errVQ = errors.New("vqerr") + +func (fb *fakeFailBridge) listVersions(id ProjectIdentifier) ([]Version, error) { + return nil, errVQ +} + +func TestVersionQueueSetup(t *testing.T) { + id := ProjectIdentifier{ProjectRoot: ProjectRoot("foo")}.normalize() + + // shouldn't even need to embed a real bridge + fb := &fakeBridge{vl: fakevl} + ffb := &fakeFailBridge{} + + _, err := newVersionQueue(id, nil, nil, ffb) + if err == nil { + t.Error("Expected err when providing no prefv or lockv, and injected bridge returns err from ListVersions()") + } + + vq, err := newVersionQueue(id, nil, nil, fb) + if err != nil { + t.Errorf("Unexpected err on vq create: %s", err) + } else { + if len(vq.pi) != 5 { + t.Errorf("Should have five versions from listVersions() when providing no prefv or lockv; got %v:\n\t%s", len(vq.pi), vq.String()) + } + if !vq.allLoaded { + t.Errorf("allLoaded flag should be set, but wasn't") + } + + if vq.prefv != nil || vq.lockv != nil { + t.Error("lockv and prefv should be nil") + } + if vq.current() != fakevl[0] { + t.Errorf("current should be head of fakevl (%s), got %s", fakevl[0], vq.current()) + } + } + + lockv := fakevl[0] + prefv := fakevl[1] + vq, err = newVersionQueue(id, lockv, nil, fb) + if err != nil { + t.Errorf("Unexpected err on vq create: %s", err) + } else { + if len(vq.pi) != 1 { + t.Errorf("Should have one version when providing only a lockv; got %v:\n\t%s", len(vq.pi), vq.String()) + } + if vq.allLoaded { + t.Errorf("allLoaded flag should not be set") + } + if vq.lockv != lockv { + t.Errorf("lockv should be %s, was %s", lockv, vq.lockv) + } + if vq.current() != lockv { + t.Errorf("current should be lockv (%s), got %s", lockv, vq.current()) + } + } + + vq, err = newVersionQueue(id, nil, prefv, fb) + if err != nil { + t.Errorf("Unexpected err on vq create: %s", err) + } else { + if len(vq.pi) != 1 { + t.Errorf("Should have one version when providing only a prefv; got %v:\n\t%s", len(vq.pi), vq.String()) + } + if vq.allLoaded { + t.Errorf("allLoaded flag should not be set") + } + if vq.prefv != prefv { + t.Errorf("prefv should be %s, was %s", prefv, vq.prefv) + } + if vq.current() != prefv { + t.Errorf("current should be prefv (%s), got %s", prefv, vq.current()) + } + } + + vq, err = newVersionQueue(id, lockv, prefv, fb) + if err != nil { + t.Errorf("Unexpected err on vq create: %s", err) + } else { + if len(vq.pi) != 2 { + t.Errorf("Should have two versions when providing both a prefv and lockv; got %v:\n\t%s", len(vq.pi), vq.String()) + } + if vq.allLoaded { + t.Errorf("allLoaded flag should not be set") + } + if vq.prefv != prefv { + t.Errorf("prefv should be %s, was %s", prefv, vq.prefv) + } + if vq.lockv != lockv { + t.Errorf("lockv should be %s, was %s", lockv, vq.lockv) + } + if vq.current() != lockv { + t.Errorf("current should be lockv (%s), got %s", lockv, vq.current()) + } + } +} + +func TestVersionQueueAdvance(t *testing.T) { + fb := &fakeBridge{vl: fakevl} + id := ProjectIdentifier{ProjectRoot: ProjectRoot("foo")}.normalize() + + // First with no prefv or lockv + vq, err := newVersionQueue(id, nil, nil, fb) + if err != nil { + t.Fatalf("Unexpected err on vq create: %s", err) + } + + for k, v := range fakevl[1:] { + err = vq.advance(errors.Errorf("advancment fail for %s", fakevl[k])) + if err != nil { + t.Errorf("error on advancing vq from %s to %s", fakevl[k], v) + break + } + + if vq.current() != v { + t.Errorf("on advance() %v, current should be %s, got %s", k, v, vq.current()) + } + } + + if vq.isExhausted() { + t.Error("should not be exhausted until advancing 'past' the end") + } + if err = vq.advance(errors.Errorf("final advance failure")); err != nil { + t.Errorf("should not error on advance, even past end, but got %s", err) + } + + if !vq.isExhausted() { + t.Error("advanced past end, should now report exhaustion") + } + if vq.current() != nil { + t.Error("advanced past end, current should return nil") + } + + // now, do one with both a prefv and lockv + lockv := fakevl[2] + prefv := fakevl[0] + vq, err = newVersionQueue(id, lockv, prefv, fb) + if err != nil { + t.Errorf("error creating version queue: %v", err) + } + if vq.String() != "[v1.1.0, v2.0.0]" { + t.Error("stringifying vq did not have expected outcome, got", vq.String()) + } + if vq.isExhausted() { + t.Error("can't be exhausted, we aren't even 'allLoaded' yet") + } + + err = vq.advance(errors.Errorf("dequeue lockv")) + if err != nil { + t.Error("unexpected error when advancing past lockv", err) + } else { + if vq.current() != prefv { + t.Errorf("current should be prefv (%s) after first advance, got %s", prefv, vq.current()) + } + if len(vq.pi) != 1 { + t.Errorf("should have just prefv elem left in vq, but there are %v:\n\t%s", len(vq.pi), vq.String()) + } + } + + err = vq.advance(errors.Errorf("dequeue prefv")) + if err != nil { + t.Error("unexpected error when advancing past prefv", err) + } else { + if !vq.allLoaded { + t.Error("allLoaded should now be true") + } + if len(vq.pi) != 3 { + t.Errorf("should have three remaining versions after removing prefv and lockv, but there are %v:\n\t%s", len(vq.pi), vq.String()) + } + if vq.current() != fakevl[1] { + t.Errorf("current should be first elem of fakevl (%s) after advancing into all, got %s", fakevl[1], vq.current()) + } + } + + // make sure the queue ordering is still right even with a double-delete + vq.advance(nil) + if vq.current() != fakevl[3] { + t.Errorf("second elem after ListVersions() should be idx 3 of fakevl (%s), got %s", fakevl[3], vq.current()) + } + vq.advance(nil) + if vq.current() != fakevl[4] { + t.Errorf("third elem after ListVersions() should be idx 4 of fakevl (%s), got %s", fakevl[4], vq.current()) + } + vq.advance(nil) + if vq.current() != nil || !vq.isExhausted() { + t.Error("should be out of versions in the queue") + } + + // Make sure we handle things correctly when listVersions adds nothing new + fb = &fakeBridge{vl: []Version{lockv, prefv}} + vq, err = newVersionQueue(id, lockv, prefv, fb) + if err != nil { + t.Errorf("error creating version queue: %v", err) + } + vq.advance(nil) + vq.advance(nil) + if vq.current() != nil || !vq.isExhausted() { + t.Errorf("should have no versions left, as ListVersions() added nothing new, but still have %s", vq.String()) + } + err = vq.advance(nil) + if err != nil { + t.Errorf("should be fine to advance on empty queue, per docs, but got err %s", err) + } + + // Also handle it well when advancing calls ListVersions() and it gets an + // error + vq, err = newVersionQueue(id, lockv, nil, &fakeFailBridge{}) + if err != nil { + t.Errorf("should not err on creation when preseeded with lockv, but got err %s", err) + } + err = vq.advance(nil) + if err == nil { + t.Error("advancing should trigger call to erroring bridge, but no err") + } + err = vq.advance(nil) + if err == nil { + t.Error("err should be stored for reuse on any subsequent calls") + } + +} diff --git a/vendor/github.com/golang/dep/gps/version_test.go b/vendor/github.com/golang/dep/gps/version_test.go new file mode 100644 index 00000000..3c68fe58 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/version_test.go @@ -0,0 +1,189 @@ +// Copyright 2017 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 gps + +import "testing" + +func TestVersionSorts(t *testing.T) { + rev := Revision("flooboofoobooo") + v1 := NewBranch("master").Pair(rev) + v2 := NewBranch("test").Pair(rev) + v3 := NewVersion("1.0.0").Pair(rev) + v4 := NewVersion("1.0.1").Pair(rev) + v5 := NewVersion("v2.0.5").Pair(rev) + v6 := NewVersion("2.0.5.2").Pair(rev) + v7 := newDefaultBranch("unwrapped").Pair(rev) + v8 := NewVersion("20.0.5.2").Pair(rev) + v9 := NewVersion("v1.5.5-beta.4").Pair(rev) + v10 := NewVersion("v3.0.1-alpha.1").Pair(rev) + + start := []Version{ + v1, + v2, + v3, + v4, + v5, + v6, + v7, + v8, + v9, + v10, + rev, + } + + down := make([]Version, len(start)) + copy(down, start) + up := make([]Version, len(start)) + copy(up, start) + + edown := []Version{ + v3, v4, v5, // semvers + v9, v10, // prerelease semver + v7, v1, v2, // floating/branches + v6, v8, // plain versions + rev, // revs + } + + eup := []Version{ + v5, v4, v3, // semvers + v10, v9, // prerelease semver + v7, v1, v2, // floating/branches + v6, v8, // plain versions + rev, // revs + } + + SortForUpgrade(up) + var wrong []int + for k, v := range up { + if eup[k] != v { + wrong = append(wrong, k) + t.Errorf("Expected version %s in position %v on upgrade sort, but got %s", eup[k], k, v) + } + } + if len(wrong) > 0 { + // Just helps with readability a bit + t.Errorf("Upgrade sort positions with wrong versions: %v", wrong) + } + + SortForDowngrade(down) + wrong = wrong[:0] + for k, v := range down { + if edown[k] != v { + wrong = append(wrong, k) + t.Errorf("Expected version %s in position %v on downgrade sort, but got %s", edown[k], k, v) + } + } + if len(wrong) > 0 { + // Just helps with readability a bit + t.Errorf("Downgrade sort positions with wrong versions: %v", wrong) + } + + // Now make sure we sort back the other way correctly...just because + SortForUpgrade(down) + wrong = wrong[:0] + for k, v := range down { + if eup[k] != v { + wrong = append(wrong, k) + t.Errorf("Expected version %s in position %v on down-then-upgrade sort, but got %s", eup[k], k, v) + } + } + if len(wrong) > 0 { + // Just helps with readability a bit + t.Errorf("Down-then-upgrade sort positions with wrong versions: %v", wrong) + } + + // Now make sure we sort back the other way correctly...just because + SortForDowngrade(up) + wrong = wrong[:0] + for k, v := range up { + if edown[k] != v { + wrong = append(wrong, k) + t.Errorf("Expected version %s in position %v on up-then-downgrade sort, but got %s", edown[k], k, v) + } + } + if len(wrong) > 0 { + // Just helps with readability a bit + t.Fatalf("Up-then-downgrade sort positions with wrong versions: %v", wrong) + } + + /////////// + // Repeat for PairedVersion slices & sorts + + pdown, pup := make([]PairedVersion, 0, len(start)), make([]PairedVersion, 0, len(start)) + for _, v := range start { + if _, ok := v.(Revision); ok { + continue + } + pdown = append(pdown, v.(PairedVersion)) + pup = append(pup, v.(PairedVersion)) + } + + pedown, peup := make([]PairedVersion, 0, len(edown)), make([]PairedVersion, 0, len(eup)) + for _, v := range edown { + if _, ok := v.(Revision); ok { + continue + } + pedown = append(pedown, v.(PairedVersion)) + } + for _, v := range eup { + if _, ok := v.(Revision); ok { + continue + } + peup = append(peup, v.(PairedVersion)) + } + + SortPairedForUpgrade(pup) + for k, v := range pup { + if peup[k] != v { + wrong = append(wrong, k) + t.Errorf("Expected version %s in position %v on upgrade sort, but got %s", peup[k], k, v) + } + } + if len(wrong) > 0 { + // Just helps with readability a bit + t.Errorf("Upgrade sort positions with wrong versions: %v", wrong) + } + + SortPairedForDowngrade(pdown) + wrong = wrong[:0] + for k, v := range pdown { + if pedown[k] != v { + wrong = append(wrong, k) + t.Errorf("Expected version %s in position %v on downgrade sort, but got %s", pedown[k], k, v) + } + } + if len(wrong) > 0 { + // Just helps with readability a bit + t.Errorf("Downgrade sort positions with wrong versions: %v", wrong) + } + + // Now make sure we sort back the other way correctly...just because + SortPairedForUpgrade(pdown) + wrong = wrong[:0] + for k, v := range pdown { + if peup[k] != v { + wrong = append(wrong, k) + t.Errorf("Expected version %s in position %v on down-then-upgrade sort, but got %s", peup[k], k, v) + } + } + if len(wrong) > 0 { + // Just helps with readability a bit + t.Errorf("Down-then-upgrade sort positions with wrong versions: %v", wrong) + } + + // Now make sure we sort back the other way correctly...just because + SortPairedForDowngrade(pup) + wrong = wrong[:0] + for k, v := range pup { + if pedown[k] != v { + wrong = append(wrong, k) + t.Errorf("Expected version %s in position %v on up-then-downgrade sort, but got %s", pedown[k], k, v) + } + } + if len(wrong) > 0 { + // Just helps with readability a bit + t.Errorf("Up-then-downgrade sort positions with wrong versions: %v", wrong) + } +} diff --git a/vendor/github.com/golang/dep/gps/version_unifier.go b/vendor/github.com/golang/dep/gps/version_unifier.go new file mode 100644 index 00000000..3698dc7e --- /dev/null +++ b/vendor/github.com/golang/dep/gps/version_unifier.go @@ -0,0 +1,302 @@ +// Copyright 2017 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 gps + +import "github.com/golang/dep/gps/internal/pb" + +// versionUnifier facilitates cross-type version comparison and set operations. +type versionUnifier struct { + b sourceBridge + mtr *metrics +} + +// pairVersion takes an UnpairedVersion and attempts to pair it with an +// underlying Revision in the context of the provided ProjectIdentifier by +// consulting the canonical version list. +func (vu versionUnifier) pairVersion(id ProjectIdentifier, v UnpairedVersion) PairedVersion { + vl, err := vu.b.listVersions(id) + if err != nil { + return nil + } + + vu.mtr.push("b-pair-version") + // doing it like this is a bit sloppy + for _, v2 := range vl { + if p, ok := v2.(PairedVersion); ok { + if p.Matches(v) { + vu.mtr.pop() + return p + } + } + } + + vu.mtr.pop() + return nil +} + +// pairRevision takes a Revision and attempts to pair it with all possible +// versionsby consulting the canonical version list of the provided +// ProjectIdentifier. +func (vu versionUnifier) pairRevision(id ProjectIdentifier, r Revision) []Version { + vl, err := vu.b.listVersions(id) + if err != nil { + return nil + } + + vu.mtr.push("b-pair-rev") + p := []Version{r} + // doing it like this is a bit sloppy + for _, v2 := range vl { + if pv, ok := v2.(PairedVersion); ok { + if pv.Matches(r) { + p = append(p, pv) + } + } + } + + vu.mtr.pop() + return p +} + +// matches performs a typical match check between the provided version and +// constraint. If that basic check fails and the provided version is incomplete +// (e.g. an unpaired version or bare revision), it will attempt to gather more +// information on one or the other and re-perform the comparison. +func (vu versionUnifier) matches(id ProjectIdentifier, c Constraint, v Version) bool { + if c.Matches(v) { + return true + } + + vu.mtr.push("b-matches") + // This approach is slightly wasteful, but just SO much less verbose, and + // more easily understood. + vtu := vu.createTypeUnion(id, v) + + var uc Constraint + if cv, ok := c.(Version); ok { + uc = vu.createTypeUnion(id, cv) + } else { + uc = c + } + + vu.mtr.pop() + return uc.Matches(vtu) +} + +// matchesAny is the authoritative version of Constraint.MatchesAny. +func (vu versionUnifier) matchesAny(id ProjectIdentifier, c1, c2 Constraint) bool { + if c1.MatchesAny(c2) { + return true + } + + vu.mtr.push("b-matches-any") + // This approach is slightly wasteful, but just SO much less verbose, and + // more easily understood. + var uc1, uc2 Constraint + if v1, ok := c1.(Version); ok { + uc1 = vu.createTypeUnion(id, v1) + } else { + uc1 = c1 + } + + if v2, ok := c2.(Version); ok { + uc2 = vu.createTypeUnion(id, v2) + } else { + uc2 = c2 + } + + vu.mtr.pop() + return uc1.MatchesAny(uc2) +} + +// intersect is the authoritative version of Constraint.Intersect. +func (vu versionUnifier) intersect(id ProjectIdentifier, c1, c2 Constraint) Constraint { + rc := c1.Intersect(c2) + if rc != none { + return rc + } + + vu.mtr.push("b-intersect") + // This approach is slightly wasteful, but just SO much less verbose, and + // more easily understood. + var uc1, uc2 Constraint + if v1, ok := c1.(Version); ok { + uc1 = vu.createTypeUnion(id, v1) + } else { + uc1 = c1 + } + + if v2, ok := c2.(Version); ok { + uc2 = vu.createTypeUnion(id, v2) + } else { + uc2 = c2 + } + + vu.mtr.pop() + return uc1.Intersect(uc2) +} + +// createTypeUnion creates a versionTypeUnion for the provided version. +// +// This union may (and typically will) end up being nothing more than the single +// input version, but creating a versionTypeUnion guarantees that 'local' +// constraint checks (direct method calls) are authoritative. +func (vu versionUnifier) createTypeUnion(id ProjectIdentifier, v Version) versionTypeUnion { + switch tv := v.(type) { + case Revision: + return versionTypeUnion(vu.pairRevision(id, tv)) + case PairedVersion: + return versionTypeUnion(vu.pairRevision(id, tv.Revision())) + case UnpairedVersion: + pv := vu.pairVersion(id, tv) + if pv == nil { + return versionTypeUnion{tv} + } + + return versionTypeUnion(vu.pairRevision(id, pv.Revision())) + } + + return nil +} + +// versionTypeUnion represents a set of versions that are, within the scope of +// this solver run, equivalent. +// +// The simple case here is just a pair - a normal version plus its underlying +// revision - but if a tag or branch point at the same rev, then we consider +// them equivalent. Again, however, this equivalency is short-lived; it must be +// re-assessed during every solver run. +// +// The union members are treated as being OR'd together: all constraint +// operations attempt each member, and will take the most open/optimistic +// answer. +// +// This technically does allow tags to match branches - something we otherwise +// try hard to avoid - but because the original input constraint never actually +// changes (and is never written out in the Solution), there's no harmful case +// of a user suddenly riding a branch when they expected a fixed tag. +type versionTypeUnion []Version + +// This should generally not be called, but is required for the interface. If it +// is called, we have a bigger problem (the type has escaped the solver); thus, +// panic. +func (vtu versionTypeUnion) String() string { + panic("versionTypeUnion should never be turned into a string; it is solver internal-only") +} + +// This should generally not be called, but is required for the interface. If it +// is called, we have a bigger problem (the type has escaped the solver); thus, +// panic. +func (vtu versionTypeUnion) ImpliedCaretString() string { + panic("versionTypeUnion should never be turned into a string; it is solver internal-only") +} + +func (vtu versionTypeUnion) typedString() string { + panic("versionTypeUnion should never be turned into a string; it is solver internal-only") +} + +// This should generally not be called, but is required for the interface. If it +// is called, we have a bigger problem (the type has escaped the solver); thus, +// panic. +func (vtu versionTypeUnion) Type() VersionType { + panic("versionTypeUnion should never need to answer a Type() call; it is solver internal-only") +} + +// Matches takes a version, and returns true if that version matches any version +// contained in the union. +// +// This DOES allow tags to match branches, albeit indirectly through a revision. +func (vtu versionTypeUnion) Matches(v Version) bool { + vtu2, otherIs := v.(versionTypeUnion) + + for _, v1 := range vtu { + if otherIs { + for _, v2 := range vtu2 { + if v1.Matches(v2) { + return true + } + } + } else if v1.Matches(v) { + return true + } + } + + return false +} + +// MatchesAny returns true if any of the contained versions (which are also +// constraints) in the union successfully MatchAny with the provided +// constraint. +func (vtu versionTypeUnion) MatchesAny(c Constraint) bool { + vtu2, otherIs := c.(versionTypeUnion) + + for _, v1 := range vtu { + if otherIs { + for _, v2 := range vtu2 { + if v1.MatchesAny(v2) { + return true + } + } + } else if v1.MatchesAny(c) { + return true + } + } + + return false +} + +// Intersect takes a constraint, and attempts to intersect it with all the +// versions contained in the union until one returns non-none. If that never +// happens, then none is returned. +// +// In order to avoid weird version floating elsewhere in the solver, the union +// always returns the input constraint. (This is probably obviously correct, but +// is still worth noting.) +func (vtu versionTypeUnion) Intersect(c Constraint) Constraint { + vtu2, otherIs := c.(versionTypeUnion) + + for _, v1 := range vtu { + if otherIs { + for _, v2 := range vtu2 { + if rc := v1.Intersect(v2); rc != none { + return rc + } + } + } else if rc := v1.Intersect(c); rc != none { + return rc + } + } + + return none +} + +func (vtu versionTypeUnion) identical(c Constraint) bool { + vtu2, ok := c.(versionTypeUnion) + if !ok { + return false + } + if len(vtu) != len(vtu2) { + return false + } + used := make([]bool, len(vtu)) +outter: + for _, v := range vtu { + for i, v2 := range vtu2 { + if used[i] { + continue + } + if v.identical(v2) { + used[i] = true + continue outter + } + } + return false + } + return true +} + +func (vtu versionTypeUnion) copyTo(*pb.Constraint) { + panic("versionTypeUnion should never be serialized; it is solver internal-only") +} diff --git a/vendor/github.com/golang/dep/gps/version_unifier_test.go b/vendor/github.com/golang/dep/gps/version_unifier_test.go new file mode 100644 index 00000000..741cb300 --- /dev/null +++ b/vendor/github.com/golang/dep/gps/version_unifier_test.go @@ -0,0 +1,142 @@ +// Copyright 2017 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 gps + +import ( + "testing" + + "github.com/golang/dep/gps/pkgtree" +) + +type lvFixBridge []Version + +var lvfb1 lvFixBridge + +func init() { + rev1 := Revision("revision-one") + rev2 := Revision("revision-two") + rev3 := Revision("revision-three") + + lvfb1 = lvFixBridge{ + NewBranch("master").Pair(rev1), + NewBranch("test").Pair(rev2), + NewVersion("1.0.0").Pair(rev1), + NewVersion("1.0.1").Pair("other1"), + NewVersion("v2.0.5").Pair(rev3), + NewVersion("2.0.5.2").Pair(rev3), + newDefaultBranch("unwrapped").Pair(rev3), + NewVersion("20.0.5.2").Pair(rev1), + NewVersion("v1.5.5-beta.4").Pair("other2"), + NewVersion("v3.0.1-alpha.1").Pair(rev2), + } +} + +func (lb lvFixBridge) listVersions(ProjectIdentifier) ([]Version, error) { + return lb, nil +} + +func TestCreateTyepUnion(t *testing.T) { + vu := versionUnifier{ + b: lvfb1, + mtr: newMetrics(), + } + + rev1 := Revision("revision-one") + rev2 := Revision("revision-two") + id := mkPI("irrelevant") + + vtu := vu.createTypeUnion(id, rev1) + if len(vtu) != 4 { + t.Fatalf("wanted a type union with four elements, got %v: \n%#v", len(vtu), vtu) + } + + vtu = vu.createTypeUnion(id, NewBranch("master")) + if len(vtu) != 4 { + t.Fatalf("wanted a type union with four elements, got %v: \n%#v", len(vtu), vtu) + } + + vtu = vu.createTypeUnion(id, Revision("notexist")) + if len(vtu) != 1 { + t.Fatalf("wanted a type union with one elements, got %v: \n%#v", len(vtu), vtu) + } + + vtu = vu.createTypeUnion(id, rev2) + if len(vtu) != 3 { + t.Fatalf("wanted a type union with three elements, got %v: \n%#v", len(vtu), vtu) + } + + vtu = vu.createTypeUnion(id, nil) + if vtu != nil { + t.Fatalf("wanted a nil return on nil input, got %#v", vtu) + } +} + +func TestTypeUnionIntersect(t *testing.T) { + vu := versionUnifier{ + b: lvfb1, + mtr: newMetrics(), + } + + rev1 := Revision("revision-one") + rev2 := Revision("revision-two") + rev3 := Revision("revision-three") + id := mkPI("irrelevant") + + c, _ := NewSemverConstraint("^2.0.0") + gotc := vu.intersect(id, rev2, c) + if gotc != none { + t.Fatalf("wanted empty set from intersect, got %#v", gotc) + } + + gotc = vu.intersect(id, c, rev1) + if gotc != none { + t.Fatalf("wanted empty set from intersect, got %#v", gotc) + } + + gotc = vu.intersect(id, c, rev3) + if gotc != NewVersion("v2.0.5").Pair(rev3) { + t.Fatalf("wanted v2.0.5, got %s from intersect", gotc.typedString()) + } +} + +func (lb lvFixBridge) SourceExists(ProjectIdentifier) (bool, error) { + panic("not implemented") +} + +func (lb lvFixBridge) SyncSourceFor(ProjectIdentifier) error { + panic("not implemented") +} + +func (lb lvFixBridge) RevisionPresentIn(ProjectIdentifier, Revision) (bool, error) { + panic("not implemented") +} + +func (lb lvFixBridge) ListPackages(ProjectIdentifier, Version) (pkgtree.PackageTree, error) { + panic("not implemented") +} + +func (lb lvFixBridge) GetManifestAndLock(ProjectIdentifier, Version, ProjectAnalyzer) (Manifest, Lock, error) { + panic("not implemented") +} + +func (lb lvFixBridge) ExportProject(ProjectIdentifier, Version, string) error { + panic("not implemented") +} + +func (lb lvFixBridge) DeduceProjectRoot(ip string) (ProjectRoot, error) { + panic("not implemented") +} + +func (lb lvFixBridge) verifyRootDir(path string) error { + panic("not implemented") +} + +func (lb lvFixBridge) vendorCodeExists(ProjectIdentifier) (bool, error) { + panic("not implemented") +} + +func (lb lvFixBridge) breakLock() { + panic("not implemented") +} diff --git a/vendor/github.com/golang/dep/hack/build-all.bash b/vendor/github.com/golang/dep/hack/build-all.bash new file mode 100755 index 00000000..05297508 --- /dev/null +++ b/vendor/github.com/golang/dep/hack/build-all.bash @@ -0,0 +1,41 @@ +#!/usr/bin/env bash +# Copyright 2017 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. +# +# This script will build dep and calculate hash for each +# (DEP_BUILD_PLATFORMS, DEP_BUILD_ARCHS) pair. +# DEP_BUILD_PLATFORMS="linux" DEP_BUILD_ARCHS="amd64" ./hack/build-all.sh +# can be called to build only for linux-amd64 + +set -e + +VERSION=$(git describe --tags --dirty) +COMMIT_HASH=$(git rev-parse --short HEAD 2>/dev/null) +DATE=$(date "+%Y-%m-%d") + +GO_BUILD_CMD="go build -a -installsuffix cgo" +GO_BUILD_LDFLAGS="-s -w -X main.commitHash=$COMMIT_HASH -X main.buildDate=$DATE -X main.version=$VERSION" + +if [ -z "$DEP_BUILD_PLATFORMS" ]; then + DEP_BUILD_PLATFORMS="linux windows darwin freebsd" +fi + +if [ -z "$DEP_BUILD_ARCHS" ]; then + DEP_BUILD_ARCHS="amd64 386" +fi + +mkdir -p release + +for OS in ${DEP_BUILD_PLATFORMS[@]}; do + for ARCH in ${DEP_BUILD_ARCHS[@]}; do + NAME="dep-$OS-$ARCH" + if [ "$OS" == "windows" ]; then + NAME="$NAME.exe" + fi + echo "Building for $OS/$ARCH" + GOARCH=$ARCH GOOS=$OS CGO_ENABLED=0 $GO_BUILD_CMD -ldflags "$GO_BUILD_LDFLAGS"\ + -o "release/$NAME" ./cmd/dep/ + shasum -a 256 "release/$NAME" > "release/$NAME".sha256 + done +done diff --git a/vendor/github.com/golang/dep/hack/coverage.bash b/vendor/github.com/golang/dep/hack/coverage.bash new file mode 100755 index 00000000..6ad89d9f --- /dev/null +++ b/vendor/github.com/golang/dep/hack/coverage.bash @@ -0,0 +1,16 @@ +#!/usr/bin/env bash +# Copyright 2017 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. +# +# This script will generate coverage.txt +set -e + +PKGS=$(go list ./... | grep -v /vendor/) +for pkg in $PKGS; do + go test -race -coverprofile=profile.out -covermode=atomic $pkg + if [[ -f profile.out ]]; then + cat profile.out >> coverage.txt + rm profile.out + fi +done diff --git a/vendor/github.com/golang/dep/hack/licenseok/main.go b/vendor/github.com/golang/dep/hack/licenseok/main.go new file mode 100644 index 00000000..f47c7715 --- /dev/null +++ b/vendor/github.com/golang/dep/hack/licenseok/main.go @@ -0,0 +1,201 @@ +// Copyright 2017 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. + +// Checks if all files have the license header, a lot of this is based off +// https://github.com/google/addlicense. +package main + +import ( + "bytes" + "flag" + "fmt" + "io/ioutil" + "log" + "os" + "path/filepath" + "sync" + "time" +) + +const helpText = `Usage: licenseok [flags] pattern [pattern ...] +This program ensures source code files have copyright license headers +by scanning directory patterns recursively. +The pattern argument can be provided multiple times, and may also refer +to single files. +Flags: +` + +const tmpl = `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.` + +var ( + update bool +) + +type file struct { + path string + mode os.FileMode +} + +func init() { + flag.BoolVar(&update, "u", false, "modifies all source files in place and avoids adding a license header to any file that already has one.") + + flag.Usage = func() { + fmt.Fprintln(os.Stderr, helpText) + flag.PrintDefaults() + } + + flag.Parse() + + if flag.NArg() == 0 { + flag.Usage() + os.Exit(1) + } +} + +func main() { + exitStatus := 0 + + // process at most 1000 files in parallel + ch := make(chan *file, 1000) + done := make(chan struct{}) + go func() { + var wg sync.WaitGroup + for f := range ch { + wg.Add(1) + go func(f *file) { + b, err := ioutil.ReadFile(f.path) + if err != nil { + log.Printf("%s: %v", f.path, err) + exitStatus = 1 + } + + if !hasLicense(b) { + if !update { + fmt.Fprintln(os.Stderr, f.path) + exitStatus = 1 + } else { + fmt.Fprintln(os.Stdout, f.path) + if err := addLicense(b, f.path, f.mode); err != nil { + log.Printf("%s: %v", f.path, err) + exitStatus = 1 + } + } + } + + wg.Done() + }(f) + } + wg.Wait() + close(done) + }() + + for _, d := range flag.Args() { + walk(ch, d) + } + close(ch) + <-done + os.Exit(exitStatus) +} + +func walk(ch chan<- *file, start string) { + filepath.Walk(start, func(path string, fi os.FileInfo, err error) error { + if err != nil { + log.Printf("%s error: %v", path, err) + return nil + } + if fi.IsDir() { + return nil + } + ch <- &file{path, fi.Mode()} + return nil + }) +} + +func addLicense(b []byte, path string, fmode os.FileMode) error { + var lic []byte + var err error + switch filepath.Ext(path) { + default: + return nil + case ".c", ".h": + lic, err = prefix("/*", " * ", " */") + case ".js", ".css": + lic, err = prefix("/**", " * ", " */") + case ".cc", ".cpp", ".cs", ".go", ".hh", ".hpp", ".java", ".m", ".mm", ".proto", ".rs", ".scala", ".swift", ".dart": + lic, err = prefix("", "// ", "") + case ".py", ".sh": + lic, err = prefix("", "# ", "") + case ".el", ".lisp": + lic, err = prefix("", ";; ", "") + case ".erl": + lic, err = prefix("", "% ", "") + case ".hs": + lic, err = prefix("", "-- ", "") + case ".html", ".xml": + lic, err = prefix("") + case ".php": + lic, err = prefix("") + } + if err != nil || lic == nil { + return err + } + + line := hashBang(b) + if len(line) > 0 { + b = b[len(line):] + if line[len(line)-1] != '\n' { + line = append(line, '\n') + } + lic = append(line, lic...) + } + b = append(lic, b...) + return ioutil.WriteFile(path, b, fmode) +} + +func hashBang(b []byte) []byte { + var line []byte + for _, c := range b { + line = append(line, c) + if c == '\n' { + break + } + } + if bytes.HasPrefix(line, []byte("#!")) { + return line + } + return nil +} + +func hasLicense(b []byte) bool { + n := 100 + if len(b) < 100 { + n = len(b) + } + return bytes.Contains(bytes.ToLower(b[:n]), []byte("copyright")) +} + +// prefix will execute a license template and prefix the result with top, middle and bottom. +func prefix(top, mid, bot string) ([]byte, error) { + buf := bytes.NewBufferString(fmt.Sprintf("Copyright %d %s", time.Now().Year(), tmpl)) + var out bytes.Buffer + if top != "" { + out.WriteString(top) + out.WriteRune('\n') + } + out.WriteString(mid) + for _, c := range buf.Bytes() { + out.WriteByte(c) + if c == '\n' { + out.WriteString(mid) + } + } + if bot != "" { + out.WriteRune('\n') + out.WriteString(bot) + } + out.Write([]byte{'\n', '\n'}) + return out.Bytes(), nil +} diff --git a/vendor/github.com/golang/dep/hack/lint.bash b/vendor/github.com/golang/dep/hack/lint.bash new file mode 100755 index 00000000..c474d6b7 --- /dev/null +++ b/vendor/github.com/golang/dep/hack/lint.bash @@ -0,0 +1,12 @@ +#!/usr/bin/env bash +# Copyright 2017 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. +# +# This script will validate code with various linters +set -e + +PKGS=$(go list ./... | grep -vF /vendor/) +go vet $PKGS +golint $PKGS +megacheck -unused.exported -ignore "github.com/golang/dep/internal/test/test.go:U1000 github.com/golang/dep/gps/prune.go:U1000 github.com/golang/dep/manifest.go:U1000" $PKGS diff --git a/vendor/github.com/golang/dep/hack/validate-gofmt.bash b/vendor/github.com/golang/dep/hack/validate-gofmt.bash new file mode 100755 index 00000000..a5ee7fa8 --- /dev/null +++ b/vendor/github.com/golang/dep/hack/validate-gofmt.bash @@ -0,0 +1,38 @@ +#!/usr/bin/env bash +# Copyright 2017 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. +# +# This script will validate that `go fmt` has been ran +# and is passing for certain directories in the project. +# +# Here we use `go list` to help determine which packages +# we need to check for `go fmt` +# +# EXIT 0 - The check is successful +# EXIT 1 - The check has failed + +PKGS=$(go list ./... | grep -v /vendor/) +REPO_TLD="github.com/golang/dep" +IGNORE_PKGS=". ./gps" + +for PKG in $PKGS; do + RELATIVE_PATH="${PKG/$REPO_TLD/.}" + i=0 + for IGNORE_PKG in $IGNORE_PKGS; do + if [ "${IGNORE_PKG}" == $RELATIVE_PATH ]; then + i=1 + fi + done; + if [ $i -eq 1 ]; then + continue + fi + + echo "Processing gofmt for: ${PKG}" + gofmt -s -l $RELATIVE_PATH + if [ $? -ne 0 ]; then + echo "GO FMT FAILURE: ${PKG}" + exit 1 + fi +done; +exit 0 diff --git a/vendor/github.com/golang/dep/hack/validate-licence.bash b/vendor/github.com/golang/dep/hack/validate-licence.bash new file mode 100755 index 00000000..dcf1c7ed --- /dev/null +++ b/vendor/github.com/golang/dep/hack/validate-licence.bash @@ -0,0 +1,12 @@ +#!/usr/bin/env bash +# Copyright 2017 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. +# +# This script will build licenseok and run it on all +# source files to check licence +set -e + +go build ./hack/licenseok +find . -path ./vendor -prune -o -regex ".+\.pb\.go$" -prune -o -type f -regex ".*\.\(go\|proto\)$"\ + -printf '%P\n' | xargs ./licenseok diff --git a/vendor/github.com/golang/dep/hack/validate-vendor.bash b/vendor/github.com/golang/dep/hack/validate-vendor.bash new file mode 100755 index 00000000..d6fb2bf5 --- /dev/null +++ b/vendor/github.com/golang/dep/hack/validate-vendor.bash @@ -0,0 +1,53 @@ +#!/usr/bin/env bash +# Copyright 2017 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. +# +# This script checks if we changed anything with regard to dependency management +# for our repo and makes sure that it was done in a valid way. + +set -e -o pipefail + +if [ -z "$VALIDATE_UPSTREAM" ]; then + VALIDATE_REPO='https://github.com/golang/dep.git' + VALIDATE_BRANCH='master' + + VALIDATE_HEAD="$(git rev-parse --verify HEAD)" + + git fetch -q "$VALIDATE_REPO" "refs/heads/$VALIDATE_BRANCH" + VALIDATE_UPSTREAM="$(git rev-parse --verify FETCH_HEAD)" + + VALIDATE_COMMIT_DIFF="$VALIDATE_UPSTREAM...$VALIDATE_HEAD" + + validate_diff() { + if [ "$VALIDATE_UPSTREAM" != "$VALIDATE_HEAD" ]; then + git diff "$VALIDATE_COMMIT_DIFF" "$@" + fi + } +fi + +IFS=$'\n' +files=( $(validate_diff --diff-filter=ACMR --name-only -- 'Gopkg.toml' 'Gopkg.lock' 'vendor/' || true) ) +unset IFS + +if [ ${#files[@]} -gt 0 ]; then + go build ./cmd/dep + ./dep ensure -vendor-only + # Let see if the working directory is clean + diffs="$(git status --porcelain -- vendor Gopkg.toml Gopkg.lock 2>/dev/null)" + if [ "$diffs" ]; then + { + echo 'The contents of vendor differ after "dep ensure":' + echo + echo "$diffs" + echo + echo 'Make sure these commands have been run before committing.' + echo + } >&2 + false + else + echo 'Congratulations! All vendoring changes are done the right way.' + fi +else + echo 'No vendor changes in diff.' +fi diff --git a/vendor/github.com/golang/dep/internal/feedback/feedback.go b/vendor/github.com/golang/dep/internal/feedback/feedback.go new file mode 100644 index 00000000..7084b9b9 --- /dev/null +++ b/vendor/github.com/golang/dep/internal/feedback/feedback.go @@ -0,0 +1,117 @@ +// Copyright 2017 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 feedback + +import ( + "encoding/hex" + "fmt" + "log" + + "github.com/golang/dep/gps" +) + +const ( + // ConsTypeConstraint represents a constraint + ConsTypeConstraint = "constraint" + + // ConsTypeHint represents a constraint type hint + ConsTypeHint = "hint" + + // DepTypeDirect represents a direct dependency + DepTypeDirect = "direct dep" + + // DepTypeTransitive represents a transitive dependency, + // or a dependency of a dependency + DepTypeTransitive = "transitive dep" + + // DepTypeImported represents a dependency imported by an external tool + DepTypeImported = "imported dep" +) + +// ConstraintFeedback holds project constraint feedback data +type ConstraintFeedback struct { + Constraint, LockedVersion, Revision, ConstraintType, DependencyType, ProjectPath string +} + +// NewConstraintFeedback builds a feedback entry for a constraint in the manifest. +func NewConstraintFeedback(pc gps.ProjectConstraint, depType string) *ConstraintFeedback { + cf := &ConstraintFeedback{ + Constraint: pc.Constraint.String(), + ProjectPath: string(pc.Ident.ProjectRoot), + DependencyType: depType, + } + + if _, ok := pc.Constraint.(gps.Revision); ok { + cf.ConstraintType = ConsTypeHint + } else { + cf.ConstraintType = ConsTypeConstraint + } + + return cf +} + +// NewLockedProjectFeedback builds a feedback entry for a project in the lock. +func NewLockedProjectFeedback(lp gps.LockedProject, depType string) *ConstraintFeedback { + cf := &ConstraintFeedback{ + ProjectPath: string(lp.Ident().ProjectRoot), + DependencyType: depType, + } + + switch vt := lp.Version().(type) { + case gps.PairedVersion: + cf.LockedVersion = vt.String() + cf.Revision = vt.Revision().String() + case gps.UnpairedVersion: // Logically this should never occur, but handle for completeness sake + cf.LockedVersion = vt.String() + case gps.Revision: + cf.Revision = vt.String() + } + + return cf +} + +// LogFeedback logs feedback on changes made to the manifest or lock. +func (cf ConstraintFeedback) LogFeedback(logger *log.Logger) { + if cf.Constraint != "" { + logger.Printf(" %v", GetUsingFeedback(cf.Constraint, cf.ConstraintType, cf.DependencyType, cf.ProjectPath)) + } + if cf.Revision != "" { + logger.Printf(" %v", GetLockingFeedback(cf.LockedVersion, cf.Revision, cf.DependencyType, cf.ProjectPath)) + } +} + +// GetUsingFeedback returns a dependency "using" feedback message. For example: +// +// Using ^1.0.0 as constraint for direct dep github.com/foo/bar +// Using 1b8edb3 as hint for direct dep github.com/bar/baz +func GetUsingFeedback(version, consType, depType, projectPath string) string { + if depType == DepTypeImported { + return fmt.Sprintf("Using %s as initial %s for %s %s", version, consType, depType, projectPath) + } + return fmt.Sprintf("Using %s as %s for %s %s", version, consType, depType, projectPath) +} + +// GetLockingFeedback returns a dependency "locking" feedback message. For +// example: +// +// Locking in v1.1.4 (bc29b4f) for direct dep github.com/foo/bar +// Locking in master (436f39d) for transitive dep github.com/baz/qux +func GetLockingFeedback(version, revision, depType, projectPath string) string { + // Check if it's a valid SHA1 digest and trim to 7 characters. + if len(revision) == 40 { + if _, err := hex.DecodeString(revision); err == nil { + // Valid SHA1 digest + revision = revision[0:7] + } + } + + if depType == DepTypeImported { + if version == "" { + version = "*" + } + return fmt.Sprintf("Trying %s (%s) as initial lock for %s %s", version, revision, depType, projectPath) + } + return fmt.Sprintf("Locking in %s (%s) for %s %s", version, revision, depType, projectPath) +} diff --git a/vendor/github.com/golang/dep/internal/feedback/feedback_test.go b/vendor/github.com/golang/dep/internal/feedback/feedback_test.go new file mode 100644 index 00000000..9b7d0216 --- /dev/null +++ b/vendor/github.com/golang/dep/internal/feedback/feedback_test.go @@ -0,0 +1,95 @@ +// Copyright 2017 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 feedback + +import ( + "bytes" + log2 "log" + "strings" + "testing" + + "github.com/golang/dep/gps" + _ "github.com/golang/dep/internal/test" // DO NOT REMOVE, allows go test ./... -update to work +) + +func TestFeedback_Constraint(t *testing.T) { + ver, _ := gps.NewSemverConstraint("^1.0.0") + rev := gps.Revision("1b8edb3") + pi := gps.ProjectIdentifier{ProjectRoot: gps.ProjectRoot("github.com/foo/bar")} + + cases := []struct { + feedback *ConstraintFeedback + want string + }{ + { + feedback: NewConstraintFeedback(gps.ProjectConstraint{Constraint: ver, Ident: pi}, DepTypeDirect), + want: "Using ^1.0.0 as constraint for direct dep github.com/foo/bar", + }, + { + feedback: NewConstraintFeedback(gps.ProjectConstraint{Constraint: ver, Ident: pi}, DepTypeImported), + want: "Using ^1.0.0 as initial constraint for imported dep github.com/foo/bar", + }, + { + feedback: NewConstraintFeedback(gps.ProjectConstraint{Constraint: gps.Any(), Ident: pi}, DepTypeImported), + want: "Using * as initial constraint for imported dep github.com/foo/bar", + }, + { + feedback: NewConstraintFeedback(gps.ProjectConstraint{Constraint: rev, Ident: pi}, DepTypeDirect), + want: "Using 1b8edb3 as hint for direct dep github.com/foo/bar", + }, + { + feedback: NewConstraintFeedback(gps.ProjectConstraint{Constraint: rev, Ident: pi}, DepTypeImported), + want: "Using 1b8edb3 as initial hint for imported dep github.com/foo/bar", + }, + } + + for _, c := range cases { + buf := &bytes.Buffer{} + log := log2.New(buf, "", 0) + c.feedback.LogFeedback(log) + got := strings.TrimSpace(buf.String()) + if c.want != got { + t.Errorf("Feedbacks are not expected: \n\t(GOT) '%s'\n\t(WNT) '%s'", got, c.want) + } + } +} + +func TestFeedback_LockedProject(t *testing.T) { + v := gps.NewVersion("v1.1.4").Pair("bc29b4f") + b := gps.NewBranch("master").Pair("436f39d") + pi := gps.ProjectIdentifier{ProjectRoot: gps.ProjectRoot("github.com/foo/bar")} + + cases := []struct { + feedback *ConstraintFeedback + want string + }{ + { + feedback: NewLockedProjectFeedback(gps.NewLockedProject(pi, v, nil), DepTypeDirect), + want: "Locking in v1.1.4 (bc29b4f) for direct dep github.com/foo/bar", + }, + { + feedback: NewLockedProjectFeedback(gps.NewLockedProject(pi, v, nil), DepTypeImported), + want: "Trying v1.1.4 (bc29b4f) as initial lock for imported dep github.com/foo/bar", + }, + { + feedback: NewLockedProjectFeedback(gps.NewLockedProject(pi, gps.NewVersion("").Pair("bc29b4f"), nil), DepTypeImported), + want: "Trying * (bc29b4f) as initial lock for imported dep github.com/foo/bar", + }, + { + feedback: NewLockedProjectFeedback(gps.NewLockedProject(pi, b, nil), DepTypeTransitive), + want: "Locking in master (436f39d) for transitive dep github.com/foo/bar", + }, + } + + for _, c := range cases { + buf := &bytes.Buffer{} + log := log2.New(buf, "", 0) + c.feedback.LogFeedback(log) + got := strings.TrimSpace(buf.String()) + if c.want != got { + t.Errorf("Feedbacks are not expected: \n\t(GOT) '%s'\n\t(WNT) '%s'", got, c.want) + } + } +} diff --git a/vendor/github.com/golang/dep/internal/fs/fs.go b/vendor/github.com/golang/dep/internal/fs/fs.go new file mode 100644 index 00000000..4be512aa --- /dev/null +++ b/vendor/github.com/golang/dep/internal/fs/fs.go @@ -0,0 +1,694 @@ +// Copyright 2016 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 fs + +import ( + "io" + "io/ioutil" + "os" + "path/filepath" + "runtime" + "strings" + "syscall" + "unicode" + + "github.com/pkg/errors" +) + +// HasFilepathPrefix will determine if "path" starts with "prefix" from +// the point of view of a filesystem. +// +// Unlike filepath.HasPrefix, this function is path-aware, meaning that +// it knows that two directories /foo and /foobar are not the same +// thing, and therefore HasFilepathPrefix("/foobar", "/foo") will return +// false. +// +// This function also handles the case where the involved filesystems +// are case-insensitive, meaning /foo/bar and /Foo/Bar correspond to the +// same file. In that situation HasFilepathPrefix("/Foo/Bar", "/foo") +// will return true. The implementation is *not* OS-specific, so a FAT32 +// filesystem mounted on Linux will be handled correctly. +func HasFilepathPrefix(path, prefix string) (bool, error) { + // this function is more convoluted then ideal due to need for special + // handling of volume name/drive letter on Windows. vnPath and vnPrefix + // are first compared, and then used to initialize initial values of p and + // d which will be appended to for incremental checks using + // IsCaseSensitiveFilesystem and then equality. + + // no need to check IsCaseSensitiveFilesystem because VolumeName return + // empty string on all non-Windows machines + vnPath := strings.ToLower(filepath.VolumeName(path)) + vnPrefix := strings.ToLower(filepath.VolumeName(prefix)) + if vnPath != vnPrefix { + return false, nil + } + + // Because filepath.Join("c:","dir") returns "c:dir", we have to manually + // add path separator to drive letters. Also, we need to set the path root + // on *nix systems, since filepath.Join("", "dir") returns a relative path. + vnPath += string(os.PathSeparator) + vnPrefix += string(os.PathSeparator) + + var dn string + + if isDir, err := IsDir(path); err != nil { + return false, errors.Wrap(err, "failed to check filepath prefix") + } else if isDir { + dn = path + } else { + dn = filepath.Dir(path) + } + + dn = strings.TrimSuffix(dn, string(os.PathSeparator)) + prefix = strings.TrimSuffix(prefix, string(os.PathSeparator)) + + // [1:] in the lines below eliminates empty string on *nix and volume name on Windows + dirs := strings.Split(dn, string(os.PathSeparator))[1:] + prefixes := strings.Split(prefix, string(os.PathSeparator))[1:] + + if len(prefixes) > len(dirs) { + return false, nil + } + + // d,p are initialized with "/" on *nix and volume name on Windows + d := vnPath + p := vnPrefix + + for i := range prefixes { + // need to test each component of the path for + // case-sensitiveness because on Unix we could have + // something like ext4 filesystem mounted on FAT + // mountpoint, mounted on ext4 filesystem, i.e. the + // problematic filesystem is not the last one. + caseSensitive, err := IsCaseSensitiveFilesystem(filepath.Join(d, dirs[i])) + if err != nil { + return false, errors.Wrap(err, "failed to check filepath prefix") + } + if caseSensitive { + d = filepath.Join(d, dirs[i]) + p = filepath.Join(p, prefixes[i]) + } else { + d = filepath.Join(d, strings.ToLower(dirs[i])) + p = filepath.Join(p, strings.ToLower(prefixes[i])) + } + + if p != d { + return false, nil + } + } + + return true, nil +} + +// EquivalentPaths compares the paths passed to check if they are equivalent. +// It respects the case-sensitivity of the underlying filesysyems. +func EquivalentPaths(p1, p2 string) (bool, error) { + p1 = filepath.Clean(p1) + p2 = filepath.Clean(p2) + + fi1, err := os.Stat(p1) + if err != nil { + return false, errors.Wrapf(err, "could not check for path equivalence") + } + fi2, err := os.Stat(p2) + if err != nil { + return false, errors.Wrapf(err, "could not check for path equivalence") + } + + p1Filename, p2Filename := "", "" + + if !fi1.IsDir() { + p1, p1Filename = filepath.Split(p1) + } + if !fi2.IsDir() { + p2, p2Filename = filepath.Split(p2) + } + + if isPrefix1, err := HasFilepathPrefix(p1, p2); err != nil { + return false, errors.Wrap(err, "failed to check for path equivalence") + } else if isPrefix2, err := HasFilepathPrefix(p2, p1); err != nil { + return false, errors.Wrap(err, "failed to check for path equivalence") + } else if !isPrefix1 || !isPrefix2 { + return false, nil + } + + if p1Filename != "" || p2Filename != "" { + caseSensitive, err := IsCaseSensitiveFilesystem(filepath.Join(p1, p1Filename)) + if err != nil { + return false, errors.Wrap(err, "could not check for filesystem case-sensitivity") + } + if caseSensitive { + if p1Filename != p2Filename { + return false, nil + } + } else { + if strings.ToLower(p1Filename) != strings.ToLower(p2Filename) { + return false, nil + } + } + } + + return true, nil +} + +// RenameWithFallback attempts to rename a file or directory, but falls back to +// copying in the event of a cross-device link error. If the fallback copy +// succeeds, src is still removed, emulating normal rename behavior. +func RenameWithFallback(src, dst string) error { + _, err := os.Stat(src) + if err != nil { + return errors.Wrapf(err, "cannot stat %s", src) + } + + err = os.Rename(src, dst) + if err == nil { + return nil + } + + return renameFallback(err, src, dst) +} + +// renameByCopy attempts to rename a file or directory by copying it to the +// destination and then removing the src thus emulating the rename behavior. +func renameByCopy(src, dst string) error { + var cerr error + if dir, _ := IsDir(src); dir { + cerr = CopyDir(src, dst) + if cerr != nil { + cerr = errors.Wrap(cerr, "copying directory failed") + } + } else { + cerr = copyFile(src, dst) + if cerr != nil { + cerr = errors.Wrap(cerr, "copying file failed") + } + } + + if cerr != nil { + return errors.Wrapf(cerr, "rename fallback failed: cannot rename %s to %s", src, dst) + } + + return errors.Wrapf(os.RemoveAll(src), "cannot delete %s", src) +} + +// IsCaseSensitiveFilesystem determines if the filesystem where dir +// exists is case sensitive or not. +// +// CAVEAT: this function works by taking the last component of the given +// path and flipping the case of the first letter for which case +// flipping is a reversible operation (/foo/Bar → /foo/bar), then +// testing for the existence of the new filename. There are two +// possibilities: +// +// 1. The alternate filename does not exist. We can conclude that the +// filesystem is case sensitive. +// +// 2. The filename happens to exist. We have to test if the two files +// are the same file (case insensitive file system) or different ones +// (case sensitive filesystem). +// +// If the input directory is such that the last component is composed +// exclusively of case-less codepoints (e.g. numbers), this function will +// return false. +func IsCaseSensitiveFilesystem(dir string) (bool, error) { + alt := filepath.Join(filepath.Dir(dir), genTestFilename(filepath.Base(dir))) + + dInfo, err := os.Stat(dir) + if err != nil { + return false, errors.Wrap(err, "could not determine the case-sensitivity of the filesystem") + } + + aInfo, err := os.Stat(alt) + if err != nil { + // If the file doesn't exists, assume we are on a case-sensitive filesystem. + if os.IsNotExist(err) { + return true, nil + } + + return false, errors.Wrap(err, "could not determine the case-sensitivity of the filesystem") + } + + return !os.SameFile(dInfo, aInfo), nil +} + +// genTestFilename returns a string with at most one rune case-flipped. +// +// The transformation is applied only to the first rune that can be +// reversibly case-flipped, meaning: +// +// * A lowercase rune for which it's true that lower(upper(r)) == r +// * An uppercase rune for which it's true that upper(lower(r)) == r +// +// All the other runes are left intact. +func genTestFilename(str string) string { + flip := true + return strings.Map(func(r rune) rune { + if flip { + if unicode.IsLower(r) { + u := unicode.ToUpper(r) + if unicode.ToLower(u) == r { + r = u + flip = false + } + } else if unicode.IsUpper(r) { + l := unicode.ToLower(r) + if unicode.ToUpper(l) == r { + r = l + flip = false + } + } + } + return r + }, str) +} + +var errPathNotDir = errors.New("given path is not a directory") + +// ReadActualFilenames is used to determine the actual file names in given directory. +// +// On case sensitive file systems like ext4, it will check if those files exist using +// `os.Stat` and return a map with key and value as filenames which exist in the folder. +// +// Otherwise, it reads the contents of the directory and returns a map which has the +// given file name as the key and actual filename as the value(if it was found). +func ReadActualFilenames(dirPath string, names []string) (map[string]string, error) { + actualFilenames := make(map[string]string, len(names)) + if len(names) == 0 { + // This isn't expected to happen for current usage. Adding edge case handling, + // as it may be useful in future. + return actualFilenames, nil + } + // First, check that the given path is valid and it is a directory + dirStat, err := os.Stat(dirPath) + if err != nil { + return nil, errors.Wrap(err, "failed to read actual filenames") + } + + if !dirStat.IsDir() { + return nil, errPathNotDir + } + + // Ideally, we would use `os.Stat` for getting the actual file names but that returns + // the name we passed in as an argument and not the actual filename. So we are forced + // to list the directory contents and check against that. Since this check is costly, + // we do it only if absolutely necessary. + caseSensitive, err := IsCaseSensitiveFilesystem(dirPath) + if err != nil { + return nil, errors.Wrap(err, "failed to read actual filenames") + } + if caseSensitive { + // There will be no difference between actual filename and given filename. So + // just check if those files exist. + for _, name := range names { + _, err := os.Stat(filepath.Join(dirPath, name)) + if err == nil { + actualFilenames[name] = name + } else if !os.IsNotExist(err) { + // Some unexpected err, wrap and return it. + return nil, errors.Wrap(err, "failed to read actual filenames") + } + } + return actualFilenames, nil + } + + dir, err := os.Open(dirPath) + if err != nil { + return nil, errors.Wrap(err, "failed to read actual filenames") + } + defer dir.Close() + + // Pass -1 to read all filenames in directory + filenames, err := dir.Readdirnames(-1) + if err != nil { + return nil, errors.Wrap(err, "failed to read actual filenames") + } + + // namesMap holds the mapping from lowercase name to search name. Using this, we can + // avoid repeatedly looping through names. + namesMap := make(map[string]string, len(names)) + for _, name := range names { + namesMap[strings.ToLower(name)] = name + } + + for _, filename := range filenames { + searchName, ok := namesMap[strings.ToLower(filename)] + if ok { + // We are interested in this file, case insensitive match successful. + actualFilenames[searchName] = filename + if len(actualFilenames) == len(names) { + // We found all that we were looking for. + return actualFilenames, nil + } + } + } + return actualFilenames, nil +} + +var ( + errSrcNotDir = errors.New("source is not a directory") + errDstExist = errors.New("destination already exists") +) + +// CopyDir recursively copies a directory tree, attempting to preserve permissions. +// Source directory must exist, destination directory must *not* exist. +func CopyDir(src, dst string) error { + src = filepath.Clean(src) + dst = filepath.Clean(dst) + + // We use os.Lstat() here to ensure we don't fall in a loop where a symlink + // actually links to a one of its parent directories. + fi, err := os.Lstat(src) + if err != nil { + return err + } + if !fi.IsDir() { + return errSrcNotDir + } + + _, err = os.Stat(dst) + if err != nil && !os.IsNotExist(err) { + return err + } + if err == nil { + return errDstExist + } + + if err = os.MkdirAll(dst, fi.Mode()); err != nil { + return errors.Wrapf(err, "cannot mkdir %s", dst) + } + + entries, err := ioutil.ReadDir(src) + if err != nil { + return errors.Wrapf(err, "cannot read directory %s", dst) + } + + for _, entry := range entries { + srcPath := filepath.Join(src, entry.Name()) + dstPath := filepath.Join(dst, entry.Name()) + + if entry.IsDir() { + if err = CopyDir(srcPath, dstPath); err != nil { + return errors.Wrap(err, "copying directory failed") + } + } else { + // This will include symlinks, which is what we want when + // copying things. + if err = copyFile(srcPath, dstPath); err != nil { + return errors.Wrap(err, "copying file failed") + } + } + } + + return nil +} + +// copyFile copies the contents of the file named src to the file named +// by dst. The file will be created if it does not already exist. If the +// destination file exists, all its contents will be replaced by the contents +// of the source file. The file mode will be copied from the source. +func copyFile(src, dst string) (err error) { + if sym, err := IsSymlink(src); err != nil { + return errors.Wrap(err, "symlink check failed") + } else if sym { + if err := cloneSymlink(src, dst); err != nil { + if runtime.GOOS == "windows" { + // If cloning the symlink fails on Windows because the user + // does not have the required privileges, ignore the error and + // fall back to copying the file contents. + // + // ERROR_PRIVILEGE_NOT_HELD is 1314 (0x522): + // https://msdn.microsoft.com/en-us/library/windows/desktop/ms681385(v=vs.85).aspx + if lerr, ok := err.(*os.LinkError); ok && lerr.Err != syscall.Errno(1314) { + return err + } + } else { + return err + } + } else { + return nil + } + } + + in, err := os.Open(src) + if err != nil { + return + } + defer in.Close() + + out, err := os.Create(dst) + if err != nil { + return + } + + if _, err = io.Copy(out, in); err != nil { + out.Close() + return + } + + // Check for write errors on Close + if err = out.Close(); err != nil { + return + } + + si, err := os.Stat(src) + if err != nil { + return + } + + // Temporary fix for Go < 1.9 + // + // See: https://github.com/golang/dep/issues/774 + // and https://github.com/golang/go/issues/20829 + if runtime.GOOS == "windows" { + dst = fixLongPath(dst) + } + err = os.Chmod(dst, si.Mode()) + + return +} + +// cloneSymlink will create a new symlink that points to the resolved path of sl. +// If sl is a relative symlink, dst will also be a relative symlink. +func cloneSymlink(sl, dst string) error { + resolved, err := os.Readlink(sl) + if err != nil { + return err + } + + return os.Symlink(resolved, dst) +} + +// EnsureDir tries to ensure that a directory is present at the given path. It first +// checks if the directory already exists at the given path. If there isn't one, it tries +// to create it with the given permissions. However, it does not try to create the +// directory recursively. +func EnsureDir(path string, perm os.FileMode) error { + _, err := IsDir(path) + + if os.IsNotExist(err) { + err = os.Mkdir(path, perm) + if err != nil { + return errors.Wrapf(err, "failed to ensure directory at %q", path) + } + } + + return err +} + +// IsDir determines is the path given is a directory or not. +func IsDir(name string) (bool, error) { + fi, err := os.Stat(name) + if err != nil { + return false, err + } + if !fi.IsDir() { + return false, errors.Errorf("%q is not a directory", name) + } + return true, nil +} + +// IsNonEmptyDir determines if the path given is a non-empty directory or not. +func IsNonEmptyDir(name string) (bool, error) { + isDir, err := IsDir(name) + if err != nil && !os.IsNotExist(err) { + return false, err + } else if !isDir { + return false, nil + } + + // Get file descriptor + f, err := os.Open(name) + if err != nil { + return false, err + } + defer f.Close() + + // Query only 1 child. EOF if no children. + _, err = f.Readdirnames(1) + switch err { + case io.EOF: + return false, nil + case nil: + return true, nil + default: + return false, err + } +} + +// IsRegular determines if the path given is a regular file or not. +func IsRegular(name string) (bool, error) { + fi, err := os.Stat(name) + if os.IsNotExist(err) { + return false, nil + } + if err != nil { + return false, err + } + mode := fi.Mode() + if mode&os.ModeType != 0 { + return false, errors.Errorf("%q is a %v, expected a file", name, mode) + } + return true, nil +} + +// IsSymlink determines if the given path is a symbolic link. +func IsSymlink(path string) (bool, error) { + l, err := os.Lstat(path) + if err != nil { + return false, err + } + + return l.Mode()&os.ModeSymlink == os.ModeSymlink, nil +} + +// fixLongPath returns the extended-length (\\?\-prefixed) form of +// path when needed, in order to avoid the default 260 character file +// path limit imposed by Windows. If path is not easily converted to +// the extended-length form (for example, if path is a relative path +// or contains .. elements), or is short enough, fixLongPath returns +// path unmodified. +// +// See https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx#maxpath +func fixLongPath(path string) string { + // Do nothing (and don't allocate) if the path is "short". + // Empirically (at least on the Windows Server 2013 builder), + // the kernel is arbitrarily okay with < 248 bytes. That + // matches what the docs above say: + // "When using an API to create a directory, the specified + // path cannot be so long that you cannot append an 8.3 file + // name (that is, the directory name cannot exceed MAX_PATH + // minus 12)." Since MAX_PATH is 260, 260 - 12 = 248. + // + // The MSDN docs appear to say that a normal path that is 248 bytes long + // will work; empirically the path must be less then 248 bytes long. + if len(path) < 248 { + // Don't fix. (This is how Go 1.7 and earlier worked, + // not automatically generating the \\?\ form) + return path + } + + // The extended form begins with \\?\, as in + // \\?\c:\windows\foo.txt or \\?\UNC\server\share\foo.txt. + // The extended form disables evaluation of . and .. path + // elements and disables the interpretation of / as equivalent + // to \. The conversion here rewrites / to \ and elides + // . elements as well as trailing or duplicate separators. For + // simplicity it avoids the conversion entirely for relative + // paths or paths containing .. elements. For now, + // \\server\share paths are not converted to + // \\?\UNC\server\share paths because the rules for doing so + // are less well-specified. + if len(path) >= 2 && path[:2] == `\\` { + // Don't canonicalize UNC paths. + return path + } + if !isAbs(path) { + // Relative path + return path + } + + const prefix = `\\?` + + pathbuf := make([]byte, len(prefix)+len(path)+len(`\`)) + copy(pathbuf, prefix) + n := len(path) + r, w := 0, len(prefix) + for r < n { + switch { + case os.IsPathSeparator(path[r]): + // empty block + r++ + case path[r] == '.' && (r+1 == n || os.IsPathSeparator(path[r+1])): + // /./ + r++ + case r+1 < n && path[r] == '.' && path[r+1] == '.' && (r+2 == n || os.IsPathSeparator(path[r+2])): + // /../ is currently unhandled + return path + default: + pathbuf[w] = '\\' + w++ + for ; r < n && !os.IsPathSeparator(path[r]); r++ { + pathbuf[w] = path[r] + w++ + } + } + } + // A drive's root directory needs a trailing \ + if w == len(`\\?\c:`) { + pathbuf[w] = '\\' + w++ + } + return string(pathbuf[:w]) +} + +func isAbs(path string) (b bool) { + v := volumeName(path) + if v == "" { + return false + } + path = path[len(v):] + if path == "" { + return false + } + return os.IsPathSeparator(path[0]) +} + +func volumeName(path string) (v string) { + if len(path) < 2 { + return "" + } + // with drive letter + c := path[0] + if path[1] == ':' && + ('0' <= c && c <= '9' || 'a' <= c && c <= 'z' || + 'A' <= c && c <= 'Z') { + return path[:2] + } + // is it UNC + if l := len(path); l >= 5 && os.IsPathSeparator(path[0]) && os.IsPathSeparator(path[1]) && + !os.IsPathSeparator(path[2]) && path[2] != '.' { + // first, leading `\\` and next shouldn't be `\`. its server name. + for n := 3; n < l-1; n++ { + // second, next '\' shouldn't be repeated. + if os.IsPathSeparator(path[n]) { + n++ + // third, following something characters. its share name. + if !os.IsPathSeparator(path[n]) { + if path[n] == '.' { + break + } + for ; n < l; n++ { + if os.IsPathSeparator(path[n]) { + break + } + } + return path[:n] + } + break + } + } + } + return "" +} diff --git a/vendor/github.com/golang/dep/internal/fs/fs_test.go b/vendor/github.com/golang/dep/internal/fs/fs_test.go new file mode 100644 index 00000000..5ca8bf16 --- /dev/null +++ b/vendor/github.com/golang/dep/internal/fs/fs_test.go @@ -0,0 +1,1126 @@ +// Copyright 2016 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 fs + +import ( + "io/ioutil" + "os" + "path/filepath" + "reflect" + "runtime" + "strings" + "testing" + + "github.com/golang/dep/internal/test" + "github.com/pkg/errors" +) + +// This function tests HadFilepathPrefix. It should test it on both case +// sensitive and insensitive situations. However, the only reliable way to test +// case-insensitive behaviour is if using case-insensitive filesystem. This +// cannot be guaranteed in an automated test. Therefore, the behaviour of the +// tests is not to test case sensitivity on *nix and to assume that Windows is +// case-insensitive. Please see link below for some background. +// +// https://superuser.com/questions/266110/how-do-you-make-windows-7-fully-case-sensitive-with-respect-to-the-filesystem +// +// NOTE: NTFS can be made case-sensitive. However many Windows programs, +// including Windows Explorer do not handle gracefully multiple files that +// differ only in capitalization. It is possible that this can cause these tests +// to fail on some setups. +func TestHasFilepathPrefix(t *testing.T) { + dir, err := ioutil.TempDir("", "dep") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(dir) + + // dir2 is the same as dir but with different capitalization on Windows to + // test case insensitivity + var dir2 string + if runtime.GOOS == "windows" { + dir = strings.ToLower(dir) + dir2 = strings.ToUpper(dir) + } else { + dir2 = dir + } + + cases := []struct { + path string + prefix string + want bool + }{ + {filepath.Join(dir, "a", "b"), filepath.Join(dir2), true}, + {filepath.Join(dir, "a", "b"), filepath.Join(dir2, "a"), true}, + {filepath.Join(dir, "a", "b"), filepath.Join(dir2, "a", "b"), true}, + {filepath.Join(dir, "a", "b"), filepath.Join(dir2, "c"), false}, + {filepath.Join(dir, "a", "b"), filepath.Join(dir2, "a", "d", "b"), false}, + {filepath.Join(dir, "a", "b"), filepath.Join(dir2, "a", "b2"), false}, + {filepath.Join(dir), filepath.Join(dir2, "a", "b"), false}, + {filepath.Join(dir, "ab"), filepath.Join(dir2, "a", "b"), false}, + {filepath.Join(dir, "ab"), filepath.Join(dir2, "a"), false}, + {filepath.Join(dir, "123"), filepath.Join(dir2, "123"), true}, + {filepath.Join(dir, "123"), filepath.Join(dir2, "1"), false}, + {filepath.Join(dir, "⌘"), filepath.Join(dir2, "⌘"), true}, + {filepath.Join(dir, "a"), filepath.Join(dir2, "⌘"), false}, + {filepath.Join(dir, "⌘"), filepath.Join(dir2, "a"), false}, + } + + for _, c := range cases { + if err := os.MkdirAll(c.path, 0755); err != nil { + t.Fatal(err) + } + + if err = os.MkdirAll(c.prefix, 0755); err != nil { + t.Fatal(err) + } + + got, err := HasFilepathPrefix(c.path, c.prefix) + if err != nil { + t.Fatalf("unexpected error: %s", err) + } + if c.want != got { + t.Fatalf("dir: %q, prefix: %q, expected: %v, got: %v", c.path, c.prefix, c.want, got) + } + } +} + +// This function tests HadFilepathPrefix. It should test it on both case +// sensitive and insensitive situations. However, the only reliable way to test +// case-insensitive behaviour is if using case-insensitive filesystem. This +// cannot be guaranteed in an automated test. Therefore, the behaviour of the +// tests is not to test case sensitivity on *nix and to assume that Windows is +// case-insensitive. Please see link below for some background. +// +// https://superuser.com/questions/266110/how-do-you-make-windows-7-fully-case-sensitive-with-respect-to-the-filesystem +// +// NOTE: NTFS can be made case-sensitive. However many Windows programs, +// including Windows Explorer do not handle gracefully multiple files that +// differ only in capitalization. It is possible that this can cause these tests +// to fail on some setups. +func TestHasFilepathPrefix_Files(t *testing.T) { + dir, err := ioutil.TempDir("", "dep") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(dir) + + // dir2 is the same as dir but with different capitalization on Windows to + // test case insensitivity + var dir2 string + if runtime.GOOS == "windows" { + dir = strings.ToLower(dir) + dir2 = strings.ToUpper(dir) + } else { + dir2 = dir + } + + existingFile := filepath.Join(dir, "exists") + if err = os.MkdirAll(existingFile, 0755); err != nil { + t.Fatal(err) + } + + nonExistingFile := filepath.Join(dir, "does_not_exists") + + cases := []struct { + path string + prefix string + want bool + err bool + }{ + {existingFile, filepath.Join(dir2), true, false}, + {nonExistingFile, filepath.Join(dir2), false, true}, + } + + for _, c := range cases { + got, err := HasFilepathPrefix(c.path, c.prefix) + if err != nil && !c.err { + t.Fatalf("unexpected error: %s", err) + } + if c.want != got { + t.Fatalf("dir: %q, prefix: %q, expected: %v, got: %v", c.path, c.prefix, c.want, got) + } + } +} + +func TestEquivalentPaths(t *testing.T) { + h := test.NewHelper(t) + h.TempDir("dir") + h.TempDir("dir2") + + h.TempFile("file", "") + h.TempFile("file2", "") + + h.TempDir("DIR") + h.TempFile("FILE", "") + + testcases := []struct { + p1, p2 string + caseSensitiveEquivalent bool + caseInensitiveEquivalent bool + err bool + }{ + {h.Path("dir"), h.Path("dir"), true, true, false}, + {h.Path("file"), h.Path("file"), true, true, false}, + {h.Path("dir"), h.Path("dir2"), false, false, false}, + {h.Path("file"), h.Path("file2"), false, false, false}, + {h.Path("dir"), h.Path("file"), false, false, false}, + {h.Path("dir"), h.Path("DIR"), false, true, false}, + {strings.ToLower(h.Path("dir")), strings.ToUpper(h.Path("dir")), false, true, true}, + } + + caseSensitive, err := IsCaseSensitiveFilesystem(h.Path("dir")) + if err != nil { + t.Fatal("unexpcted error:", err) + } + + for _, tc := range testcases { + got, err := EquivalentPaths(tc.p1, tc.p2) + if err != nil && !tc.err { + t.Error("unexpected error:", err) + } + if caseSensitive { + if tc.caseSensitiveEquivalent != got { + t.Errorf("expected EquivalentPaths(%q, %q) to be %t on case-sensitive filesystem, got %t", tc.p1, tc.p2, tc.caseSensitiveEquivalent, got) + } + } else { + if tc.caseInensitiveEquivalent != got { + t.Errorf("expected EquivalentPaths(%q, %q) to be %t on case-insensitive filesystem, got %t", tc.p1, tc.p2, tc.caseInensitiveEquivalent, got) + } + } + } +} + +func TestRenameWithFallback(t *testing.T) { + dir, err := ioutil.TempDir("", "dep") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(dir) + + if err = RenameWithFallback(filepath.Join(dir, "does_not_exists"), filepath.Join(dir, "dst")); err == nil { + t.Fatal("expected an error for non existing file, but got nil") + } + + srcpath := filepath.Join(dir, "src") + + if srcf, err := os.Create(srcpath); err != nil { + t.Fatal(err) + } else { + srcf.Close() + } + + if err = RenameWithFallback(srcpath, filepath.Join(dir, "dst")); err != nil { + t.Fatal(err) + } + + srcpath = filepath.Join(dir, "a") + if err = os.MkdirAll(srcpath, 0777); err != nil { + t.Fatal(err) + } + + dstpath := filepath.Join(dir, "b") + if err = os.MkdirAll(dstpath, 0777); err != nil { + t.Fatal(err) + } + + if err = RenameWithFallback(srcpath, dstpath); err == nil { + t.Fatal("expected an error if dst is an existing directory, but got nil") + } +} + +func TestIsCaseSensitiveFilesystem(t *testing.T) { + isLinux := runtime.GOOS == "linux" + isWindows := runtime.GOOS == "windows" + isMacOS := runtime.GOOS == "darwin" + + if !isLinux && !isWindows && !isMacOS { + t.Skip("Run this test on Windows, Linux and macOS only") + } + + dir, err := ioutil.TempDir("", "TestCaseSensitivity") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(dir) + + var want bool + if isLinux { + want = true + } else { + want = false + } + + got, err := IsCaseSensitiveFilesystem(dir) + + if err != nil { + t.Fatalf("unexpected error message: \n\t(GOT) %+v", err) + } + + if want != got { + t.Fatalf("unexpected value returned: \n\t(GOT) %t\n\t(WNT) %t", got, want) + } +} + +func TestReadActualFilenames(t *testing.T) { + // We are trying to skip this test on file systems which are case-sensiive. We could + // have used `fs.IsCaseSensitiveFilesystem` for this check. However, the code we are + // testing also relies on `fs.IsCaseSensitiveFilesystem`. So a bug in + // `fs.IsCaseSensitiveFilesystem` could prevent this test from being run. This is the + // only scenario where we prefer the OS heuristic over doing the actual work of + // validating filesystem case sensitivity via `fs.IsCaseSensitiveFilesystem`. + if runtime.GOOS != "windows" && runtime.GOOS != "darwin" { + t.Skip("skip this test on non-Windows, non-macOS") + } + + h := test.NewHelper(t) + defer h.Cleanup() + + h.TempDir("") + tmpPath := h.Path(".") + + // First, check the scenarios for which we expect an error. + _, err := ReadActualFilenames(filepath.Join(tmpPath, "does_not_exists"), []string{""}) + switch { + case err == nil: + t.Fatal("expected err for non-existing folder") + // use `errors.Cause` because the error is wrapped and returned + case !os.IsNotExist(errors.Cause(err)): + t.Fatalf("unexpected error: %+v", err) + } + h.TempFile("tmpFile", "") + _, err = ReadActualFilenames(h.Path("tmpFile"), []string{""}) + switch { + case err == nil: + t.Fatal("expected err for passing file instead of directory") + case err != errPathNotDir: + t.Fatalf("unexpected error: %+v", err) + } + + cases := []struct { + createFiles []string + names []string + want map[string]string + }{ + // If we supply no filenames to the function, it should return an empty map. + {nil, nil, map[string]string{}}, + // If the directory contains the given file with different case, it should return + // a map which has the given filename as the key and actual filename as the value. + { + []string{"test1.txt"}, + []string{"Test1.txt"}, + map[string]string{"Test1.txt": "test1.txt"}, + }, + // 1. If the given filename is same as the actual filename, map should have the + // same key and value for the file. + // 2. If the given filename is present with different case for file extension, + // it should return a map which has the given filename as the key and actual + // filename as the value. + // 3. If the given filename is not present even with a different case, the map + // returned should not have an entry for that filename. + { + []string{"test2.txt", "test3.TXT"}, + []string{"test2.txt", "Test3.txt", "Test4.txt"}, + map[string]string{ + "test2.txt": "test2.txt", + "Test3.txt": "test3.TXT", + }, + }, + } + for _, c := range cases { + for _, file := range c.createFiles { + h.TempFile(file, "") + } + got, err := ReadActualFilenames(tmpPath, c.names) + if err != nil { + t.Fatalf("unexpected error: %+v", err) + } + if !reflect.DeepEqual(c.want, got) { + t.Fatalf("returned value does not match expected: \n\t(GOT) %v\n\t(WNT) %v", + got, c.want) + } + } +} + +func TestGenTestFilename(t *testing.T) { + cases := []struct { + str string + want string + }{ + {"abc", "Abc"}, + {"ABC", "aBC"}, + {"AbC", "abC"}, + {"αβγ", "Αβγ"}, + {"123", "123"}, + {"1a2", "1A2"}, + {"12a", "12A"}, + {"⌘", "⌘"}, + } + + for _, c := range cases { + got := genTestFilename(c.str) + if c.want != got { + t.Fatalf("str: %q, expected: %q, got: %q", c.str, c.want, got) + } + } +} + +func BenchmarkGenTestFilename(b *testing.B) { + cases := []string{ + strings.Repeat("a", 128), + strings.Repeat("A", 128), + strings.Repeat("α", 128), + strings.Repeat("1", 128), + strings.Repeat("⌘", 128), + } + + for i := 0; i < b.N; i++ { + for _, str := range cases { + genTestFilename(str) + } + } +} + +func TestCopyDir(t *testing.T) { + dir, err := ioutil.TempDir("", "dep") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(dir) + + srcdir := filepath.Join(dir, "src") + if err := os.MkdirAll(srcdir, 0755); err != nil { + t.Fatal(err) + } + + files := []struct { + path string + contents string + fi os.FileInfo + }{ + {path: "myfile", contents: "hello world"}, + {path: filepath.Join("subdir", "file"), contents: "subdir file"}, + } + + // Create structure indicated in 'files' + for i, file := range files { + fn := filepath.Join(srcdir, file.path) + dn := filepath.Dir(fn) + if err = os.MkdirAll(dn, 0755); err != nil { + t.Fatal(err) + } + + fh, err := os.Create(fn) + if err != nil { + t.Fatal(err) + } + + if _, err = fh.Write([]byte(file.contents)); err != nil { + t.Fatal(err) + } + fh.Close() + + files[i].fi, err = os.Stat(fn) + if err != nil { + t.Fatal(err) + } + } + + destdir := filepath.Join(dir, "dest") + if err := CopyDir(srcdir, destdir); err != nil { + t.Fatal(err) + } + + // Compare copy against structure indicated in 'files' + for _, file := range files { + fn := filepath.Join(srcdir, file.path) + dn := filepath.Dir(fn) + dirOK, err := IsDir(dn) + if err != nil { + t.Fatal(err) + } + if !dirOK { + t.Fatalf("expected %s to be a directory", dn) + } + + got, err := ioutil.ReadFile(fn) + if err != nil { + t.Fatal(err) + } + + if file.contents != string(got) { + t.Fatalf("expected: %s, got: %s", file.contents, string(got)) + } + + gotinfo, err := os.Stat(fn) + if err != nil { + t.Fatal(err) + } + + if file.fi.Mode() != gotinfo.Mode() { + t.Fatalf("expected %s: %#v\n to be the same mode as %s: %#v", + file.path, file.fi.Mode(), fn, gotinfo.Mode()) + } + } +} + +func TestCopyDirFail_SrcInaccessible(t *testing.T) { + if runtime.GOOS == "windows" { + // XXX: setting permissions works differently in + // Microsoft Windows. Skipping this this until a + // compatible implementation is provided. + t.Skip("skipping on windows") + } + + var srcdir, dstdir string + + cleanup := setupInaccessibleDir(t, func(dir string) error { + srcdir = filepath.Join(dir, "src") + return os.MkdirAll(srcdir, 0755) + }) + defer cleanup() + + dir, err := ioutil.TempDir("", "dep") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(dir) + + dstdir = filepath.Join(dir, "dst") + if err = CopyDir(srcdir, dstdir); err == nil { + t.Fatalf("expected error for CopyDir(%s, %s), got none", srcdir, dstdir) + } +} + +func TestCopyDirFail_DstInaccessible(t *testing.T) { + if runtime.GOOS == "windows" { + // XXX: setting permissions works differently in + // Microsoft Windows. Skipping this this until a + // compatible implementation is provided. + t.Skip("skipping on windows") + } + + var srcdir, dstdir string + + dir, err := ioutil.TempDir("", "dep") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(dir) + + srcdir = filepath.Join(dir, "src") + if err = os.MkdirAll(srcdir, 0755); err != nil { + t.Fatal(err) + } + + cleanup := setupInaccessibleDir(t, func(dir string) error { + dstdir = filepath.Join(dir, "dst") + return nil + }) + defer cleanup() + + if err := CopyDir(srcdir, dstdir); err == nil { + t.Fatalf("expected error for CopyDir(%s, %s), got none", srcdir, dstdir) + } +} + +func TestCopyDirFail_SrcIsNotDir(t *testing.T) { + var srcdir, dstdir string + + dir, err := ioutil.TempDir("", "dep") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(dir) + + srcdir = filepath.Join(dir, "src") + if _, err = os.Create(srcdir); err != nil { + t.Fatal(err) + } + + dstdir = filepath.Join(dir, "dst") + + if err = CopyDir(srcdir, dstdir); err == nil { + t.Fatalf("expected error for CopyDir(%s, %s), got none", srcdir, dstdir) + } + + if err != errSrcNotDir { + t.Fatalf("expected %v error for CopyDir(%s, %s), got %s", errSrcNotDir, srcdir, dstdir, err) + } + +} + +func TestCopyDirFail_DstExists(t *testing.T) { + var srcdir, dstdir string + + dir, err := ioutil.TempDir("", "dep") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(dir) + + srcdir = filepath.Join(dir, "src") + if err = os.MkdirAll(srcdir, 0755); err != nil { + t.Fatal(err) + } + + dstdir = filepath.Join(dir, "dst") + if err = os.MkdirAll(dstdir, 0755); err != nil { + t.Fatal(err) + } + + if err = CopyDir(srcdir, dstdir); err == nil { + t.Fatalf("expected error for CopyDir(%s, %s), got none", srcdir, dstdir) + } + + if err != errDstExist { + t.Fatalf("expected %v error for CopyDir(%s, %s), got %s", errDstExist, srcdir, dstdir, err) + } +} + +func TestCopyDirFailOpen(t *testing.T) { + if runtime.GOOS == "windows" { + // XXX: setting permissions works differently in + // Microsoft Windows. os.Chmod(..., 0222) below is not + // enough for the file to be readonly, and os.Chmod(..., + // 0000) returns an invalid argument error. Skipping + // this this until a compatible implementation is + // provided. + t.Skip("skipping on windows") + } + + var srcdir, dstdir string + + dir, err := ioutil.TempDir("", "dep") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(dir) + + srcdir = filepath.Join(dir, "src") + if err = os.MkdirAll(srcdir, 0755); err != nil { + t.Fatal(err) + } + + srcfn := filepath.Join(srcdir, "file") + srcf, err := os.Create(srcfn) + if err != nil { + t.Fatal(err) + } + srcf.Close() + + // setup source file so that it cannot be read + if err = os.Chmod(srcfn, 0222); err != nil { + t.Fatal(err) + } + + dstdir = filepath.Join(dir, "dst") + + if err = CopyDir(srcdir, dstdir); err == nil { + t.Fatalf("expected error for CopyDir(%s, %s), got none", srcdir, dstdir) + } +} + +func TestCopyFile(t *testing.T) { + dir, err := ioutil.TempDir("", "dep") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(dir) + + srcf, err := os.Create(filepath.Join(dir, "srcfile")) + if err != nil { + t.Fatal(err) + } + + want := "hello world" + if _, err := srcf.Write([]byte(want)); err != nil { + t.Fatal(err) + } + srcf.Close() + + destf := filepath.Join(dir, "destf") + if err := copyFile(srcf.Name(), destf); err != nil { + t.Fatal(err) + } + + got, err := ioutil.ReadFile(destf) + if err != nil { + t.Fatal(err) + } + + if want != string(got) { + t.Fatalf("expected: %s, got: %s", want, string(got)) + } + + wantinfo, err := os.Stat(srcf.Name()) + if err != nil { + t.Fatal(err) + } + + gotinfo, err := os.Stat(destf) + if err != nil { + t.Fatal(err) + } + + if wantinfo.Mode() != gotinfo.Mode() { + t.Fatalf("expected %s: %#v\n to be the same mode as %s: %#v", srcf.Name(), wantinfo.Mode(), destf, gotinfo.Mode()) + } +} + +func TestCopyFileSymlink(t *testing.T) { + h := test.NewHelper(t) + defer h.Cleanup() + h.TempDir(".") + + testcases := map[string]string{ + filepath.Join("./testdata/symlinks/file-symlink"): filepath.Join(h.Path("."), "dst-file"), + filepath.Join("./testdata/symlinks/windows-file-symlink"): filepath.Join(h.Path("."), "windows-dst-file"), + filepath.Join("./testdata/symlinks/dir-symlink"): filepath.Join(h.Path("."), "dst-dir"), + filepath.Join("./testdata/symlinks/invalid-symlink"): filepath.Join(h.Path("."), "invalid-symlink"), + } + + for symlink, dst := range testcases { + t.Run(symlink, func(t *testing.T) { + var err error + if err = copyFile(symlink, dst); err != nil { + t.Fatalf("failed to copy symlink: %s", err) + } + + var want, got string + + if runtime.GOOS == "windows" { + // Creating symlinks on Windows require an additional permission + // regular users aren't granted usually. So we copy the file + // content as a fall back instead of creating a real symlink. + srcb, err := ioutil.ReadFile(symlink) + h.Must(err) + dstb, err := ioutil.ReadFile(dst) + h.Must(err) + + want = string(srcb) + got = string(dstb) + } else { + want, err = os.Readlink(symlink) + h.Must(err) + + got, err = os.Readlink(dst) + if err != nil { + t.Fatalf("could not resolve symlink: %s", err) + } + } + + if want != got { + t.Fatalf("resolved path is incorrect. expected %s, got %s", want, got) + } + }) + } +} + +func TestCopyFileLongFilePath(t *testing.T) { + if runtime.GOOS != "windows" { + // We want to ensure the temporary fix actually fixes the issue with + // os.Chmod and long file paths. This is only applicable on Windows. + t.Skip("skipping on non-windows") + } + + h := test.NewHelper(t) + h.TempDir(".") + defer h.Cleanup() + + tmpPath := h.Path(".") + + // Create a directory with a long-enough path name to cause the bug in #774. + dirName := "" + for len(tmpPath+string(os.PathSeparator)+dirName) <= 300 { + dirName += "directory" + } + + h.TempDir(dirName) + h.TempFile(dirName+string(os.PathSeparator)+"src", "") + + tmpDirPath := tmpPath + string(os.PathSeparator) + dirName + string(os.PathSeparator) + + err := copyFile(tmpDirPath+"src", tmpDirPath+"dst") + if err != nil { + t.Fatalf("unexpected error while copying file: %v", err) + } +} + +// C:\Users\appveyor\AppData\Local\Temp\1\gotest639065787\dir4567890\dir4567890\dir4567890\dir4567890\dir4567890\dir4567890\dir4567890\dir4567890\dir4567890\dir4567890\dir4567890\dir4567890\dir4567890\dir4567890\dir4567890\dir4567890\dir4567890\dir4567890\dir4567890\dir4567890\dir4567890\dir4567890\dir4567890 + +func TestCopyFileFail(t *testing.T) { + if runtime.GOOS == "windows" { + // XXX: setting permissions works differently in + // Microsoft Windows. Skipping this this until a + // compatible implementation is provided. + t.Skip("skipping on windows") + } + + dir, err := ioutil.TempDir("", "dep") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(dir) + + srcf, err := os.Create(filepath.Join(dir, "srcfile")) + if err != nil { + t.Fatal(err) + } + srcf.Close() + + var dstdir string + + cleanup := setupInaccessibleDir(t, func(dir string) error { + dstdir = filepath.Join(dir, "dir") + return os.Mkdir(dstdir, 0777) + }) + defer cleanup() + + fn := filepath.Join(dstdir, "file") + if err := copyFile(srcf.Name(), fn); err == nil { + t.Fatalf("expected error for %s, got none", fn) + } +} + +// setupInaccessibleDir creates a temporary location with a single +// directory in it, in such a way that that directory is not accessible +// after this function returns. +// +// op is called with the directory as argument, so that it can create +// files or other test artifacts. +// +// If setupInaccessibleDir fails in its preparation, or op fails, t.Fatal +// will be invoked. +// +// This function returns a cleanup function that removes all the temporary +// files this function creates. It is the caller's responsibility to call +// this function before the test is done running, whether there's an error or not. +func setupInaccessibleDir(t *testing.T, op func(dir string) error) func() { + dir, err := ioutil.TempDir("", "dep") + if err != nil { + t.Fatal(err) + return nil // keep compiler happy + } + + subdir := filepath.Join(dir, "dir") + + cleanup := func() { + if err := os.Chmod(subdir, 0777); err != nil { + t.Error(err) + } + if err := os.RemoveAll(dir); err != nil { + t.Error(err) + } + } + + if err := os.Mkdir(subdir, 0777); err != nil { + cleanup() + t.Fatal(err) + return nil + } + + if err := op(subdir); err != nil { + cleanup() + t.Fatal(err) + return nil + } + + if err := os.Chmod(subdir, 0666); err != nil { + cleanup() + t.Fatal(err) + return nil + } + + return cleanup +} + +func TestEnsureDir(t *testing.T) { + h := test.NewHelper(t) + defer h.Cleanup() + h.TempDir(".") + h.TempFile("file", "") + + tmpPath := h.Path(".") + + var dn string + cleanup := setupInaccessibleDir(t, func(dir string) error { + dn = filepath.Join(dir, "dir") + return os.Mkdir(dn, 0777) + }) + defer cleanup() + + tests := map[string]bool{ + // [success] A dir already exists for the given path. + tmpPath: true, + // [success] Dir does not exist but parent dir exists, so should get created. + filepath.Join(tmpPath, "testdir"): true, + // [failure] Dir and parent dir do not exist, should return an error. + filepath.Join(tmpPath, "notexist", "testdir"): false, + // [failure] Regular file present at given path. + h.Path("file"): false, + // [failure] Path inaccessible. + dn: false, + } + + if runtime.GOOS == "windows" { + // This test doesn't work on Microsoft Windows because + // of the differences in how file permissions are + // implemented. For this to work, the directory where + // the directory exists should be inaccessible. + delete(tests, dn) + } + + for path, shouldEnsure := range tests { + err := EnsureDir(path, 0777) + if shouldEnsure { + if err != nil { + t.Fatalf("unexpected error %q for %q", err, path) + } else if ok, err := IsDir(path); !ok { + t.Fatalf("expected directory to be preset at %q", path) + t.Fatal(err) + } + } else if err == nil { + t.Fatalf("expected error for path %q, got none", path) + } + } +} + +func TestIsRegular(t *testing.T) { + wd, err := os.Getwd() + if err != nil { + t.Fatal(err) + } + + var fn string + + cleanup := setupInaccessibleDir(t, func(dir string) error { + fn = filepath.Join(dir, "file") + fh, err := os.Create(fn) + if err != nil { + return err + } + + return fh.Close() + }) + defer cleanup() + + tests := map[string]struct { + exists bool + err bool + }{ + wd: {false, true}, + filepath.Join(wd, "testdata"): {false, true}, + filepath.Join(wd, "testdata", "test.file"): {true, false}, + filepath.Join(wd, "this_file_does_not_exist.thing"): {false, false}, + fn: {false, true}, + } + + if runtime.GOOS == "windows" { + // This test doesn't work on Microsoft Windows because + // of the differences in how file permissions are + // implemented. For this to work, the directory where + // the file exists should be inaccessible. + delete(tests, fn) + } + + for f, want := range tests { + got, err := IsRegular(f) + if err != nil { + if want.exists != got { + t.Fatalf("expected %t for %s, got %t", want.exists, f, got) + } + if !want.err { + t.Fatalf("expected no error, got %v", err) + } + } else { + if want.err { + t.Fatalf("expected error for %s, got none", f) + } + } + + if got != want.exists { + t.Fatalf("expected %t for %s, got %t", want, f, got) + } + } + +} + +func TestIsDir(t *testing.T) { + wd, err := os.Getwd() + if err != nil { + t.Fatal(err) + } + + var dn string + + cleanup := setupInaccessibleDir(t, func(dir string) error { + dn = filepath.Join(dir, "dir") + return os.Mkdir(dn, 0777) + }) + defer cleanup() + + tests := map[string]struct { + exists bool + err bool + }{ + wd: {true, false}, + filepath.Join(wd, "testdata"): {true, false}, + filepath.Join(wd, "main.go"): {false, true}, + filepath.Join(wd, "this_file_does_not_exist.thing"): {false, true}, + dn: {false, true}, + } + + if runtime.GOOS == "windows" { + // This test doesn't work on Microsoft Windows because + // of the differences in how file permissions are + // implemented. For this to work, the directory where + // the directory exists should be inaccessible. + delete(tests, dn) + } + + for f, want := range tests { + got, err := IsDir(f) + if err != nil && !want.err { + t.Fatalf("expected no error, got %v", err) + } + + if got != want.exists { + t.Fatalf("expected %t for %s, got %t", want.exists, f, got) + } + } +} + +func TestIsNonEmptyDir(t *testing.T) { + wd, err := os.Getwd() + if err != nil { + t.Fatal(err) + } + + h := test.NewHelper(t) + defer h.Cleanup() + + h.TempDir("empty") + + testCases := []struct { + path string + empty bool + err bool + }{ + {wd, true, false}, + {"testdata", true, false}, + {filepath.Join(wd, "fs.go"), false, true}, + {filepath.Join(wd, "this_file_does_not_exist.thing"), false, false}, + {h.Path("empty"), false, false}, + } + + // This test case doesn't work on Microsoft Windows because of the + // differences in how file permissions are implemented. + if runtime.GOOS != "windows" { + var inaccessibleDir string + cleanup := setupInaccessibleDir(t, func(dir string) error { + inaccessibleDir = filepath.Join(dir, "empty") + return os.Mkdir(inaccessibleDir, 0777) + }) + defer cleanup() + + testCases = append(testCases, struct { + path string + empty bool + err bool + }{inaccessibleDir, false, true}) + } + + for _, want := range testCases { + got, err := IsNonEmptyDir(want.path) + if want.err && err == nil { + if got { + t.Fatalf("wanted false with error for %v, but got true", want.path) + } + t.Fatalf("wanted an error for %v, but it was nil", want.path) + } + + if got != want.empty { + t.Fatalf("wanted %t for %v, but got %t", want.empty, want.path, got) + } + } +} + +func TestIsSymlink(t *testing.T) { + dir, err := ioutil.TempDir("", "dep") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(dir) + + dirPath := filepath.Join(dir, "directory") + if err = os.MkdirAll(dirPath, 0777); err != nil { + t.Fatal(err) + } + + filePath := filepath.Join(dir, "file") + f, err := os.Create(filePath) + if err != nil { + t.Fatal(err) + } + f.Close() + + dirSymlink := filepath.Join(dir, "dirSymlink") + fileSymlink := filepath.Join(dir, "fileSymlink") + + if err = os.Symlink(dirPath, dirSymlink); err != nil { + t.Fatal(err) + } + if err = os.Symlink(filePath, fileSymlink); err != nil { + t.Fatal(err) + } + + var ( + inaccessibleFile string + inaccessibleSymlink string + ) + + cleanup := setupInaccessibleDir(t, func(dir string) error { + inaccessibleFile = filepath.Join(dir, "file") + if fh, err := os.Create(inaccessibleFile); err != nil { + return err + } else if err = fh.Close(); err != nil { + return err + } + + inaccessibleSymlink = filepath.Join(dir, "symlink") + return os.Symlink(inaccessibleFile, inaccessibleSymlink) + }) + defer cleanup() + + tests := map[string]struct{ expected, err bool }{ + dirPath: {false, false}, + filePath: {false, false}, + dirSymlink: {true, false}, + fileSymlink: {true, false}, + inaccessibleFile: {false, true}, + inaccessibleSymlink: {false, true}, + } + + if runtime.GOOS == "windows" { + // XXX: setting permissions works differently in Windows. Skipping + // these cases until a compatible implementation is provided. + delete(tests, inaccessibleFile) + delete(tests, inaccessibleSymlink) + } + + for path, want := range tests { + got, err := IsSymlink(path) + if err != nil { + if !want.err { + t.Errorf("expected no error, got %v", err) + } + } + + if got != want.expected { + t.Errorf("expected %t for %s, got %t", want.expected, path, got) + } + } +} diff --git a/vendor/github.com/golang/dep/internal/fs/rename.go b/vendor/github.com/golang/dep/internal/fs/rename.go new file mode 100644 index 00000000..c48f69f1 --- /dev/null +++ b/vendor/github.com/golang/dep/internal/fs/rename.go @@ -0,0 +1,31 @@ +// Copyright 2016 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. + +// +build !windows + +package fs + +import ( + "os" + "syscall" + + "github.com/pkg/errors" +) + +// renameFallback attempts to determine the appropriate fallback to failed rename +// operation depending on the resulting error. +func renameFallback(err error, src, dst string) error { + // Rename may fail if src and dst are on different devices; fall back to + // copy if we detect that case. syscall.EXDEV is the common name for the + // cross device link error which has varying output text across different + // operating systems. + terr, ok := err.(*os.LinkError) + if !ok { + return err + } else if terr.Err != syscall.EXDEV { + return errors.Wrapf(terr, "link error: cannot rename %s to %s", src, dst) + } + + return renameByCopy(src, dst) +} diff --git a/vendor/github.com/golang/dep/internal/fs/rename_windows.go b/vendor/github.com/golang/dep/internal/fs/rename_windows.go new file mode 100644 index 00000000..50829a5c --- /dev/null +++ b/vendor/github.com/golang/dep/internal/fs/rename_windows.go @@ -0,0 +1,42 @@ +// Copyright 2016 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. + +// +build windows + +package fs + +import ( + "os" + "syscall" + + "github.com/pkg/errors" +) + +// renameFallback attempts to determine the appropriate fallback to failed rename +// operation depending on the resulting error. +func renameFallback(err error, src, dst string) error { + // Rename may fail if src and dst are on different devices; fall back to + // copy if we detect that case. syscall.EXDEV is the common name for the + // cross device link error which has varying output text across different + // operating systems. + terr, ok := err.(*os.LinkError) + if !ok { + return err + } + + if terr.Err != syscall.EXDEV { + // In windows it can drop down to an operating system call that + // returns an operating system error with a different number and + // message. Checking for that as a fall back. + noerr, ok := terr.Err.(syscall.Errno) + + // 0x11 (ERROR_NOT_SAME_DEVICE) is the windows error. + // See https://msdn.microsoft.com/en-us/library/cc231199.aspx + if ok && noerr != 0x11 { + return errors.Wrapf(terr, "link error: cannot rename %s to %s", src, dst) + } + } + + return renameByCopy(src, dst) +} diff --git a/vendor/github.com/golang/dep/internal/fs/testdata/symlinks/dir-symlink b/vendor/github.com/golang/dep/internal/fs/testdata/symlinks/dir-symlink new file mode 120000 index 00000000..777ebd01 --- /dev/null +++ b/vendor/github.com/golang/dep/internal/fs/testdata/symlinks/dir-symlink @@ -0,0 +1 @@ +../../testdata \ No newline at end of file diff --git a/vendor/github.com/golang/dep/internal/fs/testdata/symlinks/file-symlink b/vendor/github.com/golang/dep/internal/fs/testdata/symlinks/file-symlink new file mode 120000 index 00000000..4c52274d --- /dev/null +++ b/vendor/github.com/golang/dep/internal/fs/testdata/symlinks/file-symlink @@ -0,0 +1 @@ +../test.file \ No newline at end of file diff --git a/vendor/github.com/golang/dep/internal/fs/testdata/symlinks/invalid-symlink b/vendor/github.com/golang/dep/internal/fs/testdata/symlinks/invalid-symlink new file mode 120000 index 00000000..0edf4f30 --- /dev/null +++ b/vendor/github.com/golang/dep/internal/fs/testdata/symlinks/invalid-symlink @@ -0,0 +1 @@ +/non/existing/file \ No newline at end of file diff --git a/vendor/github.com/golang/dep/internal/fs/testdata/symlinks/windows-file-symlink b/vendor/github.com/golang/dep/internal/fs/testdata/symlinks/windows-file-symlink new file mode 120000 index 00000000..af1d6c8f --- /dev/null +++ b/vendor/github.com/golang/dep/internal/fs/testdata/symlinks/windows-file-symlink @@ -0,0 +1 @@ +C:/Users/ibrahim/go/src/github.com/golang/dep/internal/fs/testdata/test.file \ No newline at end of file diff --git a/vendor/github.com/golang/dep/internal/fs/testdata/test.file b/vendor/github.com/golang/dep/internal/fs/testdata/test.file new file mode 100644 index 00000000..e69de29b diff --git a/vendor/github.com/golang/dep/internal/importers/base/importer.go b/vendor/github.com/golang/dep/internal/importers/base/importer.go new file mode 100644 index 00000000..82dff700 --- /dev/null +++ b/vendor/github.com/golang/dep/internal/importers/base/importer.go @@ -0,0 +1,333 @@ +// Copyright 2017 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 base + +import ( + "log" + "strings" + + "github.com/golang/dep" + "github.com/golang/dep/gps" + fb "github.com/golang/dep/internal/feedback" + "github.com/pkg/errors" +) + +// Importer provides a common implementation for importing from other +// dependency managers. +type Importer struct { + SourceManager gps.SourceManager + Logger *log.Logger + Verbose bool + Manifest *dep.Manifest + Lock *dep.Lock +} + +// NewImporter creates a new Importer for embedding in an importer. +func NewImporter(logger *log.Logger, verbose bool, sm gps.SourceManager) *Importer { + return &Importer{ + Logger: logger, + Verbose: verbose, + Manifest: dep.NewManifest(), + Lock: &dep.Lock{}, + SourceManager: sm, + } +} + +// isTag determines if the specified value is a tag (plain or semver). +func (i *Importer) isTag(pi gps.ProjectIdentifier, value string) (bool, gps.Version, error) { + versions, err := i.SourceManager.ListVersions(pi) + if err != nil { + return false, nil, errors.Wrapf(err, "unable to list versions for %s(%s)", pi.ProjectRoot, pi.Source) + } + + for _, version := range versions { + if version.Type() != gps.IsVersion && version.Type() != gps.IsSemver { + continue + } + + if value == version.String() { + return true, version, nil + } + } + + return false, nil, nil +} + +// lookupVersionForLockedProject figures out the appropriate version for a locked +// project based on the locked revision and the constraint from the manifest. +// First try matching the revision to a version, then try the constraint from the +// manifest, then finally the revision. +func (i *Importer) lookupVersionForLockedProject(pi gps.ProjectIdentifier, c gps.Constraint, rev gps.Revision) (gps.Version, error) { + // Find the version that goes with this revision, if any + versions, err := i.SourceManager.ListVersions(pi) + if err != nil { + return rev, errors.Wrapf(err, "Unable to lookup the version represented by %s in %s(%s). Falling back to locking the revision only.", rev, pi.ProjectRoot, pi.Source) + } + + var branchConstraint gps.PairedVersion + gps.SortPairedForUpgrade(versions) // Sort versions in asc order + matches := []gps.Version{} + for _, v := range versions { + if v.Revision() == rev { + matches = append(matches, v) + } + if c != nil && v.Type() == gps.IsBranch && v.String() == c.String() { + branchConstraint = v + } + } + + // Try to narrow down the matches with the constraint. Otherwise return the first match. + if len(matches) > 0 { + if c != nil { + for _, v := range matches { + if i.testConstraint(c, v) { + return v, nil + } + } + } + return matches[0], nil + } + + // Use branch constraint from the manifest + if branchConstraint != nil { + return branchConstraint.Unpair().Pair(rev), nil + } + + // Give up and lock only to a revision + return rev, nil +} + +// ImportedPackage is a common intermediate representation of a package imported +// from an external tool's configuration. +type ImportedPackage struct { + // Required. The package path, not necessarily the project root. + Name string + + // Required. Text representing a revision or tag. + LockHint string + + // Optional. Alternative source, or fork, for the project. + Source string + + // Optional. Text representing a branch or version. + ConstraintHint string +} + +// importedProject is a consolidated representation of a set of imported packages +// for the same project root. +type importedProject struct { + Root gps.ProjectRoot + ImportedPackage +} + +// loadPackages consolidates all package references into a set of project roots. +func (i *Importer) loadPackages(packages []ImportedPackage) []importedProject { + // preserve the original order of the packages so that messages that + // are printed as they are processed are in a consistent order. + orderedProjects := make([]importedProject, 0, len(packages)) + + projects := make(map[gps.ProjectRoot]*importedProject, len(packages)) + for _, pkg := range packages { + pr, err := i.SourceManager.DeduceProjectRoot(pkg.Name) + if err != nil { + i.Logger.Printf( + " Warning: Skipping project. Cannot determine the project root for %s: %s\n", + pkg.Name, err, + ) + continue + } + pkg.Name = string(pr) + + prj, exists := projects[pr] + if !exists { + prj := importedProject{pr, pkg} + orderedProjects = append(orderedProjects, prj) + projects[pr] = &orderedProjects[len(orderedProjects)-1] + continue + } + + // The config found first "wins", though we allow for incrementally + // setting each field because some importers have a config and lock file. + if prj.Source == "" && pkg.Source != "" { + prj.Source = pkg.Source + } + + if prj.ConstraintHint == "" && pkg.ConstraintHint != "" { + prj.ConstraintHint = pkg.ConstraintHint + } + + if prj.LockHint == "" && pkg.LockHint != "" { + prj.LockHint = pkg.LockHint + } + } + + return orderedProjects +} + +// ImportPackages loads imported packages into the manifest and lock. +// - defaultConstraintFromLock specifies if a constraint should be defaulted +// based on the locked version when there wasn't a constraint hint. +// +// Rules: +// * When a constraint is ignored, default to *. +// * HEAD revisions default to the matching branch. +// * Semantic versions default to ^VERSION. +// * Revision constraints are ignored. +// * Versions that don't satisfy the constraint, drop the constraint. +// * Untagged revisions ignore non-branch constraint hints. +func (i *Importer) ImportPackages(packages []ImportedPackage, defaultConstraintFromLock bool) { + projects := i.loadPackages(packages) + + for _, prj := range projects { + source := prj.Source + if len(source) > 0 { + isDefault, err := i.isDefaultSource(prj.Root, source) + if err != nil { + i.Logger.Printf(" Ignoring imported source %s for %s: %s", source, prj.Root, err.Error()) + source = "" + } else if isDefault { + source = "" + } else if strings.Contains(source, "/vendor/") { + i.Logger.Printf(" Ignoring imported source %s for %s because vendored sources aren't supported", source, prj.Root) + source = "" + } + } + + pc := gps.ProjectConstraint{ + Ident: gps.ProjectIdentifier{ + ProjectRoot: prj.Root, + Source: source, + }, + } + + var err error + pc.Constraint, err = i.SourceManager.InferConstraint(prj.ConstraintHint, pc.Ident) + if err != nil { + pc.Constraint = gps.Any() + } + + var version gps.Version + if prj.LockHint != "" { + var isTag bool + // Determine if the lock hint is a revision or tag + isTag, version, err = i.isTag(pc.Ident, prj.LockHint) + if err != nil { + i.Logger.Printf( + " Warning: Skipping project. Unable to import lock %q for %v: %s\n", + prj.LockHint, pc.Ident, err, + ) + continue + } + // If the hint is a revision, check if it is tagged + if !isTag { + revision := gps.Revision(prj.LockHint) + version, err = i.lookupVersionForLockedProject(pc.Ident, pc.Constraint, revision) + if err != nil { + version = nil + i.Logger.Println(err) + } + } + + // Default the constraint based on the locked version + if defaultConstraintFromLock && prj.ConstraintHint == "" && version != nil { + c := i.convertToConstraint(version) + if c != nil { + pc.Constraint = c + } + } + } + + // Ignore pinned constraints + if i.isConstraintPinned(pc.Constraint) { + if i.Verbose { + i.Logger.Printf(" Ignoring pinned constraint %v for %v.\n", pc.Constraint, pc.Ident) + } + pc.Constraint = gps.Any() + } + + // Ignore constraints which conflict with the locked revision, so that + // solve doesn't later change the revision to satisfy the constraint. + if !i.testConstraint(pc.Constraint, version) { + if i.Verbose { + i.Logger.Printf(" Ignoring constraint %v for %v because it would invalidate the locked version %v.\n", pc.Constraint, pc.Ident, version) + } + pc.Constraint = gps.Any() + } + + // Add constraint to manifest that is not empty (has a branch, version or source) + if !gps.IsAny(pc.Constraint) || pc.Ident.Source != "" { + i.Manifest.Constraints[pc.Ident.ProjectRoot] = gps.ProjectProperties{ + Source: pc.Ident.Source, + Constraint: pc.Constraint, + } + fb.NewConstraintFeedback(pc, fb.DepTypeImported).LogFeedback(i.Logger) + } + + if version != nil { + lp := gps.NewLockedProject(pc.Ident, version, nil) + i.Lock.P = append(i.Lock.P, lp) + fb.NewLockedProjectFeedback(lp, fb.DepTypeImported).LogFeedback(i.Logger) + } + } +} + +// isConstraintPinned returns if a constraint is pinned to a specific revision. +func (i *Importer) isConstraintPinned(c gps.Constraint) bool { + if version, isVersion := c.(gps.Version); isVersion { + switch version.Type() { + case gps.IsRevision, gps.IsVersion: + return true + } + } + return false +} + +// testConstraint verifies that the constraint won't invalidate the locked version. +func (i *Importer) testConstraint(c gps.Constraint, v gps.Version) bool { + // Assume branch constraints are satisfied + if version, isVersion := c.(gps.Version); isVersion { + if version.Type() == gps.IsBranch { + + return true + } + } + + return c.Matches(v) +} + +// convertToConstraint turns a version into a constraint. +// Semver tags are converted to a range with the caret operator. +func (i *Importer) convertToConstraint(v gps.Version) gps.Constraint { + if v.Type() == gps.IsSemver { + c, err := gps.NewSemverConstraintIC(v.String()) + if err != nil { + // This should never fail, because the type is semver. + // If it does fail somehow, don't let that impact the import. + return nil + } + return c + } + return v +} + +func (i *Importer) isDefaultSource(projectRoot gps.ProjectRoot, sourceURL string) (bool, error) { + // this condition is mainly for gopkg.in imports, + // as some importers specify the repository url as https://gopkg.in/..., + // but SourceManager.SourceURLsForPath() returns https://github.com/... urls for gopkg.in + if sourceURL == "https://"+string(projectRoot) { + return true, nil + } + + sourceURLs, err := i.SourceManager.SourceURLsForPath(string(projectRoot)) + if err != nil { + return false, err + } + // The first url in the slice will be the default one (usually https://...) + if len(sourceURLs) > 0 && sourceURL == sourceURLs[0].String() { + return true, nil + } + + return false, nil +} diff --git a/vendor/github.com/golang/dep/internal/importers/base/importer_test.go b/vendor/github.com/golang/dep/internal/importers/base/importer_test.go new file mode 100644 index 00000000..448bccdd --- /dev/null +++ b/vendor/github.com/golang/dep/internal/importers/base/importer_test.go @@ -0,0 +1,443 @@ +// Copyright 2016 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 base + +import ( + "fmt" + "log" + "testing" + + "github.com/golang/dep" + "github.com/golang/dep/gps" + "github.com/golang/dep/internal/importers/importertest" + "github.com/golang/dep/internal/test" +) + +func TestBaseImporter_IsTag(t *testing.T) { + testcases := map[string]struct { + input string + wantIsTag bool + wantTag gps.Version + }{ + "non-semver tag": { + input: importertest.Beta1Tag, + wantIsTag: true, + wantTag: gps.NewVersion(importertest.Beta1Tag).Pair(importertest.Beta1Rev), + }, + "semver-tag": { + input: importertest.V1PatchTag, + wantIsTag: true, + wantTag: gps.NewVersion(importertest.V1PatchTag).Pair(importertest.V1PatchRev)}, + "untagged revision": { + input: importertest.UntaggedRev, + wantIsTag: false, + }, + "branch name": { + input: importertest.V2Branch, + wantIsTag: false, + }, + "empty": { + input: "", + wantIsTag: false, + }, + } + + pi := gps.ProjectIdentifier{ProjectRoot: importertest.Project} + + for name, tc := range testcases { + name := name + tc := tc + t.Run(name, func(t *testing.T) { + h := test.NewHelper(t) + defer h.Cleanup() + // Disable parallel tests until we can resolve this error on the Windows builds: + // "remote repository at https://github.com/carolynvs/deptest-importers does not exist, or is inaccessible" + //h.Parallel() + + ctx := importertest.NewTestContext(h) + sm, err := ctx.SourceManager() + h.Must(err) + defer sm.Release() + + i := NewImporter(ctx.Err, ctx.Verbose, sm) + gotIsTag, gotTag, err := i.isTag(pi, tc.input) + h.Must(err) + + if tc.wantIsTag != gotIsTag { + t.Fatalf("unexpected isTag result for %v: \n\t(GOT) %v \n\t(WNT) %v", + tc.input, gotIsTag, tc.wantIsTag) + } + + if tc.wantTag != gotTag { + t.Fatalf("unexpected tag for %v: \n\t(GOT) %v \n\t(WNT) %v", + tc.input, gotTag, tc.wantTag) + } + }) + } +} + +func TestBaseImporter_LookupVersionForLockedProject(t *testing.T) { + testcases := map[string]struct { + revision gps.Revision + constraint gps.Constraint + wantVersion string + }{ + "match revision to tag": { + revision: importertest.V1PatchRev, + wantVersion: importertest.V1PatchTag, + }, + "match revision with multiple tags using constraint": { + revision: importertest.MultiTaggedRev, + constraint: gps.NewVersion(importertest.MultiTaggedPlainTag), + wantVersion: importertest.MultiTaggedPlainTag, + }, + "revision with multiple tags with no constraint defaults to best match": { + revision: importertest.MultiTaggedRev, + wantVersion: importertest.MultiTaggedSemverTag, + }, + "revision with multiple tags with nonmatching constraint defaults to best match": { + revision: importertest.MultiTaggedRev, + constraint: gps.NewVersion("thismatchesnothing"), + wantVersion: importertest.MultiTaggedSemverTag, + }, + "untagged revision fallback to branch constraint": { + revision: importertest.UntaggedRev, + constraint: gps.NewBranch("master"), + wantVersion: "master", + }, + "fallback to revision": { + revision: importertest.UntaggedRev, + wantVersion: importertest.UntaggedRev, + }, + } + + pi := gps.ProjectIdentifier{ProjectRoot: importertest.Project} + + for name, tc := range testcases { + name := name + tc := tc + t.Run(name, func(t *testing.T) { + h := test.NewHelper(t) + defer h.Cleanup() + // Disable parallel tests until we can resolve this error on the Windows builds: + // "remote repository at https://github.com/carolynvs/deptest-importers does not exist, or is inaccessible" + //h.Parallel() + + ctx := importertest.NewTestContext(h) + sm, err := ctx.SourceManager() + h.Must(err) + defer sm.Release() + + i := NewImporter(ctx.Err, ctx.Verbose, sm) + v, err := i.lookupVersionForLockedProject(pi, tc.constraint, tc.revision) + h.Must(err) + + gotVersion := v.String() + if gotVersion != tc.wantVersion { + t.Fatalf("unexpected locked version: \n\t(GOT) %v\n\t(WNT) %v", gotVersion, tc.wantVersion) + } + }) + } +} + +func TestBaseImporter_ImportProjects(t *testing.T) { + testcases := map[string]struct { + importertest.TestCase + projects []ImportedPackage + }{ + "tag constraints are skipped": { + importertest.TestCase{ + WantVersion: importertest.Beta1Tag, + WantRevision: importertest.Beta1Rev, + }, + []ImportedPackage{ + { + Name: importertest.Project, + LockHint: importertest.Beta1Rev, + ConstraintHint: importertest.Beta1Tag, + }, + }, + }, + "tag lock hints Lock to tagged revision": { + importertest.TestCase{ + WantVersion: importertest.Beta1Tag, + WantRevision: importertest.Beta1Rev, + }, + []ImportedPackage{ + { + Name: importertest.Project, + LockHint: importertest.Beta1Tag, + }, + }, + }, + "untagged revision ignores range constraint": { + importertest.TestCase{ + WantRevision: importertest.UntaggedRev, + }, + []ImportedPackage{ + { + Name: importertest.Project, + LockHint: importertest.UntaggedRev, + ConstraintHint: importertest.V1Constraint, + }, + }, + }, + "untagged revision keeps branch constraint": { + importertest.TestCase{ + WantConstraint: "master", + WantVersion: "master", + WantRevision: importertest.UntaggedRev, + }, + []ImportedPackage{ + { + Name: importertest.Project, + LockHint: importertest.UntaggedRev, + ConstraintHint: "master", + }, + }, + }, + "HEAD revisions default constraint to the matching branch": { + importertest.TestCase{ + DefaultConstraintFromLock: true, + WantConstraint: importertest.V2Branch, + WantVersion: importertest.V2Branch, + WantRevision: importertest.V2Rev, + }, + []ImportedPackage{ + { + Name: importertest.Project, + LockHint: importertest.V2Rev, + }, + }, + }, + "Semver tagged revisions default to ^VERSION": { + importertest.TestCase{ + DefaultConstraintFromLock: true, + WantConstraint: importertest.V1Constraint, + WantVersion: importertest.V1Tag, + WantRevision: importertest.V1Rev, + }, + []ImportedPackage{ + { + Name: importertest.Project, + LockHint: importertest.V1Rev, + }, + }, + }, + "Semver lock hint defaults constraint to ^VERSION": { + importertest.TestCase{ + DefaultConstraintFromLock: true, + WantConstraint: importertest.V1Constraint, + WantVersion: importertest.V1Tag, + WantRevision: importertest.V1Rev, + }, + []ImportedPackage{ + { + Name: importertest.Project, + LockHint: importertest.V1Tag, + }, + }, + }, + "Semver constraint hint": { + importertest.TestCase{ + WantConstraint: importertest.V1Constraint, + WantVersion: importertest.V1PatchTag, + WantRevision: importertest.V1PatchRev, + }, + []ImportedPackage{ + { + Name: importertest.Project, + LockHint: importertest.V1PatchRev, + ConstraintHint: importertest.V1Constraint, + }, + }, + }, + "Semver prerelease lock hint": { + importertest.TestCase{ + WantConstraint: importertest.V2Branch, + WantVersion: importertest.V2PatchTag, + WantRevision: importertest.V2PatchRev, + }, + []ImportedPackage{ + { + Name: importertest.Project, + LockHint: importertest.V2PatchRev, + ConstraintHint: importertest.V2Branch, + }, + }, + }, + "Revision constraints are skipped": { + importertest.TestCase{ + WantVersion: importertest.V1Tag, + WantRevision: importertest.V1Rev, + }, + []ImportedPackage{ + { + Name: importertest.Project, + LockHint: importertest.V1Rev, + ConstraintHint: importertest.V1Rev, + }, + }, + }, + "Branch constraint hint": { + importertest.TestCase{ + WantConstraint: "master", + WantVersion: importertest.V1Tag, + WantRevision: importertest.V1Rev, + }, + []ImportedPackage{ + { + Name: importertest.Project, + LockHint: importertest.V1Rev, + ConstraintHint: "master", + }, + }, + }, + "Non-matching semver constraint is skipped": { + importertest.TestCase{ + WantVersion: importertest.V1Tag, + WantRevision: importertest.V1Rev, + }, + []ImportedPackage{ + { + Name: importertest.Project, + LockHint: importertest.V1Rev, + ConstraintHint: "^2.0.0", + }, + }, + }, + "git describe constraint is skipped": { + importertest.TestCase{ + WantRevision: importertest.UntaggedRev, + }, + []ImportedPackage{ + { + Name: importertest.Project, + LockHint: importertest.UntaggedRev, + ConstraintHint: importertest.UntaggedRevAbbrv, + }, + }, + }, + "consolidate subpackages under root": { + importertest.TestCase{ + WantConstraint: "master", + WantVersion: "master", + WantRevision: importertest.UntaggedRev, + }, + []ImportedPackage{ + { + Name: importertest.Project + "/subpkA", + ConstraintHint: "master", + }, + { + Name: importertest.Project, + LockHint: importertest.UntaggedRev, + }, + }, + }, + "skip duplicate packages": { + importertest.TestCase{ + WantRevision: importertest.UntaggedRev, + }, + []ImportedPackage{ + { + Name: importertest.Project + "/subpkgA", + LockHint: importertest.UntaggedRev, // first wins + }, + { + Name: importertest.Project + "/subpkgB", + LockHint: importertest.V1Rev, + }, + }, + }, + "skip empty lock hints": { + importertest.TestCase{ + WantRevision: "", + }, + []ImportedPackage{ + { + Name: importertest.Project, + LockHint: "", + }, + }, + }, + "alternate source": { + importertest.TestCase{ + WantConstraint: "*", + WantSourceRepo: importertest.ProjectSrc, + }, + []ImportedPackage{ + { + Name: importertest.Project, + Source: importertest.ProjectSrc, + }, + }, + }, + "skip default source": { + importertest.TestCase{ + WantSourceRepo: "", + }, + []ImportedPackage{ + { + Name: importertest.Project, + Source: "https://" + importertest.Project, + }, + }, + }, + "skip vendored source": { + importertest.TestCase{ + WantSourceRepo: "", + WantWarning: "vendored sources aren't supported", + }, + []ImportedPackage{ + { + Name: importertest.Project, + Source: "example.com/vendor/" + importertest.Project, + }, + }, + }, + "invalid project root": { + importertest.TestCase{ + WantSourceRepo: "", + WantWarning: "Warning: Skipping project. Cannot determine the project root for invalid-project", + }, + []ImportedPackage{ + { + Name: "invalid-project", + }, + }, + }, + "nonexistent project": { + importertest.TestCase{ + WantSourceRepo: "", + WantWarning: fmt.Sprintf( + "Warning: Skipping project. Unable to import lock %q for %s", + importertest.V1Tag, importertest.NonexistentPrj, + ), + }, + []ImportedPackage{ + { + Name: importertest.NonexistentPrj, + LockHint: importertest.V1Tag, + }, + }, + }, + } + + for name, tc := range testcases { + name := name + tc := tc + t.Run(name, func(t *testing.T) { + err := tc.Execute(t, func(logger *log.Logger, sm gps.SourceManager) (*dep.Manifest, *dep.Lock) { + i := NewImporter(logger, true, sm) + i.ImportPackages(tc.projects, tc.DefaultConstraintFromLock) + return i.Manifest, i.Lock + }) + if err != nil { + t.Fatalf("%#v", err) + } + }) + } +} diff --git a/vendor/github.com/golang/dep/internal/importers/glide/importer.go b/vendor/github.com/golang/dep/internal/importers/glide/importer.go new file mode 100644 index 00000000..ebaa3e2d --- /dev/null +++ b/vendor/github.com/golang/dep/internal/importers/glide/importer.go @@ -0,0 +1,211 @@ +// Copyright 2016 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 glide + +import ( + "bytes" + "io/ioutil" + "log" + "os" + "path" + "path/filepath" + + "github.com/go-yaml/yaml" + "github.com/golang/dep" + "github.com/golang/dep/gps" + "github.com/golang/dep/internal/fs" + "github.com/golang/dep/internal/importers/base" + "github.com/pkg/errors" +) + +const glideYamlName = "glide.yaml" +const glideLockName = "glide.lock" + +// Importer imports glide configuration into the dep configuration format. +type Importer struct { + *base.Importer + glideConfig glideYaml + glideLock glideLock + lockFound bool +} + +// NewImporter for glide. +func NewImporter(logger *log.Logger, verbose bool, sm gps.SourceManager) *Importer { + return &Importer{Importer: base.NewImporter(logger, verbose, sm)} +} + +type glideYaml struct { + Name string `yaml:"package"` + Ignores []string `yaml:"ignore"` + ExcludeDirs []string `yaml:"excludeDirs"` + Imports []glidePackage `yaml:"import"` + TestImports []glidePackage `yaml:"testImport"` +} + +type glideLock struct { + Imports []glideLockedPackage `yaml:"imports"` + TestImports []glideLockedPackage `yaml:"testImports"` +} + +type glidePackage struct { + Name string `yaml:"package"` + Reference string `yaml:"version"` // could contain a semver, tag or branch + Repository string `yaml:"repo"` + + // Unsupported fields that we will warn if used + Subpackages []string `yaml:"subpackages"` + OS string `yaml:"os"` + Arch string `yaml:"arch"` +} + +type glideLockedPackage struct { + Name string `yaml:"name"` + Revision string `yaml:"version"` + Repository string `yaml:"repo"` +} + +// Name of the importer. +func (g *Importer) Name() string { + return "glide" +} + +// HasDepMetadata checks if a directory contains config that the importer can handle. +func (g *Importer) HasDepMetadata(dir string) bool { + // Only require glide.yaml, the lock is optional + y := filepath.Join(dir, glideYamlName) + if _, err := os.Stat(y); err != nil { + return false + } + + return true +} + +// Import the config found in the directory. +func (g *Importer) Import(dir string, pr gps.ProjectRoot) (*dep.Manifest, *dep.Lock, error) { + err := g.load(dir) + if err != nil { + return nil, nil, err + } + + m, l := g.convert(pr) + return m, l, nil +} + +// load the glide configuration files. Failure to load `glide.yaml` is considered +// unrecoverable and an error is returned for it. But if there is any error while trying +// to load the lock file, only a warning is logged. +func (g *Importer) load(projectDir string) error { + g.Logger.Println("Detected glide configuration files...") + y := filepath.Join(projectDir, glideYamlName) + if g.Verbose { + g.Logger.Printf(" Loading %s", y) + } + yb, err := ioutil.ReadFile(y) + if err != nil { + return errors.Wrapf(err, "unable to read %s", y) + } + err = yaml.Unmarshal(yb, &g.glideConfig) + if err != nil { + return errors.Wrapf(err, "unable to parse %s", y) + } + + l := filepath.Join(projectDir, glideLockName) + if exists, _ := fs.IsRegular(l); exists { + if g.Verbose { + g.Logger.Printf(" Loading %s", l) + } + lb, err := ioutil.ReadFile(l) + if err != nil { + g.Logger.Printf(" Warning: Ignoring lock file. Unable to read %s: %s\n", l, err) + return nil + } + lock := glideLock{} + err = yaml.Unmarshal(lb, &lock) + if err != nil { + g.Logger.Printf(" Warning: Ignoring lock file. Unable to parse %s: %s\n", l, err) + return nil + } + g.lockFound = true + g.glideLock = lock + } + + return nil +} + +// convert the glide configuration files into dep configuration files. +func (g *Importer) convert(pr gps.ProjectRoot) (*dep.Manifest, *dep.Lock) { + projectName := string(pr) + + task := bytes.NewBufferString("Converting from glide.yaml") + if g.lockFound { + task.WriteString(" and glide.lock") + } + task.WriteString("...") + g.Logger.Println(task) + + numPkgs := len(g.glideConfig.Imports) + len(g.glideConfig.TestImports) + len(g.glideLock.Imports) + len(g.glideLock.TestImports) + packages := make([]base.ImportedPackage, 0, numPkgs) + + // Constraints + for _, pkg := range append(g.glideConfig.Imports, g.glideConfig.TestImports...) { + // Validate + if pkg.Name == "" { + g.Logger.Println( + " Warning: Skipping project. Invalid glide configuration, Name is required", + ) + continue + } + + // Warn + if g.Verbose { + if pkg.OS != "" { + g.Logger.Printf(" The %s package specified an os, but that isn't supported by dep yet, and will be ignored. See https://github.com/golang/dep/issues/291.\n", pkg.Name) + } + if pkg.Arch != "" { + g.Logger.Printf(" The %s package specified an arch, but that isn't supported by dep yet, and will be ignored. See https://github.com/golang/dep/issues/291.\n", pkg.Name) + } + } + + ip := base.ImportedPackage{ + Name: pkg.Name, + Source: pkg.Repository, + ConstraintHint: pkg.Reference, + } + packages = append(packages, ip) + } + + // Locks + for _, pkg := range append(g.glideLock.Imports, g.glideLock.TestImports...) { + // Validate + if pkg.Name == "" { + g.Logger.Println(" Warning: Skipping project. Invalid glide lock, Name is required") + continue + } + + ip := base.ImportedPackage{ + Name: pkg.Name, + Source: pkg.Repository, + LockHint: pkg.Revision, + } + packages = append(packages, ip) + } + + g.ImportPackages(packages, false) + + // Ignores + g.Manifest.Ignored = append(g.Manifest.Ignored, g.glideConfig.Ignores...) + if len(g.glideConfig.ExcludeDirs) > 0 { + if g.glideConfig.Name != "" && g.glideConfig.Name != projectName { + g.Logger.Printf(" Glide thinks the package is '%s' but dep thinks it is '%s', using dep's value.\n", g.glideConfig.Name, projectName) + } + + for _, dir := range g.glideConfig.ExcludeDirs { + pkg := path.Join(projectName, dir) + g.Manifest.Ignored = append(g.Manifest.Ignored, pkg) + } + } + + return g.Manifest, g.Lock +} diff --git a/vendor/github.com/golang/dep/internal/importers/glide/importer_test.go b/vendor/github.com/golang/dep/internal/importers/glide/importer_test.go new file mode 100644 index 00000000..a51f2a9b --- /dev/null +++ b/vendor/github.com/golang/dep/internal/importers/glide/importer_test.go @@ -0,0 +1,222 @@ +// Copyright 2016 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 glide + +import ( + "bytes" + "log" + "path/filepath" + "testing" + + "github.com/golang/dep" + "github.com/golang/dep/gps" + "github.com/golang/dep/internal/importers/importertest" + "github.com/golang/dep/internal/test" + "github.com/pkg/errors" +) + +func TestGlideConfig_Convert(t *testing.T) { + testCases := map[string]struct { + yaml glideYaml + lock glideLock + importertest.TestCase + }{ + "project": { + glideYaml{ + Imports: []glidePackage{ + { + Name: importertest.Project, + Repository: importertest.ProjectSrc, + Reference: importertest.V2Branch, + }, + }, + }, + glideLock{ + Imports: []glideLockedPackage{ + { + Name: importertest.Project, + Repository: importertest.ProjectSrc, + Revision: importertest.V2PatchRev, + }, + }, + }, + importertest.TestCase{ + WantSourceRepo: importertest.ProjectSrc, + WantConstraint: importertest.V2Branch, + WantRevision: importertest.V2PatchRev, + WantVersion: importertest.V2PatchTag, + }, + }, + "test project": { + glideYaml{ + Imports: []glidePackage{ + { + Name: importertest.Project, + Repository: importertest.ProjectSrc, + Reference: importertest.V2Branch, + }, + }, + }, + glideLock{ + Imports: []glideLockedPackage{ + { + Name: importertest.Project, + Repository: importertest.ProjectSrc, + Revision: importertest.V2PatchRev, + }, + }, + }, + importertest.TestCase{ + WantSourceRepo: importertest.ProjectSrc, + WantConstraint: importertest.V2Branch, + WantRevision: importertest.V2PatchRev, + WantVersion: importertest.V2PatchTag, + }, + }, + "yaml only": { + glideYaml{ + Imports: []glidePackage{ + { + Name: importertest.Project, + Repository: importertest.ProjectSrc, + Reference: importertest.V2Branch, + }, + }, + }, + glideLock{}, + importertest.TestCase{ + WantSourceRepo: importertest.ProjectSrc, + WantConstraint: importertest.V2Branch, + }, + }, + "ignored package": { + glideYaml{ + Ignores: []string{importertest.Project}, + }, + glideLock{}, + importertest.TestCase{ + WantIgnored: []string{importertest.Project}, + }, + }, + "exclude dir": { + glideYaml{ + ExcludeDirs: []string{"samples"}, + }, + glideLock{}, + importertest.TestCase{ + WantIgnored: []string{importertest.RootProject + "/samples"}, + }, + }, + "exclude dir ignores mismatched package name": { + glideYaml{ + Name: "github.com/golang/mismatched-package-name", + ExcludeDirs: []string{"samples"}, + }, + glideLock{}, + importertest.TestCase{ + WantIgnored: []string{importertest.RootProject + "/samples"}, + }, + }, + "missing package name": { + glideYaml{ + Imports: []glidePackage{{Name: ""}}, + }, + glideLock{}, + importertest.TestCase{ + WantWarning: "Warning: Skipping project. Invalid glide configuration, Name is required", + }, + }, + "warn unused os field": { + glideYaml{ + Imports: []glidePackage{ + { + Name: importertest.Project, + OS: "windows", + }, + }}, + glideLock{}, + importertest.TestCase{ + WantWarning: "specified an os", + }, + }, + "warn unused arch field": { + glideYaml{ + Imports: []glidePackage{ + { + Name: importertest.Project, + Arch: "i686", + }, + }}, + glideLock{}, + importertest.TestCase{ + WantWarning: "specified an arch", + }, + }, + } + + for name, testCase := range testCases { + name := name + testCase := testCase + t.Run(name, func(t *testing.T) { + err := testCase.Execute(t, func(logger *log.Logger, sm gps.SourceManager) (*dep.Manifest, *dep.Lock) { + g := NewImporter(logger, true, sm) + g.glideConfig = testCase.yaml + g.glideLock = testCase.lock + return g.convert(importertest.RootProject) + }) + if err != nil { + t.Fatalf("%#v", err) + } + }) + } +} + +func TestGlideConfig_Import(t *testing.T) { + h := test.NewHelper(t) + defer h.Cleanup() + + ctx := importertest.NewTestContext(h) + sm, err := ctx.SourceManager() + h.Must(err) + defer sm.Release() + + h.TempDir(filepath.Join("src", importertest.RootProject)) + h.TempCopy(filepath.Join(importertest.RootProject, glideYamlName), "glide.yaml") + h.TempCopy(filepath.Join(importertest.RootProject, glideLockName), "glide.lock") + projectRoot := h.Path(importertest.RootProject) + + // Capture stderr so we can verify output + verboseOutput := &bytes.Buffer{} + ctx.Err = log.New(verboseOutput, "", 0) + + g := NewImporter(ctx.Err, false, sm) // Disable verbose so that we don't print values that change each test run + if !g.HasDepMetadata(projectRoot) { + t.Fatal("Expected the importer to detect the glide configuration files") + } + + m, l, err := g.Import(projectRoot, importertest.RootProject) + h.Must(err) + + if m == nil { + t.Fatal("Expected the manifest to be generated") + } + + if l == nil { + t.Fatal("Expected the lock to be generated") + } + + goldenFile := "golden.txt" + got := verboseOutput.String() + want := h.GetTestFileString(goldenFile) + if want != got { + if *test.UpdateGolden { + if err := h.WriteTestFile(goldenFile, got); err != nil { + t.Fatalf("%+v", errors.Wrapf(err, "Unable to write updated golden file %s", goldenFile)) + } + } else { + t.Fatalf("want %s, got %s", want, got) + } + } +} diff --git a/vendor/github.com/golang/dep/internal/importers/glide/testdata/glide.lock b/vendor/github.com/golang/dep/internal/importers/glide/testdata/glide.lock new file mode 100644 index 00000000..0fae0660 --- /dev/null +++ b/vendor/github.com/golang/dep/internal/importers/glide/testdata/glide.lock @@ -0,0 +1,12 @@ +hash: 16053c82a71f9bd509b05a4523df6bc418aed2083e4b8bd97a870bbc003256f8 +updated: 2017-03-07T17:02:32.214383898-06:00 +imports: +- name: github.com/sdboyer/deptest + repo: https://github.com/sdboyer/deptest.git + vcs: git + version: 3f4c3bea144e112a69bbe5d8d01c1b09a544253f +- name: github.com/sdboyer/deptestdos + version: 5c607206be5decd28e6263ffffdcee067266015e +testImports: +- name: github.com/golang/lint + version: cb00e5669539f047b2f4c53a421a01b0c8e172c6 diff --git a/vendor/github.com/golang/dep/internal/importers/glide/testdata/glide.yaml b/vendor/github.com/golang/dep/internal/importers/glide/testdata/glide.yaml new file mode 100644 index 00000000..88a3f2be --- /dev/null +++ b/vendor/github.com/golang/dep/internal/importers/glide/testdata/glide.yaml @@ -0,0 +1,20 @@ +package: github.com/golang/notexist +homepage: http://example.com +license: MIT +owners: +- name: Sam Boyer + email: sdboyer@example.com + homepage: http://sdboyer.io +ignore: +- github.com/sdboyer/dep-test +excludeDirs: +- samples +import: +- package: github.com/sdboyer/deptest + repo: https://github.com/sdboyer/deptest.git + vcs: git + version: master +- package: github.com/sdboyer/deptestdos + version: v2.0.0 +testImport: +- package: github.com/golang/lint diff --git a/vendor/github.com/golang/dep/internal/importers/glide/testdata/golden.txt b/vendor/github.com/golang/dep/internal/importers/glide/testdata/golden.txt new file mode 100644 index 00000000..b8a0e65c --- /dev/null +++ b/vendor/github.com/golang/dep/internal/importers/glide/testdata/golden.txt @@ -0,0 +1,7 @@ +Detected glide configuration files... +Converting from glide.yaml and glide.lock... + Using master as initial constraint for imported dep github.com/sdboyer/deptest + Trying v0.8.1 (3f4c3be) as initial lock for imported dep github.com/sdboyer/deptest + Using ^2.0.0 as initial constraint for imported dep github.com/sdboyer/deptestdos + Trying v2.0.0 (5c60720) as initial lock for imported dep github.com/sdboyer/deptestdos + Trying * (cb00e56) as initial lock for imported dep github.com/golang/lint diff --git a/vendor/github.com/golang/dep/internal/importers/glock/importer.go b/vendor/github.com/golang/dep/internal/importers/glock/importer.go new file mode 100644 index 00000000..6120d459 --- /dev/null +++ b/vendor/github.com/golang/dep/internal/importers/glock/importer.go @@ -0,0 +1,150 @@ +// Copyright 2016 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 glock + +import ( + "bufio" + "fmt" + "log" + "os" + "path/filepath" + "strings" + + "github.com/golang/dep" + "github.com/golang/dep/gps" + "github.com/golang/dep/internal/importers/base" + "github.com/pkg/errors" +) + +const glockfile = "GLOCKFILE" + +// Importer imports glock configuration into the dep configuration format. +type Importer struct { + *base.Importer + + packages []glockPackage +} + +// NewImporter for glock. +func NewImporter(logger *log.Logger, verbose bool, sm gps.SourceManager) *Importer { + return &Importer{Importer: base.NewImporter(logger, verbose, sm)} +} + +// Name of the importer. +func (g *Importer) Name() string { + return "glock" +} + +// HasDepMetadata checks if a directory contains config that the importer can handle. +func (g *Importer) HasDepMetadata(dir string) bool { + path := filepath.Join(dir, glockfile) + if _, err := os.Stat(path); err != nil { + return false + } + + return true +} + +// Import the config found in the directory. +func (g *Importer) Import(dir string, pr gps.ProjectRoot) (*dep.Manifest, *dep.Lock, error) { + err := g.load(dir) + if err != nil { + return nil, nil, err + } + + m, l := g.convert(pr) + return m, l, nil +} + +type glockPackage struct { + importPath string + revision string +} + +func (g *Importer) load(projectDir string) error { + g.Logger.Println("Detected glock configuration files...") + path := filepath.Join(projectDir, glockfile) + if g.Verbose { + g.Logger.Printf(" Loading %s", path) + } + + f, err := os.Open(path) + if err != nil { + return errors.Wrapf(err, "unable to open %s", path) + } + defer f.Close() + + scanner := bufio.NewScanner(f) + for scanner.Scan() { + pkg, err := parseGlockLine(scanner.Text()) + if err != nil { + g.Logger.Printf(" Warning: Skipping line. Unable to parse: %s\n", err) + continue + } + if pkg == nil { + continue + } + g.packages = append(g.packages, *pkg) + } + + if err := scanner.Err(); err != nil { + g.Logger.Printf(" Warning: Ignoring errors found while parsing %s: %s\n", path, err) + } + + return nil +} + +func parseGlockLine(line string) (*glockPackage, error) { + fields := strings.Fields(line) + switch len(fields) { + case 2: // Valid. + case 0: // Skip empty lines. + return nil, nil + default: + return nil, fmt.Errorf("invalid glock configuration: %s", line) + } + + // Skip commands. + if fields[0] == "cmd" { + return nil, nil + } + return &glockPackage{ + importPath: fields[0], + revision: fields[1], + }, nil +} + +func (g *Importer) convert(pr gps.ProjectRoot) (*dep.Manifest, *dep.Lock) { + g.Logger.Println("Converting from GLOCKFILE ...") + + packages := make([]base.ImportedPackage, 0, len(g.packages)) + for _, pkg := range g.packages { + // Validate + if pkg.importPath == "" { + g.Logger.Println( + " Warning: Skipping project. Invalid glock configuration, import path is required", + ) + continue + } + + if pkg.revision == "" { + // Do not add 'empty constraints' to the manifest. Solve will add to lock if required. + g.Logger.Printf( + " Warning: Skipping import with empty constraints. "+ + "The solve step will add the dependency to the lock if needed: %q\n", + pkg.importPath, + ) + continue + } + + packages = append(packages, base.ImportedPackage{ + Name: pkg.importPath, + LockHint: pkg.revision, + }) + } + + g.ImportPackages(packages, true) + return g.Manifest, g.Lock +} diff --git a/vendor/github.com/golang/dep/internal/importers/glock/importer_test.go b/vendor/github.com/golang/dep/internal/importers/glock/importer_test.go new file mode 100644 index 00000000..3cb8138d --- /dev/null +++ b/vendor/github.com/golang/dep/internal/importers/glock/importer_test.go @@ -0,0 +1,137 @@ +// Copyright 2016 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 glock + +import ( + "bytes" + "fmt" + "log" + "path/filepath" + "testing" + + "github.com/golang/dep" + "github.com/golang/dep/gps" + "github.com/golang/dep/internal/importers/importertest" + "github.com/golang/dep/internal/test" + "github.com/pkg/errors" +) + +func TestGlockConfig_Convert(t *testing.T) { + testCases := map[string]struct { + importertest.TestCase + packages []glockPackage + }{ + "package": { + importertest.TestCase{ + WantConstraint: importertest.V1Constraint, + WantRevision: importertest.V1Rev, + WantVersion: importertest.V1Tag, + }, + []glockPackage{ + { + importPath: importertest.Project, + revision: importertest.V1Rev, + }, + }, + }, + "missing package name": { + importertest.TestCase{ + WantWarning: "Warning: Skipping project. Invalid glock configuration, import path is required", + }, + []glockPackage{{importPath: ""}}, + }, + "missing revision": { + importertest.TestCase{ + WantWarning: fmt.Sprintf( + " Warning: Skipping import with empty constraints. "+ + "The solve step will add the dependency to the lock if needed: %q", + importertest.Project, + ), + }, + []glockPackage{{importPath: importertest.Project}}, + }, + } + + for name, testCase := range testCases { + name := name + testCase := testCase + t.Run(name, func(t *testing.T) { + err := testCase.Execute(t, func(logger *log.Logger, sm gps.SourceManager) (*dep.Manifest, *dep.Lock) { + g := NewImporter(logger, true, sm) + g.packages = testCase.packages + return g.convert(importertest.RootProject) + }) + if err != nil { + t.Fatalf("%#v", err) + } + }) + } +} + +func TestGlockConfig_LoadInvalid(t *testing.T) { + const testLine = "github.com/sdboyer/deptest 3f4c3bea144e112a69bbe5d8d01c1b09a544253f invalid" + _, err := parseGlockLine(testLine) + expected := fmt.Errorf("invalid glock configuration: %s", testLine) + if err.Error() != expected.Error() { + t.Errorf("want error %s, got %s", err, expected) + } +} + +func TestGlockConfig_LoadEmptyLine(t *testing.T) { + pkg, err := parseGlockLine("") + if err != nil { + t.Fatalf("%#v", err) + } + if pkg != nil { + t.Errorf("want package nil, got %+v", pkg) + } +} + +func TestGlockConfig_Import(t *testing.T) { + h := test.NewHelper(t) + defer h.Cleanup() + + ctx := importertest.NewTestContext(h) + sm, err := ctx.SourceManager() + h.Must(err) + defer sm.Release() + + h.TempDir(filepath.Join("src", importertest.RootProject)) + h.TempCopy(filepath.Join(importertest.RootProject, glockfile), glockfile) + projectRoot := h.Path(importertest.RootProject) + + // Capture stderr so we can verify output + verboseOutput := &bytes.Buffer{} + ctx.Err = log.New(verboseOutput, "", 0) + + g := NewImporter(ctx.Err, false, sm) // Disable verbose so that we don't print values that change each test run + if !g.HasDepMetadata(projectRoot) { + t.Fatal("Expected the importer to detect the glock configuration files") + } + + m, l, err := g.Import(projectRoot, importertest.RootProject) + h.Must(err) + + if m == nil { + t.Fatal("Expected the manifest to be generated") + } + + if l == nil { + t.Fatal("Expected the lock to be generated") + } + + goldenFile := "golden.txt" + got := verboseOutput.String() + want := h.GetTestFileString(goldenFile) + if want != got { + if *test.UpdateGolden { + if err := h.WriteTestFile(goldenFile, got); err != nil { + t.Fatalf("%+v", errors.Wrapf(err, "Unable to write updated golden file %s", goldenFile)) + } + } else { + t.Fatalf("want %s, got %s", want, got) + } + } +} diff --git a/vendor/github.com/golang/dep/internal/importers/glock/testdata/GLOCKFILE b/vendor/github.com/golang/dep/internal/importers/glock/testdata/GLOCKFILE new file mode 100644 index 00000000..27f499a4 --- /dev/null +++ b/vendor/github.com/golang/dep/internal/importers/glock/testdata/GLOCKFILE @@ -0,0 +1,3 @@ +cmd github.com/golang/lint +github.com/sdboyer/deptest 3f4c3bea144e112a69bbe5d8d01c1b09a544253f +github.com/sdboyer/deptestdos 5c607206be5decd28e6263ffffdcee067266015e diff --git a/vendor/github.com/golang/dep/internal/importers/glock/testdata/golden.txt b/vendor/github.com/golang/dep/internal/importers/glock/testdata/golden.txt new file mode 100644 index 00000000..3d7781b4 --- /dev/null +++ b/vendor/github.com/golang/dep/internal/importers/glock/testdata/golden.txt @@ -0,0 +1,6 @@ +Detected glock configuration files... +Converting from GLOCKFILE ... + Using ^0.8.1 as initial constraint for imported dep github.com/sdboyer/deptest + Trying v0.8.1 (3f4c3be) as initial lock for imported dep github.com/sdboyer/deptest + Using ^2.0.0 as initial constraint for imported dep github.com/sdboyer/deptestdos + Trying v2.0.0 (5c60720) as initial lock for imported dep github.com/sdboyer/deptestdos diff --git a/vendor/github.com/golang/dep/internal/importers/godep/importer.go b/vendor/github.com/golang/dep/internal/importers/godep/importer.go new file mode 100644 index 00000000..c3389d8c --- /dev/null +++ b/vendor/github.com/golang/dep/internal/importers/godep/importer.go @@ -0,0 +1,117 @@ +// Copyright 2017 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 godep + +import ( + "encoding/json" + "io/ioutil" + "log" + "os" + "path/filepath" + + "github.com/golang/dep" + "github.com/golang/dep/gps" + "github.com/golang/dep/internal/importers/base" + "github.com/pkg/errors" +) + +const godepPath = "Godeps" + string(os.PathSeparator) + "Godeps.json" + +// Importer imports godep configuration into the dep configuration format. +type Importer struct { + *base.Importer + json godepJSON +} + +// NewImporter for godep. +func NewImporter(logger *log.Logger, verbose bool, sm gps.SourceManager) *Importer { + return &Importer{Importer: base.NewImporter(logger, verbose, sm)} +} + +type godepJSON struct { + Imports []godepPackage `json:"Deps"` +} + +type godepPackage struct { + ImportPath string `json:"ImportPath"` + Rev string `json:"Rev"` + Comment string `json:"Comment"` +} + +// Name of the importer. +func (g *Importer) Name() string { + return "godep" +} + +// HasDepMetadata checks if a directory contains config that the importer can handle. +func (g *Importer) HasDepMetadata(dir string) bool { + y := filepath.Join(dir, godepPath) + if _, err := os.Stat(y); err != nil { + return false + } + + return true +} + +// Import the config found in the directory. +func (g *Importer) Import(dir string, pr gps.ProjectRoot) (*dep.Manifest, *dep.Lock, error) { + err := g.load(dir) + if err != nil { + return nil, nil, err + } + + m, l := g.convert(pr) + return m, l, nil +} + +func (g *Importer) load(projectDir string) error { + g.Logger.Println("Detected godep configuration files...") + j := filepath.Join(projectDir, godepPath) + if g.Verbose { + g.Logger.Printf(" Loading %s", j) + } + jb, err := ioutil.ReadFile(j) + if err != nil { + return errors.Wrapf(err, "unable to read %s", j) + } + err = json.Unmarshal(jb, &g.json) + if err != nil { + return errors.Wrapf(err, "unable to parse %s", j) + } + + return nil +} + +func (g *Importer) convert(pr gps.ProjectRoot) (*dep.Manifest, *dep.Lock) { + g.Logger.Println("Converting from Godeps.json ...") + + packages := make([]base.ImportedPackage, 0, len(g.json.Imports)) + for _, pkg := range g.json.Imports { + // Validate + if pkg.ImportPath == "" { + g.Logger.Println( + " Warning: Skipping project. Invalid godep configuration, ImportPath is required", + ) + continue + } + + if pkg.Rev == "" { + g.Logger.Printf( + " Warning: Invalid godep configuration, Rev not found for ImportPath %q\n", + pkg.ImportPath, + ) + } + + ip := base.ImportedPackage{ + Name: pkg.ImportPath, + LockHint: pkg.Rev, + ConstraintHint: pkg.Comment, + } + packages = append(packages, ip) + } + + g.ImportPackages(packages, true) + return g.Manifest, g.Lock +} diff --git a/vendor/github.com/golang/dep/internal/importers/godep/importer_test.go b/vendor/github.com/golang/dep/internal/importers/godep/importer_test.go new file mode 100644 index 00000000..ec9969f8 --- /dev/null +++ b/vendor/github.com/golang/dep/internal/importers/godep/importer_test.go @@ -0,0 +1,208 @@ +// Copyright 2017 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 godep + +import ( + "bytes" + "fmt" + "log" + "path/filepath" + "testing" + + "github.com/golang/dep" + "github.com/golang/dep/gps" + "github.com/golang/dep/internal/importers/importertest" + "github.com/golang/dep/internal/test" + "github.com/pkg/errors" +) + +func TestGodepConfig_Convert(t *testing.T) { + testCases := map[string]struct { + importertest.TestCase + json godepJSON + }{ + "package without comment": { + importertest.TestCase{ + WantConstraint: importertest.V1Constraint, + WantRevision: importertest.V1Rev, + WantVersion: importertest.V1Tag, + }, + godepJSON{ + Imports: []godepPackage{ + { + ImportPath: importertest.Project, + Rev: importertest.V1Rev, + }, + }, + }, + }, + "package with comment": { + importertest.TestCase{ + WantConstraint: importertest.V2Branch, + WantRevision: importertest.V2PatchRev, + WantVersion: importertest.V2PatchTag, + }, + godepJSON{ + Imports: []godepPackage{ + { + ImportPath: importertest.Project, + Rev: importertest.V2PatchRev, + Comment: importertest.V2Branch, + }, + }, + }, + }, + "missing package name": { + importertest.TestCase{ + WantWarning: "Warning: Skipping project. Invalid godep configuration, ImportPath is required", + }, + godepJSON{ + Imports: []godepPackage{{ImportPath: ""}}, + }, + }, + "missing revision": { + importertest.TestCase{ + WantWarning: fmt.Sprintf( + "Warning: Invalid godep configuration, Rev not found for ImportPath %q", + importertest.Project, + ), + }, + godepJSON{ + Imports: []godepPackage{ + { + ImportPath: importertest.Project, + }, + }, + }, + }, + } + + for name, testCase := range testCases { + name := name + testCase := testCase + t.Run(name, func(t *testing.T) { + err := testCase.Execute(t, func(logger *log.Logger, sm gps.SourceManager) (*dep.Manifest, *dep.Lock) { + g := NewImporter(logger, true, sm) + g.json = testCase.json + return g.convert(importertest.RootProject) + }) + if err != nil { + t.Fatalf("%#v", err) + } + }) + } +} + +func TestGodepConfig_Import(t *testing.T) { + h := test.NewHelper(t) + defer h.Cleanup() + + cacheDir := "gps-repocache" + h.TempDir(cacheDir) + h.TempDir("src") + h.TempDir(filepath.Join("src", importertest.RootProject)) + h.TempCopy(filepath.Join(importertest.RootProject, godepPath), "Godeps.json") + + projectRoot := h.Path(importertest.RootProject) + sm, err := gps.NewSourceManager(gps.SourceManagerConfig{ + Cachedir: h.Path(cacheDir), + Logger: log.New(test.Writer{TB: t}, "", 0), + }) + h.Must(err) + defer sm.Release() + + // Capture stderr so we can verify output + verboseOutput := &bytes.Buffer{} + logger := log.New(verboseOutput, "", 0) + + g := NewImporter(logger, false, sm) // Disable Verbose so that we don't print values that change each test run + if !g.HasDepMetadata(projectRoot) { + t.Fatal("Expected the importer to detect godep configuration file") + } + + m, l, err := g.Import(projectRoot, importertest.RootProject) + h.Must(err) + + if m == nil { + t.Fatal("Expected the manifest to be generated") + } + + if l == nil { + t.Fatal("Expected the lock to be generated") + } + + goldenFile := "golden.txt" + got := verboseOutput.String() + want := h.GetTestFileString(goldenFile) + if want != got { + if *test.UpdateGolden { + if err := h.WriteTestFile(goldenFile, got); err != nil { + t.Fatalf("%+v", errors.Wrapf(err, "Unable to write updated golden file %s", goldenFile)) + } + } else { + t.Fatalf("want %s, got %s", want, got) + } + } +} + +func TestGodepConfig_JsonLoad(t *testing.T) { + // This is same as cmd/dep/testdata/init/Godeps.json + wantJSON := godepJSON{ + Imports: []godepPackage{ + { + ImportPath: "github.com/sdboyer/deptest", + Rev: "3f4c3bea144e112a69bbe5d8d01c1b09a544253f", + }, + { + ImportPath: "github.com/sdboyer/deptestdos", + Rev: "5c607206be5decd28e6263ffffdcee067266015e", + Comment: "v2.0.0", + }, + }, + } + + h := test.NewHelper(t) + defer h.Cleanup() + + ctx := importertest.NewTestContext(h) + + h.TempCopy(filepath.Join(importertest.RootProject, godepPath), "Godeps.json") + + projectRoot := h.Path(importertest.RootProject) + + g := NewImporter(ctx.Err, true, nil) + err := g.load(projectRoot) + if err != nil { + t.Fatalf("Error while loading... %v", err) + } + + if !equalImports(g.json.Imports, wantJSON.Imports) { + t.Fatalf("Expected imports to be equal. \n\t(GOT): %v\n\t(WNT): %v", g.json.Imports, wantJSON.Imports) + } +} + +// equalImports compares two slices of godepPackage and checks if they are +// equal. +func equalImports(a, b []godepPackage) bool { + if a == nil && b == nil { + return true + } + + if a == nil || b == nil { + return false + } + + if len(a) != len(b) { + return false + } + + for i := range a { + if a[i] != b[i] { + return false + } + } + + return true +} diff --git a/vendor/github.com/golang/dep/internal/importers/godep/testdata/Godeps.json b/vendor/github.com/golang/dep/internal/importers/godep/testdata/Godeps.json new file mode 100644 index 00000000..15126ac1 --- /dev/null +++ b/vendor/github.com/golang/dep/internal/importers/godep/testdata/Godeps.json @@ -0,0 +1,16 @@ +{ + "ImportPath": "github.com/golang/notexist", + "GoVersion": "go1.8", + "GodepVersion": "vXYZ", + "Deps": [ + { + "ImportPath": "github.com/sdboyer/deptest", + "Rev": "3f4c3bea144e112a69bbe5d8d01c1b09a544253f" + }, + { + "ImportPath": "github.com/sdboyer/deptestdos", + "Comment": "v2.0.0", + "Rev": "5c607206be5decd28e6263ffffdcee067266015e" + } + ] +} diff --git a/vendor/github.com/golang/dep/internal/importers/godep/testdata/golden.txt b/vendor/github.com/golang/dep/internal/importers/godep/testdata/golden.txt new file mode 100644 index 00000000..9788b947 --- /dev/null +++ b/vendor/github.com/golang/dep/internal/importers/godep/testdata/golden.txt @@ -0,0 +1,6 @@ +Detected godep configuration files... +Converting from Godeps.json ... + Using ^0.8.1 as initial constraint for imported dep github.com/sdboyer/deptest + Trying v0.8.1 (3f4c3be) as initial lock for imported dep github.com/sdboyer/deptest + Using ^2.0.0 as initial constraint for imported dep github.com/sdboyer/deptestdos + Trying v2.0.0 (5c60720) as initial lock for imported dep github.com/sdboyer/deptestdos diff --git a/vendor/github.com/golang/dep/internal/importers/govend/importer.go b/vendor/github.com/golang/dep/internal/importers/govend/importer.go new file mode 100644 index 00000000..e4af4368 --- /dev/null +++ b/vendor/github.com/golang/dep/internal/importers/govend/importer.go @@ -0,0 +1,121 @@ +// Copyright 2017 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 govend + +import ( + "io/ioutil" + "log" + "os" + "path/filepath" + + "github.com/go-yaml/yaml" + "github.com/golang/dep" + "github.com/golang/dep/gps" + "github.com/golang/dep/internal/importers/base" + "github.com/pkg/errors" +) + +// ToDo: govend supports json and xml formats as well and we will add support for other formats in next PR - @RaviTezu +// govend don't have a separate lock file. +const govendYAMLName = "vendor.yml" + +// Importer imports govend configuration in to the dep configuration format. +type Importer struct { + *base.Importer + yaml govendYAML +} + +// NewImporter for govend. +func NewImporter(logger *log.Logger, verbose bool, sm gps.SourceManager) *Importer { + return &Importer{Importer: base.NewImporter(logger, verbose, sm)} +} + +type govendYAML struct { + Imports []govendPackage `yaml:"vendors"` +} + +type govendPackage struct { + Path string `yaml:"path"` + Revision string `yaml:"rev"` +} + +// Name of the importer. +func (g *Importer) Name() string { + return "govend" +} + +// HasDepMetadata checks if a directory contains config that the importer can handle. +func (g *Importer) HasDepMetadata(dir string) bool { + y := filepath.Join(dir, govendYAMLName) + if _, err := os.Stat(y); err != nil { + return false + } + + return true +} + +// Import the config found in the directory. +func (g *Importer) Import(dir string, pr gps.ProjectRoot) (*dep.Manifest, *dep.Lock, error) { + err := g.load(dir) + if err != nil { + return nil, nil, err + } + + m, l := g.convert(pr) + return m, l, nil +} + +// load the govend configuration files. +func (g *Importer) load(projectDir string) error { + g.Logger.Println("Detected govend configuration files...") + y := filepath.Join(projectDir, govendYAMLName) + if g.Verbose { + g.Logger.Printf(" Loading %s", y) + } + yb, err := ioutil.ReadFile(y) + if err != nil { + return errors.Wrapf(err, "unable to read %s", y) + } + err = yaml.Unmarshal(yb, &g.yaml) + if err != nil { + return errors.Wrapf(err, "unable to parse %s", y) + } + return nil +} + +// convert the govend configuration files into dep configuration files. +func (g *Importer) convert(pr gps.ProjectRoot) (*dep.Manifest, *dep.Lock) { + g.Logger.Println("Converting from vendor.yaml...") + + packages := make([]base.ImportedPackage, 0, len(g.yaml.Imports)) + for _, pkg := range g.yaml.Imports { + // Path must not be empty + if pkg.Path == "" { + g.Logger.Println( + " Warning: Skipping project. Invalid govend configuration, path is required", + ) + continue + } + + if pkg.Revision == "" { + // Do not add 'empty constraints' to the manifest. Solve will add to lock if required. + g.Logger.Printf( + " Warning: Skipping import with empty constraints. "+ + "The solve step will add the dependency to the lock if needed: %q\n", + pkg.Path, + ) + continue + } + + ip := base.ImportedPackage{ + Name: pkg.Path, + LockHint: pkg.Revision, + } + packages = append(packages, ip) + } + + g.ImportPackages(packages, true) + return g.Manifest, g.Lock +} diff --git a/vendor/github.com/golang/dep/internal/importers/govend/importer_test.go b/vendor/github.com/golang/dep/internal/importers/govend/importer_test.go new file mode 100644 index 00000000..e949efac --- /dev/null +++ b/vendor/github.com/golang/dep/internal/importers/govend/importer_test.go @@ -0,0 +1,191 @@ +// Copyright 2017 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 govend + +import ( + "bytes" + "fmt" + "log" + "path/filepath" + "testing" + + "github.com/golang/dep" + "github.com/golang/dep/gps" + "github.com/golang/dep/internal/importers/importertest" + "github.com/golang/dep/internal/test" + "github.com/pkg/errors" +) + +func TestGovendConfig_Convert(t *testing.T) { + testCases := map[string]struct { + yaml govendYAML + importertest.TestCase + }{ + "package": { + govendYAML{ + Imports: []govendPackage{ + { + Path: importertest.Project, + Revision: importertest.V1Rev, + }, + }, + }, + importertest.TestCase{ + WantConstraint: importertest.V1Constraint, + WantRevision: importertest.V1Rev, + WantVersion: importertest.V1Tag, + }, + }, + "missing package name": { + govendYAML{ + Imports: []govendPackage{ + { + Path: "", + }, + }, + }, + importertest.TestCase{ + WantWarning: "Warning: Skipping project. Invalid govend configuration, path is required", + }, + }, + + "missing revision": { + govendYAML{ + Imports: []govendPackage{ + { + Path: importertest.Project, + }, + }, + }, + importertest.TestCase{ + WantWarning: fmt.Sprintf( + " Warning: Skipping import with empty constraints. "+ + "The solve step will add the dependency to the lock if needed: %q\n", + importertest.Project, + ), + }, + }, + } + + for name, testCase := range testCases { + name := name + testCase := testCase + t.Run(name, func(t *testing.T) { + err := testCase.Execute(t, func(logger *log.Logger, sm gps.SourceManager) (*dep.Manifest, *dep.Lock) { + g := NewImporter(logger, true, sm) + g.yaml = testCase.yaml + return g.convert(importertest.RootProject) + }) + if err != nil { + t.Fatalf("%#v", err) + } + }) + } +} + +func TestGovendConfig_Import(t *testing.T) { + h := test.NewHelper(t) + defer h.Cleanup() + + cacheDir := "gps-repocache" + h.TempDir(cacheDir) + h.TempDir("src") + h.TempDir(filepath.Join("src", importertest.RootProject)) + h.TempCopy(filepath.Join(importertest.RootProject, govendYAMLName), "vendor.yml") + + projectRoot := h.Path(importertest.RootProject) + sm, err := gps.NewSourceManager(gps.SourceManagerConfig{Cachedir: h.Path(cacheDir)}) + h.Must(err) + defer sm.Release() + + // Capture stderr so we can verify the import output + verboseOutput := &bytes.Buffer{} + logger := log.New(verboseOutput, "", 0) + + // Disable Verbose so that we don't print values that change each test run + g := NewImporter(logger, false, sm) + if !g.HasDepMetadata(projectRoot) { + t.Fatal("Expected the importer to detect govend configuration file") + } + + m, l, err := g.Import(projectRoot, importertest.RootProject) + h.Must(err) + + if m == nil { + t.Fatal("Expected the manifest to be generated") + } + + if l == nil { + t.Fatal("Expected the lock to be generated") + } + + govendImportOutputFile := "golden.txt" + got := verboseOutput.String() + want := h.GetTestFileString(govendImportOutputFile) + if want != got { + if *test.UpdateGolden { + if err := h.WriteTestFile(govendImportOutputFile, got); err != nil { + t.Fatalf("%+v", errors.Wrapf(err, "Unable to write updated golden file %s", govendImportOutputFile)) + } + } else { + t.Fatalf("want %s, got %s", want, got) + } + } + +} + +func TestGovendConfig_YAMLLoad(t *testing.T) { + // This is same as cmd/testdata/init/govend/vendor.yml + wantYaml := govendYAML{ + Imports: []govendPackage{ + { + Path: "github.com/sdboyer/deptest", + Revision: "3f4c3bea144e112a69bbe5d8d01c1b09a544253f", + }, + { + Path: "github.com/sdboyer/deptestdos", + Revision: "5c607206be5decd28e6263ffffdcee067266015e", + }, + }, + } + h := test.NewHelper(t) + defer h.Cleanup() + + ctx := importertest.NewTestContext(h) + h.TempCopy(filepath.Join(importertest.RootProject, govendYAMLName), "vendor.yml") + + projectRoot := h.Path(importertest.RootProject) + + g := NewImporter(ctx.Err, true, nil) + err := g.load(projectRoot) + if err != nil { + t.Fatalf("Error while loading %v", err) + } + + if !equalGovendImports(g.yaml.Imports, wantYaml.Imports) { + t.Fatalf("Expected import to be equal. \n\t(GOT): %v\n\t(WNT): %v", g.yaml.Imports, wantYaml.Imports) + } +} + +func equalGovendImports(a, b []govendPackage) bool { + if a == nil && b == nil { + return true + } + + if a == nil || b == nil { + return false + } + + if len(a) != len(b) { + return false + } + + for i := range a { + if a[i] != b[i] { + return false + } + } + return true +} diff --git a/vendor/github.com/golang/dep/internal/importers/govend/testdata/golden.txt b/vendor/github.com/golang/dep/internal/importers/govend/testdata/golden.txt new file mode 100644 index 00000000..e77c76ab --- /dev/null +++ b/vendor/github.com/golang/dep/internal/importers/govend/testdata/golden.txt @@ -0,0 +1,6 @@ +Detected govend configuration files... +Converting from vendor.yaml... + Using ^0.8.1 as initial constraint for imported dep github.com/sdboyer/deptest + Trying v0.8.1 (3f4c3be) as initial lock for imported dep github.com/sdboyer/deptest + Using ^2.0.0 as initial constraint for imported dep github.com/sdboyer/deptestdos + Trying v2.0.0 (5c60720) as initial lock for imported dep github.com/sdboyer/deptestdos diff --git a/vendor/github.com/golang/dep/internal/importers/govend/testdata/vendor.yml b/vendor/github.com/golang/dep/internal/importers/govend/testdata/vendor.yml new file mode 100644 index 00000000..0545b101 --- /dev/null +++ b/vendor/github.com/golang/dep/internal/importers/govend/testdata/vendor.yml @@ -0,0 +1,6 @@ +vendors: +- path: github.com/sdboyer/deptest + rev: 3f4c3bea144e112a69bbe5d8d01c1b09a544253f +- path: github.com/sdboyer/deptestdos + rev: 5c607206be5decd28e6263ffffdcee067266015e + diff --git a/vendor/github.com/golang/dep/internal/importers/govendor/importer.go b/vendor/github.com/golang/dep/internal/importers/govendor/importer.go new file mode 100644 index 00000000..09611f49 --- /dev/null +++ b/vendor/github.com/golang/dep/internal/importers/govendor/importer.go @@ -0,0 +1,151 @@ +// Copyright 2016 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 govendor + +import ( + "encoding/json" + "io/ioutil" + "log" + "os" + "path" + "path/filepath" + "strings" + + "github.com/golang/dep" + "github.com/golang/dep/gps" + "github.com/golang/dep/internal/importers/base" + "github.com/pkg/errors" +) + +const govendorDir = "vendor" +const govendorName = "vendor.json" + +// Importer imports govendor configuration into the dep configuration format. +type Importer struct { + *base.Importer + + file govendorFile +} + +// NewImporter for govendor. +func NewImporter(logger *log.Logger, verbose bool, sm gps.SourceManager) *Importer { + return &Importer{Importer: base.NewImporter(logger, verbose, sm)} +} + +// File is the structure of the vendor file. +type govendorFile struct { + RootPath string // Import path of vendor folder + Ignore string + Package []*govendorPackage +} + +// Package represents each package. +type govendorPackage struct { + // See the vendor spec for definitions. + Origin string + Path string + Revision string + Version string +} + +// Name of the importer. +func (g *Importer) Name() string { + return "govendor" +} + +// HasDepMetadata checks if a directory contains config that the importer can handle. +func (g *Importer) HasDepMetadata(dir string) bool { + y := filepath.Join(dir, govendorDir, govendorName) + if _, err := os.Stat(y); err != nil { + return false + } + return true +} + +// Import the config found in the directory. +func (g *Importer) Import(dir string, pr gps.ProjectRoot) (*dep.Manifest, *dep.Lock, error) { + err := g.load(dir) + if err != nil { + return nil, nil, err + } + + m, l := g.convert(pr) + return m, l, nil +} + +func (g *Importer) load(projectDir string) error { + g.Logger.Println("Detected govendor configuration file...") + v := filepath.Join(projectDir, govendorDir, govendorName) + if g.Verbose { + g.Logger.Printf(" Loading %s", v) + } + vb, err := ioutil.ReadFile(v) + if err != nil { + return errors.Wrapf(err, "unable to read %s", v) + } + err = json.Unmarshal(vb, &g.file) + if err != nil { + return errors.Wrapf(err, "unable to parse %s", v) + } + return nil +} + +func (g *Importer) convert(pr gps.ProjectRoot) (*dep.Manifest, *dep.Lock) { + g.Logger.Println("Converting from vendor.json...") + + packages := make([]base.ImportedPackage, 0, len(g.file.Package)) + for _, pkg := range g.file.Package { + // Path must not be empty + if pkg.Path == "" { + g.Logger.Println( + " Warning: Skipping project. Invalid govendor configuration, Path is required", + ) + continue + } + + // There are valid govendor configs in the wild that don't have a revision set + // so we are not requiring it to be set during import + + ip := base.ImportedPackage{ + Name: pkg.Path, + Source: pkg.Origin, + LockHint: pkg.Revision, + } + packages = append(packages, ip) + } + + g.ImportPackages(packages, true) + + if len(g.file.Ignore) > 0 { + // Govendor has three use cases here + // 1. 'test' - special case for ignoring test files + // 2. build tags - any string without a slash (/) in it + // 3. path and path prefix - any string with a slash (/) in it. + // The path case could be a full path or just a prefix. + // Dep doesn't support build tags right now: https://github.com/golang/dep/issues/120 + for _, i := range strings.Split(g.file.Ignore, " ") { + if !strings.Contains(i, "/") { + g.Logger.Printf(" Govendor was configured to ignore the %s build tag, but that isn't supported by dep yet, and will be ignored. See https://github.com/golang/dep/issues/291.", i) + continue + } + + var ignorePattern string + _, err := g.SourceManager.DeduceProjectRoot(i) + if err == nil { // external package + ignorePattern = i + } else { // relative package path in the current project + ignorePattern = path.Join(string(pr), i) + } + + // Convert to a a wildcard ignore + ignorePattern = strings.TrimRight(ignorePattern, "/") + ignorePattern += "*" + + g.Manifest.Ignored = append(g.Manifest.Ignored, ignorePattern) + } + } + + return g.Manifest, g.Lock +} diff --git a/vendor/github.com/golang/dep/internal/importers/govendor/importer_test.go b/vendor/github.com/golang/dep/internal/importers/govendor/importer_test.go new file mode 100644 index 00000000..de5c903f --- /dev/null +++ b/vendor/github.com/golang/dep/internal/importers/govendor/importer_test.go @@ -0,0 +1,155 @@ +// Copyright 2016 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 govendor + +import ( + "bytes" + "log" + "path/filepath" + "testing" + + "github.com/golang/dep" + "github.com/golang/dep/gps" + "github.com/golang/dep/internal/importers/importertest" + "github.com/golang/dep/internal/test" + "github.com/pkg/errors" +) + +const testGovendorProjectRoot = "github.com/golang/notexist" + +func TestGovendorConfig_Import(t *testing.T) { + h := test.NewHelper(t) + defer h.Cleanup() + + ctx := importertest.NewTestContext(h) + sm, err := ctx.SourceManager() + h.Must(err) + defer sm.Release() + + h.TempDir(filepath.Join("src", testGovendorProjectRoot)) + h.TempCopy(filepath.Join(testGovendorProjectRoot, govendorDir, govendorName), "vendor.json") + projectRoot := h.Path(testGovendorProjectRoot) + + // Capture stderr so we can verify output + verboseOutput := &bytes.Buffer{} + ctx.Err = log.New(verboseOutput, "", 0) + + g := NewImporter(ctx.Err, false, sm) // Disable verbose so that we don't print values that change each test run + if !g.HasDepMetadata(projectRoot) { + t.Fatal("Expected the importer to detect the govendor configuration files") + } + + m, l, err := g.Import(projectRoot, testGovendorProjectRoot) + h.Must(err) + + if m == nil { + t.Fatal("Expected the manifest to be generated") + } + + if l == nil { + t.Fatal("Expected the lock to be generated") + } + + goldenFile := "golden.txt" + got := verboseOutput.String() + want := h.GetTestFileString(goldenFile) + if want != got { + if *test.UpdateGolden { + if err := h.WriteTestFile(goldenFile, got); err != nil { + t.Fatalf("%+v", errors.Wrapf(err, "Unable to write updated golden file %s", goldenFile)) + } + } else { + t.Fatalf("expected %s, got %s", want, got) + } + } +} + +func TestGovendorConfig_Convert(t *testing.T) { + testCases := map[string]struct { + file govendorFile + importertest.TestCase + }{ + "project": { + govendorFile{ + Package: []*govendorPackage{ + { + Path: importertest.Project, + Origin: importertest.ProjectSrc, + Revision: importertest.V1Rev, + }, + }, + }, + importertest.TestCase{ + WantSourceRepo: importertest.ProjectSrc, + WantConstraint: importertest.V1Constraint, + WantRevision: importertest.V1Rev, + WantVersion: importertest.V1Tag, + }, + }, + "skipped build tags": { + govendorFile{ + Ignore: "test linux_amd64", + }, + importertest.TestCase{ + WantIgnored: nil, + }, + }, + "ignored external package": { + govendorFile{ + Ignore: "github.com/sdboyer/deptest k8s.io/apimachinery", + }, + importertest.TestCase{ + WantIgnored: []string{"github.com/sdboyer/deptest*", "k8s.io/apimachinery*"}, + }, + }, + "ignored internal package": { + govendorFile{ + Ignore: "samples/ foo/bar", + }, + importertest.TestCase{ + WantIgnored: []string{importertest.RootProject + "/samples*", importertest.RootProject + "/foo/bar*"}, + }, + }, + "missing package path": { + govendorFile{ + Package: []*govendorPackage{ + { + Revision: importertest.V2PatchRev, + }, + }, + }, + importertest.TestCase{ + WantWarning: "Warning: Skipping project. Invalid govendor configuration, Path is required", + }, + }, + "missing package revision doesn't cause an error": { + govendorFile{ + Package: []*govendorPackage{ + { + Path: importertest.Project, + }, + }, + }, + importertest.TestCase{ + WantRevision: "", + }, + }, + } + + for name, testCase := range testCases { + name := name + testCase := testCase + t.Run(name, func(t *testing.T) { + err := testCase.Execute(t, func(logger *log.Logger, sm gps.SourceManager) (*dep.Manifest, *dep.Lock) { + g := NewImporter(logger, true, sm) + g.file = testCase.file + return g.convert(importertest.RootProject) + }) + if err != nil { + t.Fatalf("%#v", err) + } + }) + } +} diff --git a/vendor/github.com/golang/dep/internal/importers/govendor/testdata/golden.txt b/vendor/github.com/golang/dep/internal/importers/govendor/testdata/golden.txt new file mode 100644 index 00000000..51a348f7 --- /dev/null +++ b/vendor/github.com/golang/dep/internal/importers/govendor/testdata/golden.txt @@ -0,0 +1,7 @@ +Detected govendor configuration file... +Converting from vendor.json... + Using ^0.8.1 as initial constraint for imported dep github.com/sdboyer/deptest + Trying v0.8.1 (3f4c3be) as initial lock for imported dep github.com/sdboyer/deptest + Using ^2.0.0 as initial constraint for imported dep github.com/sdboyer/deptestdos + Trying v2.0.0 (5c60720) as initial lock for imported dep github.com/sdboyer/deptestdos + Govendor was configured to ignore the test build tag, but that isn't supported by dep yet, and will be ignored. See https://github.com/golang/dep/issues/291. diff --git a/vendor/github.com/golang/dep/internal/importers/govendor/testdata/vendor.json b/vendor/github.com/golang/dep/internal/importers/govendor/testdata/vendor.json new file mode 100644 index 00000000..983f15f6 --- /dev/null +++ b/vendor/github.com/golang/dep/internal/importers/govendor/testdata/vendor.json @@ -0,0 +1,22 @@ +{ + "comment": "", + "ignore": "test github.com/sdboyer/dep-test", + "package": [ + { + "checksumSHA1": "4R6TQcq0/gI/I2kKeUunuO/pEec=", + "origin": "github.com/carolynvs/deptest", + "path": "github.com/sdboyer/deptest", + "revision": "3f4c3bea144e112a69bbe5d8d01c1b09a544253f", + "revisionTime": "2017-02-22T03:31:47Z" + }, + { + "checksumSHA1": "96YwrJjpE07ENey/eDWWnCWKQOw=", + "path": "github.com/sdboyer/deptestdos", + "revision": "5c607206be5decd28e6263ffffdcee067266015e", + "revisionTime": "2017-02-22T03:34:58Z", + "version": "v2", + "versionExact": "v2.0.0" + } + ], + "rootPath": "github.com/golang/notexist" +} diff --git a/vendor/github.com/golang/dep/internal/importers/gvt/importer.go b/vendor/github.com/golang/dep/internal/importers/gvt/importer.go new file mode 100644 index 00000000..97f61a16 --- /dev/null +++ b/vendor/github.com/golang/dep/internal/importers/gvt/importer.go @@ -0,0 +1,130 @@ +// Copyright 2017 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 gvt + +import ( + "encoding/json" + "io/ioutil" + "log" + "os" + "path/filepath" + + "github.com/golang/dep" + "github.com/golang/dep/gps" + "github.com/golang/dep/internal/importers/base" + "github.com/pkg/errors" +) + +const gvtPath = "vendor" + string(os.PathSeparator) + "manifest" + +// Importer imports gvt configuration into the dep configuration format. +type Importer struct { + *base.Importer + gvtConfig gvtManifest +} + +// NewImporter for gvt. It handles gb (gb-vendor) too as they share a common manifest file & format +func NewImporter(logger *log.Logger, verbose bool, sm gps.SourceManager) *Importer { + return &Importer{Importer: base.NewImporter(logger, verbose, sm)} +} + +type gvtManifest struct { + Deps []gvtPkg `json:"dependencies"` +} + +type gvtPkg struct { + ImportPath string + Repository string + Revision string + Branch string +} + +// Name of the importer. +func (g *Importer) Name() string { + return "gvt" +} + +// HasDepMetadata checks if a directory contains config that the importer can handle. +func (g *Importer) HasDepMetadata(dir string) bool { + y := filepath.Join(dir, gvtPath) + if _, err := os.Stat(y); err != nil { + return false + } + + return true +} + +// Import the config found in the directory. +func (g *Importer) Import(dir string, pr gps.ProjectRoot) (*dep.Manifest, *dep.Lock, error) { + err := g.load(dir) + if err != nil { + return nil, nil, err + } + + m, l := g.convert(pr) + return m, l, nil +} + +func (g *Importer) load(projectDir string) error { + g.Logger.Println("Detected gb/gvt configuration files...") + j := filepath.Join(projectDir, gvtPath) + if g.Verbose { + g.Logger.Printf(" Loading %s", j) + } + jb, err := ioutil.ReadFile(j) + if err != nil { + return errors.Wrapf(err, "unable to read %s", j) + } + err = json.Unmarshal(jb, &g.gvtConfig) + if err != nil { + return errors.Wrapf(err, "unable to parse %s", j) + } + + return nil +} + +func (g *Importer) convert(pr gps.ProjectRoot) (*dep.Manifest, *dep.Lock) { + g.Logger.Println("Converting from vendor/manifest ...") + + packages := make([]base.ImportedPackage, 0, len(g.gvtConfig.Deps)) + for _, pkg := range g.gvtConfig.Deps { + // Validate + if pkg.ImportPath == "" { + g.Logger.Println( + " Warning: Skipping project. Invalid gvt configuration, ImportPath is required", + ) + continue + } + + if pkg.Revision == "" { + g.Logger.Printf( + " Warning: Invalid gvt configuration, Revision not found for ImportPath %q\n", + pkg.ImportPath, + ) + } + + var contstraintHint = "" + if pkg.Branch == "HEAD" { + // gb-vendor sets "branch" to "HEAD", if the package was feteched via -tag or -revision, + // we pass the revision as the constraint hint + contstraintHint = pkg.Revision + } else if pkg.Branch != "master" { + // both gvt & gb-vendor set "branch" to "master" unless a different branch was requested. + // so it's not really a constraint unless it's a different branch + contstraintHint = pkg.Branch + } + + ip := base.ImportedPackage{ + Name: pkg.ImportPath, + Source: pkg.Repository, + LockHint: pkg.Revision, + ConstraintHint: contstraintHint, + } + packages = append(packages, ip) + } + + g.ImportPackages(packages, true) + return g.Manifest, g.Lock +} diff --git a/vendor/github.com/golang/dep/internal/importers/gvt/importer_test.go b/vendor/github.com/golang/dep/internal/importers/gvt/importer_test.go new file mode 100644 index 00000000..cf72f1b2 --- /dev/null +++ b/vendor/github.com/golang/dep/internal/importers/gvt/importer_test.go @@ -0,0 +1,248 @@ +// Copyright 2017 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 gvt + +import ( + "bytes" + "fmt" + "log" + "path/filepath" + "testing" + + "github.com/golang/dep" + "github.com/golang/dep/gps" + "github.com/golang/dep/internal/importers/importertest" + "github.com/golang/dep/internal/test" + "github.com/pkg/errors" +) + +func TestGvtConfig_Convert(t *testing.T) { + testCases := map[string]struct { + importertest.TestCase + gvtConfig gvtManifest + }{ + "package with master branch": { + importertest.TestCase{ + WantConstraint: importertest.V1Constraint, + WantRevision: importertest.V1Rev, + WantVersion: importertest.V1Tag, + }, + gvtManifest{ + Deps: []gvtPkg{ + { + ImportPath: importertest.Project, + Revision: importertest.V1Rev, + Branch: "master", + }, + }, + }, + }, + "package with non-master branch": { + importertest.TestCase{ + WantConstraint: importertest.V2Branch, + WantRevision: importertest.V2PatchRev, + WantVersion: importertest.V2PatchTag, + }, + gvtManifest{ + Deps: []gvtPkg{ + { + ImportPath: importertest.Project, + Revision: importertest.V2PatchRev, + Branch: importertest.V2Branch, + }, + }, + }, + }, + "package with HEAD branch": { + importertest.TestCase{ + WantRevision: importertest.V1Rev, + WantVersion: importertest.V1Tag, + }, + gvtManifest{ + Deps: []gvtPkg{ + { + ImportPath: importertest.Project, + Revision: importertest.V1Rev, + Branch: "HEAD", + }, + }, + }, + }, + "package with alternate repository": { + importertest.TestCase{ + WantConstraint: importertest.V1Constraint, + WantRevision: importertest.V1Rev, + WantVersion: importertest.V1Tag, + WantSourceRepo: importertest.ProjectSrc, + }, + gvtManifest{ + Deps: []gvtPkg{ + { + ImportPath: importertest.Project, + Repository: importertest.ProjectSrc, + Revision: importertest.V1Rev, + Branch: "master", + }, + }, + }, + }, + "missing package name": { + importertest.TestCase{ + WantWarning: "Warning: Skipping project. Invalid gvt configuration, ImportPath is required", + }, + gvtManifest{ + Deps: []gvtPkg{{ImportPath: ""}}, + }, + }, + "missing revision": { + importertest.TestCase{ + WantWarning: fmt.Sprintf( + "Warning: Invalid gvt configuration, Revision not found for ImportPath %q", + importertest.Project, + ), + }, + gvtManifest{ + Deps: []gvtPkg{ + { + ImportPath: importertest.Project, + }, + }, + }, + }, + } + + for name, testCase := range testCases { + name := name + testCase := testCase + t.Run(name, func(t *testing.T) { + err := testCase.Execute(t, func(logger *log.Logger, sm gps.SourceManager) (*dep.Manifest, *dep.Lock) { + g := NewImporter(logger, true, sm) + g.gvtConfig = testCase.gvtConfig + return g.convert(importertest.RootProject) + }) + if err != nil { + t.Fatalf("%#v", err) + } + }) + } +} + +func TestGvtConfig_Import(t *testing.T) { + h := test.NewHelper(t) + defer h.Cleanup() + + cacheDir := "gps-repocache" + h.TempDir(cacheDir) + h.TempDir("src") + h.TempDir(filepath.Join("src", importertest.RootProject)) + h.TempCopy(filepath.Join(importertest.RootProject, gvtPath), "manifest") + + projectRoot := h.Path(importertest.RootProject) + sm, err := gps.NewSourceManager(gps.SourceManagerConfig{ + Cachedir: h.Path(cacheDir), + Logger: log.New(test.Writer{TB: t}, "", 0), + }) + h.Must(err) + defer sm.Release() + + // Capture stderr so we can verify output + verboseOutput := &bytes.Buffer{} + logger := log.New(verboseOutput, "", 0) + + g := NewImporter(logger, false, sm) // Disable verbose so that we don't print values that change each test run + if !g.HasDepMetadata(projectRoot) { + t.Fatal("Expected the importer to detect gvt configuration file") + } + + m, l, err := g.Import(projectRoot, importertest.RootProject) + h.Must(err) + + if m == nil { + t.Fatal("Expected the manifest to be generated") + } + + if l == nil { + t.Fatal("Expected the lock to be generated") + } + + goldenFile := "golden.txt" + got := verboseOutput.String() + want := h.GetTestFileString(goldenFile) + if want != got { + if *test.UpdateGolden { + if err := h.WriteTestFile(goldenFile, got); err != nil { + t.Fatalf("%+v", errors.Wrapf(err, "Unable to write updated golden file %s", goldenFile)) + } + } else { + t.Fatalf("want %s, got %s", want, got) + } + } +} + +func TestGvtConfig_JsonLoad(t *testing.T) { + // This is same as testdata/manifest + wantConfig := gvtManifest{ + Deps: []gvtPkg{ + { + ImportPath: "github.com/sdboyer/deptest", + Revision: "3f4c3bea144e112a69bbe5d8d01c1b09a544253f", + Branch: "HEAD", + }, + { + ImportPath: "github.com/sdboyer/deptestdos", + Revision: "5c607206be5decd28e6263ffffdcee067266015e", + Branch: "master", + }, + { + ImportPath: "github.com/carolynvs/deptest-importers", + Revision: "b79bc9482da8bb7402cdc3e3fd984db250718dd7", + Branch: "v2", + }, + }, + } + + h := test.NewHelper(t) + defer h.Cleanup() + + ctx := importertest.NewTestContext(h) + + h.TempCopy(filepath.Join(importertest.RootProject, gvtPath), "manifest") + + projectRoot := h.Path(importertest.RootProject) + + g := NewImporter(ctx.Err, true, nil) + err := g.load(projectRoot) + if err != nil { + t.Fatalf("Error while loading... %v", err) + } + + if !equalImports(g.gvtConfig.Deps, wantConfig.Deps) { + t.Fatalf("Expected imports to be equal. \n\t(GOT): %v\n\t(WNT): %v", g.gvtConfig.Deps, wantConfig.Deps) + } +} + +// equalImports compares two slices of gvtPkg and checks if they are +// equal. +func equalImports(a, b []gvtPkg) bool { + if a == nil && b == nil { + return true + } + + if a == nil || b == nil { + return false + } + + if len(a) != len(b) { + return false + } + + for i := range a { + if a[i] != b[i] { + return false + } + } + + return true +} diff --git a/vendor/github.com/golang/dep/internal/importers/gvt/testdata/golden.txt b/vendor/github.com/golang/dep/internal/importers/gvt/testdata/golden.txt new file mode 100644 index 00000000..2a079fda --- /dev/null +++ b/vendor/github.com/golang/dep/internal/importers/gvt/testdata/golden.txt @@ -0,0 +1,7 @@ +Detected gb/gvt configuration files... +Converting from vendor/manifest ... + Trying v0.8.1 (3f4c3be) as initial lock for imported dep github.com/sdboyer/deptest + Using ^2.0.0 as initial constraint for imported dep github.com/sdboyer/deptestdos + Trying v2.0.0 (5c60720) as initial lock for imported dep github.com/sdboyer/deptestdos + Using v2 as initial constraint for imported dep github.com/carolynvs/deptest-importers + Trying v2 (b79bc94) as initial lock for imported dep github.com/carolynvs/deptest-importers diff --git a/vendor/github.com/golang/dep/internal/importers/gvt/testdata/manifest b/vendor/github.com/golang/dep/internal/importers/gvt/testdata/manifest new file mode 100644 index 00000000..36e49d56 --- /dev/null +++ b/vendor/github.com/golang/dep/internal/importers/gvt/testdata/manifest @@ -0,0 +1,19 @@ +{ + "dependencies": [ + { + "importpath": "github.com/sdboyer/deptest", + "revision": "3f4c3bea144e112a69bbe5d8d01c1b09a544253f", + "branch": "HEAD" + }, + { + "importpath": "github.com/sdboyer/deptestdos", + "revision": "5c607206be5decd28e6263ffffdcee067266015e", + "branch": "master" + }, + { + "importpath": "github.com/carolynvs/deptest-importers", + "revision": "b79bc9482da8bb7402cdc3e3fd984db250718dd7", + "branch": "v2" + } + ] +} diff --git a/vendor/github.com/golang/dep/internal/importers/importers.go b/vendor/github.com/golang/dep/internal/importers/importers.go new file mode 100644 index 00000000..d54277c1 --- /dev/null +++ b/vendor/github.com/golang/dep/internal/importers/importers.go @@ -0,0 +1,45 @@ +// Copyright 2017 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 importers + +import ( + "log" + + "github.com/golang/dep" + "github.com/golang/dep/gps" + "github.com/golang/dep/internal/importers/glide" + "github.com/golang/dep/internal/importers/glock" + "github.com/golang/dep/internal/importers/godep" + "github.com/golang/dep/internal/importers/govend" + "github.com/golang/dep/internal/importers/govendor" + "github.com/golang/dep/internal/importers/gvt" + "github.com/golang/dep/internal/importers/vndr" +) + +// Importer handles importing configuration from other dependency managers into +// the dep configuration format. +type Importer interface { + // Name of the importer. + Name() string + + // Import the config found in the directory. + Import(path string, pr gps.ProjectRoot) (*dep.Manifest, *dep.Lock, error) + + // HasDepMetadata checks if a directory contains config that the importer can handle. + HasDepMetadata(dir string) bool +} + +// BuildAll returns a slice of all the importers. +func BuildAll(logger *log.Logger, verbose bool, sm gps.SourceManager) []Importer { + return []Importer{ + glide.NewImporter(logger, verbose, sm), + godep.NewImporter(logger, verbose, sm), + vndr.NewImporter(logger, verbose, sm), + govend.NewImporter(logger, verbose, sm), + gvt.NewImporter(logger, verbose, sm), + govendor.NewImporter(logger, verbose, sm), + glock.NewImporter(logger, verbose, sm), + } +} diff --git a/vendor/github.com/golang/dep/internal/importers/importertest/testcase.go b/vendor/github.com/golang/dep/internal/importers/importertest/testcase.go new file mode 100644 index 00000000..415ed596 --- /dev/null +++ b/vendor/github.com/golang/dep/internal/importers/importertest/testcase.go @@ -0,0 +1,185 @@ +// Copyright 2016 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 importertest + +import ( + "bytes" + "io/ioutil" + "log" + "sort" + "strings" + "testing" + + "github.com/golang/dep" + "github.com/golang/dep/gps" + "github.com/golang/dep/internal/test" + "github.com/pkg/errors" +) + +// TestCase is a common set of validations applied to the result +// of an importer converting from an external config format to dep's. +type TestCase struct { + DefaultConstraintFromLock bool + WantSourceRepo string + WantConstraint string + WantRevision gps.Revision + WantVersion string + WantIgnored []string + WantWarning string +} + +// NewTestContext creates a unique context with its own GOPATH for a single test. +func NewTestContext(h *test.Helper) *dep.Ctx { + h.TempDir("src") + pwd := h.Path(".") + discardLogger := log.New(ioutil.Discard, "", 0) + + return &dep.Ctx{ + GOPATH: pwd, + Out: discardLogger, + Err: discardLogger, + } +} + +// Execute and validate the test case. +func (tc TestCase) Execute(t *testing.T, convert func(logger *log.Logger, sm gps.SourceManager) (*dep.Manifest, *dep.Lock)) error { + h := test.NewHelper(t) + defer h.Cleanup() + // Disable parallel tests until we can resolve this error on the Windows builds: + // "remote repository at https://github.com/carolynvs/deptest-importers does not exist, or is inaccessible" + //h.Parallel() + + ctx := NewTestContext(h) + sm, err := ctx.SourceManager() + h.Must(err) + defer sm.Release() + + // Capture stderr so we can verify warnings + output := &bytes.Buffer{} + ctx.Err = log.New(output, "", 0) + + manifest, lock := convert(ctx.Err, sm) + return tc.validate(manifest, lock, output) +} + +// validate returns an error if any of the testcase validations failed. +func (tc TestCase) validate(manifest *dep.Manifest, lock *dep.Lock, output *bytes.Buffer) error { + if !equalSlice(manifest.Ignored, tc.WantIgnored) { + return errors.Errorf("unexpected set of ignored projects: \n\t(GOT) %#v \n\t(WNT) %#v", + manifest.Ignored, tc.WantIgnored) + } + + wantConstraintCount := 0 + if tc.WantConstraint != "" { + wantConstraintCount = 1 + } + gotConstraintCount := len(manifest.Constraints) + if gotConstraintCount != wantConstraintCount { + return errors.Errorf("unexpected number of constraints: \n\t(GOT) %v \n\t(WNT) %v", + gotConstraintCount, wantConstraintCount) + } + + if tc.WantConstraint != "" { + d, ok := manifest.Constraints[Project] + if !ok { + return errors.Errorf("Expected the manifest to have a dependency for '%v'", + Project) + } + + gotConstraint := d.Constraint.String() + if gotConstraint != tc.WantConstraint { + return errors.Errorf("unexpected constraint: \n\t(GOT) %v \n\t(WNT) %v", + gotConstraint, tc.WantConstraint) + } + + } + + // Lock checks. + wantLockCount := 0 + if tc.WantRevision != "" { + wantLockCount = 1 + } + gotLockCount := 0 + if lock != nil { + gotLockCount = len(lock.P) + } + if gotLockCount != wantLockCount { + return errors.Errorf("unexpected number of locked projects: \n\t(GOT) %v \n\t(WNT) %v", + gotLockCount, wantLockCount) + } + + if tc.WantRevision != "" { + lp := lock.P[0] + + gotProjectRoot := lp.Ident().ProjectRoot + if gotProjectRoot != Project { + return errors.Errorf("unexpected root project in lock: \n\t(GOT) %v \n\t(WNT) %v", + gotProjectRoot, Project) + } + + gotSource := lp.Ident().Source + if gotSource != tc.WantSourceRepo { + return errors.Errorf("unexpected source repository: \n\t(GOT) %v \n\t(WNT) %v", + gotSource, tc.WantSourceRepo) + } + + // Break down the locked "version" into a version (optional) and revision + var gotVersion string + var gotRevision gps.Revision + if lpv, ok := lp.Version().(gps.PairedVersion); ok { + gotVersion = lpv.String() + gotRevision = lpv.Revision() + } else if lr, ok := lp.Version().(gps.Revision); ok { + gotRevision = lr + } else { + return errors.New("could not determine the type of the locked version") + } + + if gotRevision != tc.WantRevision { + return errors.Errorf("unexpected locked revision: \n\t(GOT) %v \n\t(WNT) %v", + gotRevision, + tc.WantRevision) + } + if gotVersion != tc.WantVersion { + return errors.Errorf("unexpected locked version: \n\t(GOT) %v \n\t(WNT) %v", + gotVersion, + tc.WantVersion) + } + } + + if tc.WantWarning != "" { + gotWarning := output.String() + if !strings.Contains(gotWarning, tc.WantWarning) { + return errors.Errorf("Expected the output to include the warning '%s' but got '%s'\n", tc.WantWarning, gotWarning) + } + } + + return nil +} + +// equalSlice is comparing two string slices for equality. +func equalSlice(a, b []string) bool { + if a == nil && b == nil { + return true + } + + if a == nil || b == nil { + return false + } + + if len(a) != len(b) { + return false + } + + sort.Strings(a) + sort.Strings(b) + for i := range a { + if a[i] != b[i] { + return false + } + } + + return true +} diff --git a/vendor/github.com/golang/dep/internal/importers/importertest/testdata.go b/vendor/github.com/golang/dep/internal/importers/importertest/testdata.go new file mode 100644 index 00000000..fc037ff0 --- /dev/null +++ b/vendor/github.com/golang/dep/internal/importers/importertest/testdata.go @@ -0,0 +1,67 @@ +// Copyright 2016 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 importertest + +const ( + // RootProject is the containing project performing the import. + RootProject = "github.com/golang/notexist" + + // Project being imported. + Project = "github.com/carolynvs/deptest-importers" + + // ProjectSrc is an alternate source for the imported project. + ProjectSrc = "https://github.com/carolynvs/deptest-importers.git" + + // UntaggedRev is a revision without any tags. + UntaggedRev = "9b670d143bfb4a00f7461451d5c4a62f80e9d11d" + + // UntaggedRevAbbrv is the result of running `git describe` on UntaggedRev + UntaggedRevAbbrv = "v1.0.0-1-g9b670d1" + + // Beta1Tag is a non-semver tag. + Beta1Tag = "beta1" + + // Beta1Rev is the revision of Beta1Tag + Beta1Rev = "7913ab26988c6fb1e16225f845a178e8849dd254" + + // V2Branch is a branch that could be interpreted as a semver tag (but shouldn't). + V2Branch = "v2" + + // V2Rev is the HEAD revision of V2Branch. + V2Rev = "45dcf5a09c64b48b6e836028a3bc672b19b9d11d" + + // V2PatchTag is a prerelease semver tag on the non-default branch. + V2PatchTag = "v2.0.0-alpha1" + + // V2PatchRev is the revision of V2PatchTag. + V2PatchRev = "347760b50204948ea63e531dd6560e56a9adde8f" + + // V1Tag is a semver tag that matches V1Constraint. + V1Tag = "v1.0.0" + + // V1Rev is the revision of V1Tag. + V1Rev = "d0c29640b17f77426b111f4c1640d716591aa70e" + + // V1PatchTag is a semver tag that matches V1Constraint. + V1PatchTag = "v1.0.2" + + // V1PatchRev is the revision of V1PatchTag + V1PatchRev = "788963efe22e3e6e24c776a11a57468bb2fcd780" + + // V1Constraint is a constraint that matches multiple semver tags. + V1Constraint = "^1.0.0" + + // MultiTaggedRev is a revision with multiple tags. + MultiTaggedRev = "34cf993cc346f65601fe4356dd68bd54d20a1bfe" + + // MultiTaggedSemverTag is a semver tag on MultiTaggedRev. + MultiTaggedSemverTag = "v1.0.4" + + // MultiTaggedPlainTag is a non-semver tag on MultiTaggedRev. + MultiTaggedPlainTag = "stable" + + // NonexistentPrj is a dummy project which does not exist on Github. + NonexistentPrj = "github.com/nonexistent/project" +) diff --git a/vendor/github.com/golang/dep/internal/importers/vndr/importer.go b/vendor/github.com/golang/dep/internal/importers/vndr/importer.go new file mode 100644 index 00000000..60e28e23 --- /dev/null +++ b/vendor/github.com/golang/dep/internal/importers/vndr/importer.go @@ -0,0 +1,149 @@ +// Copyright 2017 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 vndr + +import ( + "bufio" + "log" + "os" + "path/filepath" + "strings" + + "github.com/golang/dep" + "github.com/golang/dep/gps" + "github.com/golang/dep/internal/importers/base" + "github.com/pkg/errors" +) + +func vndrFile(dir string) string { + return filepath.Join(dir, "vendor.conf") +} + +// Importer imports vndr configuration into the dep configuration format. +type Importer struct { + *base.Importer + packages []vndrPackage +} + +// NewImporter for vndr. +func NewImporter(log *log.Logger, verbose bool, sm gps.SourceManager) *Importer { + return &Importer{Importer: base.NewImporter(log, verbose, sm)} +} + +// Name of the importer. +func (v *Importer) Name() string { return "vndr" } + +// HasDepMetadata checks if a directory contains config that the importer can handle. +func (v *Importer) HasDepMetadata(dir string) bool { + _, err := os.Stat(vndrFile(dir)) + return err == nil +} + +// Import the config found in the directory. +func (v *Importer) Import(dir string, pr gps.ProjectRoot) (*dep.Manifest, *dep.Lock, error) { + v.Logger.Println("Detected vndr configuration file...") + + err := v.loadVndrFile(dir) + if err != nil { + return nil, nil, errors.Wrapf(err, "unable to load vndr file") + } + + m, l := v.convert(pr) + return m, l, nil +} + +func (v *Importer) loadVndrFile(dir string) error { + v.Logger.Printf("Converting from vendor.conf...") + + path := vndrFile(dir) + f, err := os.Open(path) + if err != nil { + return errors.Wrapf(err, "unable to open %s", path) + } + defer f.Close() + + scanner := bufio.NewScanner(f) + for scanner.Scan() { + pkg, err := parseVndrLine(scanner.Text()) + if err != nil { + v.Logger.Printf(" Warning: Skipping line. Unable to parse: %s\n", err) + continue + } + if pkg == nil { + // Could be an empty line or one which is just a comment + continue + } + v.packages = append(v.packages, *pkg) + } + + if err := scanner.Err(); err != nil { + v.Logger.Printf(" Warning: Ignoring errors found while parsing %s: %s\n", path, err) + } + + return nil +} + +func (v *Importer) convert(pr gps.ProjectRoot) (*dep.Manifest, *dep.Lock) { + packages := make([]base.ImportedPackage, 0, len(v.packages)) + for _, pkg := range v.packages { + // Validate + if pkg.importPath == "" { + v.Logger.Println( + " Warning: Skipping project. Invalid vndr configuration, import path is required", + ) + continue + } + + if pkg.reference == "" { + v.Logger.Printf( + " Warning: Invalid vndr configuration, reference not found for import path %q\n", + pkg.importPath, + ) + } + + ip := base.ImportedPackage{ + Name: pkg.importPath, + Source: pkg.repository, + LockHint: pkg.reference, + } + packages = append(packages, ip) + } + v.ImportPackages(packages, true) + return v.Manifest, v.Lock +} + +type vndrPackage struct { + importPath string + reference string + repository string +} + +func parseVndrLine(line string) (*vndrPackage, error) { + commentIdx := strings.Index(line, "#") + if commentIdx >= 0 { + line = line[:commentIdx] + } + line = strings.TrimSpace(line) + + if line == "" { + return nil, nil + } + + parts := strings.Fields(line) + + if !(len(parts) == 2 || len(parts) == 3) { + return nil, errors.Errorf("invalid config format: %q", line) + } + + pkg := &vndrPackage{ + importPath: parts[0], + reference: parts[1], + } + if len(parts) == 3 { + pkg.repository = parts[2] + } + + return pkg, nil +} diff --git a/vendor/github.com/golang/dep/internal/importers/vndr/importer_test.go b/vendor/github.com/golang/dep/internal/importers/vndr/importer_test.go new file mode 100644 index 00000000..db4b1794 --- /dev/null +++ b/vendor/github.com/golang/dep/internal/importers/vndr/importer_test.go @@ -0,0 +1,218 @@ +// Copyright 2017 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 vndr + +import ( + "bytes" + "fmt" + "log" + "path/filepath" + "reflect" + "testing" + + "github.com/golang/dep" + "github.com/golang/dep/gps" + "github.com/golang/dep/internal/importers/importertest" + "github.com/golang/dep/internal/test" + "github.com/pkg/errors" +) + +func TestVndrConfig_Convert(t *testing.T) { + testCases := map[string]struct { + packages []vndrPackage + importertest.TestCase + }{ + "package": { + []vndrPackage{{ + importPath: importertest.Project, + reference: importertest.V1Rev, + repository: importertest.ProjectSrc, + }}, + importertest.TestCase{ + WantSourceRepo: importertest.ProjectSrc, + WantConstraint: importertest.V1Constraint, + WantRevision: importertest.V1Rev, + WantVersion: importertest.V1Tag, + }, + }, + "missing importPath": { + []vndrPackage{{ + reference: importertest.V1Tag, + }}, + importertest.TestCase{ + WantWarning: "Warning: Skipping project. Invalid vndr configuration, import path is required", + }, + }, + "missing reference": { + []vndrPackage{{ + importPath: importertest.Project, + }}, + importertest.TestCase{ + WantWarning: fmt.Sprintf( + "Warning: Invalid vndr configuration, reference not found for import path %q", + importertest.Project, + ), + }, + }, + } + + for name, testCase := range testCases { + name := name + testCase := testCase + t.Run(name, func(t *testing.T) { + err := testCase.Execute(t, func(logger *log.Logger, sm gps.SourceManager) (*dep.Manifest, *dep.Lock) { + g := NewImporter(logger, true, sm) + g.packages = testCase.packages + return g.convert(importertest.RootProject) + }) + if err != nil { + t.Fatalf("%#v", err) + } + }) + } +} + +func TestVndrConfig_Import(t *testing.T) { + h := test.NewHelper(t) + defer h.Cleanup() + + ctx := importertest.NewTestContext(h) + sm, err := ctx.SourceManager() + h.Must(err) + defer sm.Release() + + h.TempDir(filepath.Join("src", importertest.RootProject)) + h.TempCopy(vndrFile(importertest.RootProject), "vendor.conf") + projectRoot := h.Path(importertest.RootProject) + + logOutput := bytes.NewBuffer(nil) + ctx.Err = log.New(logOutput, "", 0) + + v := NewImporter(ctx.Err, false, sm) + if !v.HasDepMetadata(projectRoot) { + t.Fatal("Expected the importer to detect vndr configuration file") + } + + m, l, err := v.Import(projectRoot, importertest.RootProject) + h.Must(err) + + wantM := dep.NewManifest() + c1, _ := gps.NewSemverConstraint("^0.8.1") + wantM.Constraints["github.com/sdboyer/deptest"] = gps.ProjectProperties{ + Source: "https://github.com/sdboyer/deptest.git", + Constraint: c1, + } + c2, _ := gps.NewSemverConstraint("^2.0.0") + wantM.Constraints["github.com/sdboyer/deptestdos"] = gps.ProjectProperties{ + Constraint: c2, + } + if !reflect.DeepEqual(wantM, m) { + t.Errorf("unexpected manifest\nhave=%+v\nwant=%+v", m, wantM) + } + + wantL := &dep.Lock{ + P: []gps.LockedProject{ + gps.NewLockedProject( + gps.ProjectIdentifier{ + ProjectRoot: "github.com/sdboyer/deptest", + Source: "https://github.com/sdboyer/deptest.git", + }, + gps.NewVersion("v0.8.1").Pair("3f4c3bea144e112a69bbe5d8d01c1b09a544253f"), + nil, + ), + gps.NewLockedProject( + gps.ProjectIdentifier{ + ProjectRoot: "github.com/sdboyer/deptestdos", + }, + gps.NewVersion("v2.0.0").Pair("5c607206be5decd28e6263ffffdcee067266015e"), + nil, + ), + }, + } + if !reflect.DeepEqual(wantL, l) { + t.Errorf("unexpected lock\nhave=%+v\nwant=%+v", l, wantL) + } + + goldenFile := "golden.txt" + got := logOutput.String() + want := h.GetTestFileString(goldenFile) + if want != got { + if *test.UpdateGolden { + if err := h.WriteTestFile(goldenFile, got); err != nil { + t.Fatalf("%+v", errors.Wrapf(err, "Unable to write updated golden file %s", goldenFile)) + } + } else { + t.Fatalf("expected %s, got %s", want, got) + } + } +} + +func TestParseVndrLine(t *testing.T) { + testcase := func(in string, wantPkg *vndrPackage, wantErr error) func(*testing.T) { + return func(t *testing.T) { + havePkg, haveErr := parseVndrLine(in) + switch { + case wantPkg == nil: + if havePkg != nil { + t.Errorf("expected nil package, have %v", havePkg) + } + case havePkg == nil: + if wantPkg != nil { + t.Errorf("expected non-nil package %v, have nil", wantPkg) + } + default: + if !reflect.DeepEqual(havePkg, wantPkg) { + t.Errorf("unexpected package, have=%v, want=%v", *havePkg, *wantPkg) + } + } + + switch { + case wantErr == nil: + if haveErr != nil { + t.Errorf("expected nil err, have %v", haveErr) + } + case haveErr == nil: + if wantErr != nil { + t.Errorf("expected non-nil err %v, have nil", wantErr) + } + default: + if haveErr.Error() != wantErr.Error() { + t.Errorf("expected err=%q, have err=%q", wantErr.Error(), haveErr.Error()) + } + } + } + } + t.Run("normal line", + testcase("github.com/golang/notreal v1.0.0", + &vndrPackage{ + importPath: "github.com/golang/notreal", + reference: "v1.0.0", + }, nil)) + + t.Run("with repo", + testcase("github.com/golang/notreal v1.0.0 https://github.com/golang/notreal", + &vndrPackage{ + importPath: "github.com/golang/notreal", + reference: "v1.0.0", + repository: "https://github.com/golang/notreal", + }, nil)) + + t.Run("trailing comment", + testcase("github.com/golang/notreal v1.0.0 https://github.com/golang/notreal # cool comment", + &vndrPackage{ + importPath: "github.com/golang/notreal", + reference: "v1.0.0", + repository: "https://github.com/golang/notreal", + }, nil)) + + t.Run("empty line", testcase("", nil, nil)) + t.Run("comment line", testcase("# comment", nil, nil)) + t.Run("comment line with leading whitespace", testcase(" # comment", nil, nil)) + + t.Run("missing revision", + testcase("github.com/golang/notreal", nil, + errors.New("invalid config format: \"github.com/golang/notreal\""), + )) +} diff --git a/vendor/github.com/golang/dep/internal/importers/vndr/testdata/golden.txt b/vendor/github.com/golang/dep/internal/importers/vndr/testdata/golden.txt new file mode 100644 index 00000000..3702ae43 --- /dev/null +++ b/vendor/github.com/golang/dep/internal/importers/vndr/testdata/golden.txt @@ -0,0 +1,6 @@ +Detected vndr configuration file... +Converting from vendor.conf... + Using ^0.8.1 as initial constraint for imported dep github.com/sdboyer/deptest + Trying v0.8.1 (3f4c3be) as initial lock for imported dep github.com/sdboyer/deptest + Using ^2.0.0 as initial constraint for imported dep github.com/sdboyer/deptestdos + Trying v2.0.0 (5c60720) as initial lock for imported dep github.com/sdboyer/deptestdos diff --git a/vendor/github.com/golang/dep/internal/importers/vndr/testdata/vendor.conf b/vendor/github.com/golang/dep/internal/importers/vndr/testdata/vendor.conf new file mode 100644 index 00000000..072166aa --- /dev/null +++ b/vendor/github.com/golang/dep/internal/importers/vndr/testdata/vendor.conf @@ -0,0 +1,4 @@ +github.com/sdboyer/deptest 3f4c3bea144e112a69bbe5d8d01c1b09a544253f https://github.com/sdboyer/deptest.git # trailing comment +# line comment + +github.com/sdboyer/deptestdos v2.0.0 # trailing comment diff --git a/vendor/github.com/golang/dep/internal/test/integration/testcase.go b/vendor/github.com/golang/dep/internal/test/integration/testcase.go new file mode 100644 index 00000000..bd772da7 --- /dev/null +++ b/vendor/github.com/golang/dep/internal/test/integration/testcase.go @@ -0,0 +1,201 @@ +// Copyright 2017 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 integration + +import ( + "encoding/json" + "io/ioutil" + "os" + "path/filepath" + "strings" + "testing" + "unicode" + + "github.com/golang/dep/internal/test" +) + +// TestCase manages a test case directory structure and content +type TestCase struct { + t *testing.T + name string + rootPath string + initialPath string + finalPath string + Commands [][]string `json:"commands"` + ErrorExpected string `json:"error-expected"` + GopathInitial map[string]string `json:"gopath-initial"` + VendorInitial map[string]string `json:"vendor-initial"` + VendorFinal []string `json:"vendor-final"` + InitPath string `json:"init-path"` +} + +// NewTestCase creates a new TestCase. +func NewTestCase(t *testing.T, dir, name string) *TestCase { + rootPath := filepath.FromSlash(filepath.Join(dir, name)) + n := &TestCase{ + t: t, + name: name, + rootPath: rootPath, + initialPath: filepath.Join(rootPath, "initial"), + finalPath: filepath.Join(rootPath, "final"), + } + j, err := ioutil.ReadFile(filepath.Join(rootPath, "testcase.json")) + if err != nil { + t.Fatal(err) + } + err = json.Unmarshal(j, n) + if err != nil { + t.Fatal(err) + } + return n +} + +// InitialPath represents the initial set of files in a project. +func (tc *TestCase) InitialPath() string { + return tc.initialPath +} + +// UpdateFile updates the golden file with the working result. +func (tc *TestCase) UpdateFile(goldenPath, workingPath string) { + exists, working, err := getFile(workingPath) + if err != nil { + tc.t.Fatalf("Error reading project file %s: %s", goldenPath, err) + } + + golden := filepath.Join(tc.finalPath, goldenPath) + if exists { + if err := tc.WriteFile(golden, working); err != nil { + tc.t.Fatal(err) + } + } else { + err := os.Remove(golden) + if err != nil && !os.IsNotExist(err) { + tc.t.Fatal(err) + } + } +} + +// CompareFile compares the golden file with the working result. +func (tc *TestCase) CompareFile(goldenPath, working string) { + golden := filepath.Join(tc.finalPath, goldenPath) + + gotExists, got, err := getFile(working) + if err != nil { + tc.t.Fatalf("Error reading project file %q: %s", goldenPath, err) + } + wantExists, want, err := getFile(golden) + if err != nil { + tc.t.Fatalf("Error reading testcase file %q: %s", goldenPath, err) + } + + if wantExists && gotExists { + if want != got { + tc.t.Errorf("%s was not as expected\n(WNT):\n%s\n(GOT):\n%s", filepath.Base(goldenPath), want, got) + } + } else if !wantExists && gotExists { + tc.t.Errorf("%q created where none was expected", goldenPath) + } else if wantExists && !gotExists { + tc.t.Errorf("%q not created where one was expected", goldenPath) + } +} + +// UpdateOutput updates the golden file for stdout with the working result. +func (tc *TestCase) UpdateOutput(stdout string) { + stdoutPath := filepath.Join(tc.rootPath, "stdout.txt") + _, err := os.Stat(stdoutPath) + if err != nil { + if os.IsNotExist(err) { + // Don't update the stdout.txt file if it doesn't exist. + return + } + panic(err) + } + + if err := tc.WriteFile(stdoutPath, stdout); err != nil { + tc.t.Fatal(err) + } +} + +// CompareOutput compares expected and actual stdout output. +func (tc *TestCase) CompareOutput(stdout string) { + expected, err := ioutil.ReadFile(filepath.Join(tc.rootPath, "stdout.txt")) + if err != nil { + if os.IsNotExist(err) { + // Nothing to verify + return + } + panic(err) + } + + expStr := normalizeLines(string(expected)) + stdout = normalizeLines(stdout) + + if expStr != stdout { + tc.t.Errorf("stdout was not as expected\n(WNT):\n%s\n(GOT):\n%s\n", expStr, stdout) + } +} + +// normalizeLines returns a version with trailing whitespace stripped from each line. +func normalizeLines(s string) string { + lines := strings.Split(s, "\n") + for i := range lines { + lines[i] = strings.TrimRightFunc(lines[i], unicode.IsSpace) + } + return strings.Join(lines, "\n") +} + +// CompareError compares expected and actual stderr output. +func (tc *TestCase) CompareError(err error, stderr string) { + wantExists, want := tc.ErrorExpected != "", tc.ErrorExpected + gotExists, got := stderr != "" && err != nil, stderr + + if wantExists && gotExists { + switch c := strings.Count(got, want); c { + case 0: + tc.t.Errorf("error did not contain expected string:\n\t(GOT): %s\n\t(WNT): %s", got, want) + case 1: + default: + tc.t.Errorf("expected error %s matches %d times to actual error %s", want, c, got) + } + } else if !wantExists && gotExists { + tc.t.Fatalf("error raised where none was expected: \n%v", stderr) + } else if wantExists && !gotExists { + tc.t.Error("error not raised where one was expected:", want) + } +} + +// CompareVendorPaths validates the vendor directory contents. +func (tc *TestCase) CompareVendorPaths(gotVendorPaths []string) { + if *test.UpdateGolden { + tc.VendorFinal = gotVendorPaths + } else { + wantVendorPaths := tc.VendorFinal + if len(gotVendorPaths) != len(wantVendorPaths) { + tc.t.Fatalf("Wrong number of vendor paths created: want %d got %d", len(wantVendorPaths), len(gotVendorPaths)) + } + for ind := range gotVendorPaths { + if gotVendorPaths[ind] != wantVendorPaths[ind] { + tc.t.Errorf("Mismatch in vendor paths created: want %s got %s", wantVendorPaths, gotVendorPaths) + } + } + } +} + +// WriteFile writes a file using the default file permissions. +func (tc *TestCase) WriteFile(src string, content string) error { + return ioutil.WriteFile(src, []byte(content), 0666) +} + +func getFile(path string) (bool, string, error) { + _, err := os.Stat(path) + if err != nil { + return false, "", nil + } + f, err := ioutil.ReadFile(path) + if err != nil { + return true, "", err + } + return true, string(f), nil +} diff --git a/vendor/github.com/golang/dep/internal/test/integration/testproj.go b/vendor/github.com/golang/dep/internal/test/integration/testproj.go new file mode 100644 index 00000000..760e1cc5 --- /dev/null +++ b/vendor/github.com/golang/dep/internal/test/integration/testproj.go @@ -0,0 +1,310 @@ +// Copyright 2017 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 integration + +import ( + "bytes" + "io" + "io/ioutil" + "os" + "os/exec" + "path/filepath" + "runtime" + "sort" + "strings" + "testing" + + "github.com/golang/dep/internal/test" + "github.com/pkg/errors" +) + +const ( + projectRoot string = "src/github.com/golang/notexist" +) + +// RunFunc defines the function signature for an integration test command to execute. +type RunFunc func(prog string, newargs []string, outW, errW io.Writer, dir string, env []string) error + +// TestProject manages the "virtual" test project directory structure +// and content +type TestProject struct { + t *testing.T + preImports []string + tempdir string + env []string + origWd string + stdout bytes.Buffer + stderr bytes.Buffer + run RunFunc +} + +// NewTestProject initializes a new test's project directory. +func NewTestProject(t *testing.T, initPath, wd string, run RunFunc) *TestProject { + new := &TestProject{ + t: t, + origWd: wd, + env: os.Environ(), + run: run, + } + new.makeRootTempDir() + new.TempDir(projectRoot, "vendor") + new.CopyTree(initPath) + + new.Setenv("GOPATH", new.tempdir) + + return new +} + +// Cleanup (remove) the test project's directory. +func (p *TestProject) Cleanup() { + os.RemoveAll(p.tempdir) +} + +// Path to the test project directory. +func (p *TestProject) Path(args ...string) string { + return filepath.Join(p.tempdir, filepath.Join(args...)) +} + +// ProjPath builds an import path for the test project. +func (p *TestProject) ProjPath(args ...string) string { + localPath := append([]string{projectRoot}, args...) + return p.Path(localPath...) +} + +// TempDir creates a temporary directory for the test project. +func (p *TestProject) TempDir(args ...string) { + fullPath := p.Path(args...) + if err := os.MkdirAll(fullPath, 0755); err != nil && !os.IsExist(err) { + p.t.Fatalf("%+v", errors.Errorf("Unable to create temp directory: %s", fullPath)) + } +} + +// TempProjDir builds the path to a package within the test project. +func (p *TestProject) TempProjDir(args ...string) { + localPath := append([]string{projectRoot}, args...) + p.TempDir(localPath...) +} + +// VendorPath lists the contents of the test project's vendor directory. +func (p *TestProject) VendorPath(args ...string) string { + localPath := append([]string{projectRoot, "vendor"}, args...) + p.TempDir(localPath...) + return p.Path(localPath...) +} + +// RunGo runs a go command, and expects it to succeed. +func (p *TestProject) RunGo(args ...string) { + cmd := exec.Command("go", args...) + p.stdout.Reset() + p.stderr.Reset() + cmd.Stdout = &p.stdout + cmd.Stderr = &p.stderr + cmd.Dir = p.tempdir + cmd.Env = p.env + status := cmd.Run() + if p.stdout.Len() > 0 { + p.t.Log("go standard output:") + p.t.Log(p.stdout.String()) + } + if p.stderr.Len() > 0 { + p.t.Log("go standard error:") + p.t.Log(p.stderr.String()) + } + if status != nil { + p.t.Logf("go %v failed unexpectedly: %v", args, status) + p.t.FailNow() + } +} + +// RunGit runs a git command, and expects it to succeed. +func (p *TestProject) RunGit(dir string, args ...string) { + cmd := exec.Command("git", args...) + p.stdout.Reset() + p.stderr.Reset() + cmd.Stdout = &p.stdout + cmd.Stderr = &p.stderr + cmd.Dir = dir + cmd.Env = p.env + status := cmd.Run() + if *test.PrintLogs { + if p.stdout.Len() > 0 { + p.t.Logf("git %v standard output:", args) + p.t.Log(p.stdout.String()) + } + if p.stderr.Len() > 0 { + p.t.Logf("git %v standard error:", args) + p.t.Log(p.stderr.String()) + } + } + if status != nil { + p.t.Logf("git %v failed unexpectedly: %v", args, status) + p.t.FailNow() + } +} + +// GetStdout gets the Stdout output from test run. +func (p *TestProject) GetStdout() string { + return p.stdout.String() +} + +// GetStderr gets the Stderr output from test run. +func (p *TestProject) GetStderr() string { + return p.stderr.String() +} + +// GetVendorGit populates the initial vendor directory for a test project. +func (p *TestProject) GetVendorGit(ip string) { + parse := strings.Split(ip, "/") + gitDir := strings.Join(parse[:len(parse)-1], string(filepath.Separator)) + p.TempProjDir("vendor", gitDir) + p.RunGit(p.ProjPath("vendor", gitDir), "clone", "http://"+ip) +} + +// DoRun executes the integration test command against the test project. +func (p *TestProject) DoRun(args []string) error { + if *test.PrintLogs { + p.t.Logf("running testdep %v", args) + } + prog := filepath.Join(p.origWd, "testdep"+test.ExeSuffix) + newargs := append([]string{args[0], "-v"}, args[1:]...) + + p.stdout.Reset() + p.stderr.Reset() + + status := p.run(prog, newargs, &p.stdout, &p.stderr, p.ProjPath(""), p.env) + + if *test.PrintLogs { + if p.stdout.Len() > 0 { + p.t.Logf("\nstandard output:%s", p.stdout.String()) + } + if p.stderr.Len() > 0 { + p.t.Logf("standard error:\n%s", p.stderr.String()) + } + } + return status +} + +// CopyTree recursively copies a source directory into the test project's directory. +func (p *TestProject) CopyTree(src string) { + filepath.Walk(src, + func(path string, info os.FileInfo, err error) error { + if path != src { + localpath := path[len(src)+1:] + if info.IsDir() { + p.TempDir(projectRoot, localpath) + } else { + destpath := filepath.Join(p.ProjPath(), localpath) + copyFile(destpath, path) + } + } + return nil + }) +} + +func copyFile(dest, src string) { + in, err := os.Open(src) + if err != nil { + panic(err) + } + defer in.Close() + + out, err := os.Create(dest) + if err != nil { + panic(err) + } + defer out.Close() + + io.Copy(out, in) +} + +// GetVendorPaths collects final vendor paths at a depth of three levels. +func (p *TestProject) GetVendorPaths() []string { + vendorPath := p.ProjPath("vendor") + result := make([]string, 0) + filepath.Walk( + vendorPath, + func(path string, info os.FileInfo, err error) error { + if len(path) > len(vendorPath) && info.IsDir() { + parse := strings.Split(path[len(vendorPath)+1:], string(filepath.Separator)) + if len(parse) == 3 { + result = append(result, strings.Join(parse, "/")) + return filepath.SkipDir + } + } + return nil + }, + ) + sort.Strings(result) + return result +} + +// GetImportPaths collect final vendor paths at a depth of three levels. +func (p *TestProject) GetImportPaths() []string { + importPath := p.Path("src") + result := make([]string, 0) + filepath.Walk( + importPath, + func(path string, info os.FileInfo, err error) error { + if len(path) > len(importPath) && info.IsDir() { + parse := strings.Split(path[len(importPath)+1:], string(filepath.Separator)) + if len(parse) == 3 { + result = append(result, strings.Join(parse, "/")) + return filepath.SkipDir + } + } + return nil + }, + ) + sort.Strings(result) + return result +} + +// RecordImportPaths takes a snapshot of the import paths before test is run. +func (p *TestProject) RecordImportPaths() { + p.preImports = p.GetImportPaths() +} + +// CompareImportPaths compares import paths before and after test commands. +func (p *TestProject) CompareImportPaths() { + wantImportPaths := p.preImports + gotImportPaths := p.GetImportPaths() + if len(gotImportPaths) != len(wantImportPaths) { + p.t.Fatalf("Import path count changed during command: pre %d post %d", len(wantImportPaths), len(gotImportPaths)) + } + for ind := range gotImportPaths { + if gotImportPaths[ind] != wantImportPaths[ind] { + p.t.Errorf("Change in import paths during: pre %s post %s", gotImportPaths, wantImportPaths) + } + } +} + +// makeRootTempdir makes a temporary directory for a run of testgo. If +// the temporary directory was already created, this does nothing. +func (p *TestProject) makeRootTempDir() { + if p.tempdir == "" { + var err error + p.tempdir, err = ioutil.TempDir("", "gotest") + p.Must(err) + + // Fix for OSX where the tempdir is a symlink: + if runtime.GOOS == "darwin" { + p.tempdir, err = filepath.EvalSymlinks(p.tempdir) + p.Must(err) + } + } +} + +// Setenv sets an environment variable to use when running the test go +// command. +func (p *TestProject) Setenv(name, val string) { + p.env = append(p.env, name+"="+val) +} + +// Must gives a fatal error if err is not nil. +func (p *TestProject) Must(err error) { + if err != nil { + p.t.Fatalf("%+v", err) + } +} diff --git a/vendor/github.com/golang/dep/internal/test/test.go b/vendor/github.com/golang/dep/internal/test/test.go new file mode 100644 index 00000000..9a7fbc8d --- /dev/null +++ b/vendor/github.com/golang/dep/internal/test/test.go @@ -0,0 +1,625 @@ +// Copyright 2017 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 test + +import ( + "bytes" + "flag" + "fmt" + "go/format" + "io" + "io/ioutil" + "os" + "os/exec" + "path/filepath" + "regexp" + "runtime" + "strings" + "sync" + "testing" + + "github.com/pkg/errors" +) + +var ( + // ExeSuffix is the suffix of executable files; ".exe" on Windows. + ExeSuffix string + mu sync.Mutex + // PrintLogs controls logging of test commands. + PrintLogs = flag.Bool("logs", false, "log stdin/stdout of test commands") + // UpdateGolden controls updating test fixtures. + UpdateGolden = flag.Bool("update", false, "update golden files") +) + +const ( + manifestName string = "Gopkg.toml" + lockName string = "Gopkg.lock" +) + +func init() { + switch runtime.GOOS { + case "windows": + ExeSuffix = ".exe" + } +} + +// Helper with utilities for testing. +type Helper struct { + t *testing.T + temps []string + wd string + origWd string + env []string + tempdir string + ran bool + inParallel bool + stdout, stderr bytes.Buffer +} + +// NewHelper initializes a new helper for testing. +func NewHelper(t *testing.T) *Helper { + wd, err := os.Getwd() + if err != nil { + panic(err) + } + return &Helper{t: t, origWd: wd} +} + +// Must gives a fatal error if err is not nil. +func (h *Helper) Must(err error) { + if err != nil { + h.t.Fatalf("%+v", err) + } +} + +// check gives a test non-fatal error if err is not nil. +func (h *Helper) check(err error) { + if err != nil { + h.t.Errorf("%+v", err) + } +} + +// Parallel runs the test in parallel by calling t.Parallel. +func (h *Helper) Parallel() { + if h.ran { + h.t.Fatalf("%+v", errors.New("internal testsuite error: call to parallel after run")) + } + if h.wd != "" { + h.t.Fatalf("%+v", errors.New("internal testsuite error: call to parallel after cd")) + } + for _, e := range h.env { + if strings.HasPrefix(e, "GOROOT=") || strings.HasPrefix(e, "GOPATH=") || strings.HasPrefix(e, "GOBIN=") { + val := e[strings.Index(e, "=")+1:] + if strings.HasPrefix(val, "testdata") || strings.HasPrefix(val, "./testdata") { + h.t.Fatalf("%+v", errors.Errorf("internal testsuite error: call to parallel with testdata in environment (%s)", e)) + } + } + } + h.inParallel = true + h.t.Parallel() +} + +// pwd returns the current directory. +func (h *Helper) pwd() string { + wd, err := os.Getwd() + if err != nil { + h.t.Fatalf("%+v", errors.Wrap(err, "could not get working directory")) + } + return wd +} + +// Cd changes the current directory to the named directory. Note that +// using this means that the test must not be run in parallel with any +// other tests. +func (h *Helper) Cd(dir string) { + if h.inParallel { + h.t.Fatalf("%+v", errors.New("internal testsuite error: changing directory when running in parallel")) + } + if h.wd == "" { + h.wd = h.pwd() + } + abs, err := filepath.Abs(dir) + if err == nil { + h.Setenv("PWD", abs) + } + + err = os.Chdir(dir) + h.Must(errors.Wrapf(err, "Unable to cd to %s", dir)) +} + +// Setenv sets an environment variable to use when running the test go +// command. +func (h *Helper) Setenv(name, val string) { + if h.inParallel && (name == "GOROOT" || name == "GOPATH" || name == "GOBIN") && (strings.HasPrefix(val, "testdata") || strings.HasPrefix(val, "./testdata")) { + h.t.Fatalf("%+v", errors.Errorf("internal testsuite error: call to setenv with testdata (%s=%s) after parallel", name, val)) + } + h.unsetenv(name) + h.env = append(h.env, name+"="+val) +} + +// unsetenv removes an environment variable. +func (h *Helper) unsetenv(name string) { + if h.env == nil { + h.env = append([]string(nil), os.Environ()...) + } + for i, v := range h.env { + if strings.HasPrefix(v, name+"=") { + h.env = append(h.env[:i], h.env[i+1:]...) + break + } + } +} + +// DoRun runs the test go command, recording stdout and stderr and +// returning exit status. +func (h *Helper) DoRun(args []string) error { + if h.inParallel { + for _, arg := range args { + if strings.HasPrefix(arg, "testdata") || strings.HasPrefix(arg, "./testdata") { + h.t.Fatalf("%+v", errors.New("internal testsuite error: parallel run using testdata")) + } + } + } + if *PrintLogs { + h.t.Logf("running testdep %v", args) + } + var prog string + if h.wd == "" { + prog = "./testdep" + ExeSuffix + } else { + prog = filepath.Join(h.wd, "testdep"+ExeSuffix) + } + newargs := []string{args[0], "-v"} + newargs = append(newargs, args[1:]...) + cmd := exec.Command(prog, newargs...) + h.stdout.Reset() + h.stderr.Reset() + cmd.Stdout = &h.stdout + cmd.Stderr = &h.stderr + cmd.Env = h.env + status := cmd.Run() + if *PrintLogs { + if h.stdout.Len() > 0 { + h.t.Log("standard output:") + h.t.Log(h.stdout.String()) + } + if h.stderr.Len() > 0 { + h.t.Log("standard error:") + h.t.Log(h.stderr.String()) + } + } + h.ran = true + return errors.Wrapf(status, "Error running %s\n%s", strings.Join(newargs, " "), h.stderr.String()) +} + +// Run runs the test go command, and expects it to succeed. +func (h *Helper) Run(args ...string) { + if runtime.GOOS == "windows" { + mu.Lock() + defer mu.Unlock() + } + if status := h.DoRun(args); status != nil { + h.t.Logf("go %v failed unexpectedly: %v", args, status) + h.t.FailNow() + } +} + +// runFail runs the test go command, and expects it to fail. +func (h *Helper) runFail(args ...string) { + if status := h.DoRun(args); status == nil { + h.t.Fatalf("%+v", errors.New("testgo succeeded unexpectedly")) + } else { + h.t.Log("testgo failed as expected:", status) + } +} + +// RunGo runs a go command, and expects it to succeed. +func (h *Helper) RunGo(args ...string) { + cmd := exec.Command("go", args...) + h.stdout.Reset() + h.stderr.Reset() + cmd.Stdout = &h.stdout + cmd.Stderr = &h.stderr + cmd.Dir = h.wd + cmd.Env = h.env + status := cmd.Run() + if h.stdout.Len() > 0 { + h.t.Log("go standard output:") + h.t.Log(h.stdout.String()) + } + if h.stderr.Len() > 0 { + h.t.Log("go standard error:") + h.t.Log(h.stderr.String()) + } + if status != nil { + h.t.Logf("go %v failed unexpectedly: %v", args, status) + h.t.FailNow() + } +} + +// NeedsExternalNetwork makes sure the tests needing external network will not +// be run when executing tests in short mode. +func NeedsExternalNetwork(t *testing.T) { + if testing.Short() { + t.Skip("skipping test: no external network in -short mode") + } +} + +// NeedsGit will make sure the tests that require git will be skipped if the +// git binary is not available. +func NeedsGit(t *testing.T) { + if _, err := exec.LookPath("git"); err != nil { + t.Skip("skipping because git binary not found") + } +} + +// RunGit runs a git command, and expects it to succeed. +func (h *Helper) RunGit(dir string, args ...string) { + cmd := exec.Command("git", args...) + h.stdout.Reset() + h.stderr.Reset() + cmd.Stdout = &h.stdout + cmd.Stderr = &h.stderr + cmd.Dir = dir + cmd.Env = h.env + status := cmd.Run() + if *PrintLogs { + if h.stdout.Len() > 0 { + h.t.Logf("git %v standard output:", args) + h.t.Log(h.stdout.String()) + } + if h.stderr.Len() > 0 { + h.t.Logf("git %v standard error:", args) + h.t.Log(h.stderr.String()) + } + } + if status != nil { + h.t.Logf("git %v failed unexpectedly: %v", args, status) + h.t.FailNow() + } +} + +// getStdout returns standard output of the testgo run as a string. +func (h *Helper) getStdout() string { + if !h.ran { + h.t.Fatalf("%+v", errors.New("internal testsuite error: stdout called before run")) + } + return h.stdout.String() +} + +// getStderr returns standard error of the testgo run as a string. +func (h *Helper) getStderr() string { + if !h.ran { + h.t.Fatalf("%+v", errors.New("internal testsuite error: stdout called before run")) + } + return h.stderr.String() +} + +// doGrepMatch looks for a regular expression in a buffer, and returns +// whether it is found. The regular expression is matched against +// each line separately, as with the grep command. +func (h *Helper) doGrepMatch(match string, b *bytes.Buffer) bool { + if !h.ran { + h.t.Fatalf("%+v", errors.New("internal testsuite error: grep called before run")) + } + re := regexp.MustCompile(match) + for _, ln := range bytes.Split(b.Bytes(), []byte{'\n'}) { + if re.Match(ln) { + return true + } + } + return false +} + +// doGrep looks for a regular expression in a buffer and fails if it +// is not found. The name argument is the name of the output we are +// searching, "output" or "error". The msg argument is logged on +// failure. +func (h *Helper) doGrep(match string, b *bytes.Buffer, name, msg string) { + if !h.doGrepMatch(match, b) { + h.t.Log(msg) + h.t.Logf("pattern %v not found in standard %s", match, name) + h.t.FailNow() + } +} + +// grepStdout looks for a regular expression in the test run's +// standard output and fails, logging msg, if it is not found. +func (h *Helper) grepStdout(match, msg string) { + h.doGrep(match, &h.stdout, "output", msg) +} + +// grepStderr looks for a regular expression in the test run's +// standard error and fails, logging msg, if it is not found. +func (h *Helper) grepStderr(match, msg string) { + h.doGrep(match, &h.stderr, "error", msg) +} + +// grepBoth looks for a regular expression in the test run's standard +// output or stand error and fails, logging msg, if it is not found. +func (h *Helper) grepBoth(match, msg string) { + if !h.doGrepMatch(match, &h.stdout) && !h.doGrepMatch(match, &h.stderr) { + h.t.Log(msg) + h.t.Logf("pattern %v not found in standard output or standard error", match) + h.t.FailNow() + } +} + +// doGrepNot looks for a regular expression in a buffer and fails if +// it is found. The name and msg arguments are as for doGrep. +func (h *Helper) doGrepNot(match string, b *bytes.Buffer, name, msg string) { + if h.doGrepMatch(match, b) { + h.t.Log(msg) + h.t.Logf("pattern %v found unexpectedly in standard %s", match, name) + h.t.FailNow() + } +} + +// grepStdoutNot looks for a regular expression in the test run's +// standard output and fails, logging msg, if it is found. +func (h *Helper) grepStdoutNot(match, msg string) { + h.doGrepNot(match, &h.stdout, "output", msg) +} + +// grepStderrNot looks for a regular expression in the test run's +// standard error and fails, logging msg, if it is found. +func (h *Helper) grepStderrNot(match, msg string) { + h.doGrepNot(match, &h.stderr, "error", msg) +} + +// grepBothNot looks for a regular expression in the test run's +// standard output or stand error and fails, logging msg, if it is +// found. +func (h *Helper) grepBothNot(match, msg string) { + if h.doGrepMatch(match, &h.stdout) || h.doGrepMatch(match, &h.stderr) { + h.t.Log(msg) + h.t.Fatalf("%+v", errors.Errorf("pattern %v found unexpectedly in standard output or standard error", match)) + } +} + +// doGrepCount counts the number of times a regexp is seen in a buffer. +func (h *Helper) doGrepCount(match string, b *bytes.Buffer) int { + if !h.ran { + h.t.Fatalf("%+v", errors.New("internal testsuite error: doGrepCount called before run")) + } + re := regexp.MustCompile(match) + c := 0 + for _, ln := range bytes.Split(b.Bytes(), []byte{'\n'}) { + if re.Match(ln) { + c++ + } + } + return c +} + +// grepCountBoth returns the number of times a regexp is seen in both +// standard output and standard error. +func (h *Helper) grepCountBoth(match string) int { + return h.doGrepCount(match, &h.stdout) + h.doGrepCount(match, &h.stderr) +} + +// creatingTemp records that the test plans to create a temporary file +// or directory. If the file or directory exists already, it will be +// removed. When the test completes, the file or directory will be +// removed if it exists. +func (h *Helper) creatingTemp(path string) { + if filepath.IsAbs(path) && !strings.HasPrefix(path, h.tempdir) { + h.t.Fatalf("%+v", errors.Errorf("internal testsuite error: creatingTemp(%q) with absolute path not in temporary directory", path)) + } + // If we have changed the working directory, make sure we have + // an absolute path, because we are going to change directory + // back before we remove the temporary. + if h.wd != "" && !filepath.IsAbs(path) { + path = filepath.Join(h.pwd(), path) + } + h.Must(os.RemoveAll(path)) + h.temps = append(h.temps, path) +} + +// makeTempdir makes a temporary directory for a run of testgo. If +// the temporary directory was already created, this does nothing. +func (h *Helper) makeTempdir() { + if h.tempdir == "" { + var err error + h.tempdir, err = ioutil.TempDir("", "gotest") + h.Must(err) + } +} + +// TempFile adds a temporary file for a run of testgo. +func (h *Helper) TempFile(path, contents string) { + h.makeTempdir() + h.Must(os.MkdirAll(filepath.Join(h.tempdir, filepath.Dir(path)), 0755)) + bytes := []byte(contents) + if strings.HasSuffix(path, ".go") { + formatted, err := format.Source(bytes) + if err == nil { + bytes = formatted + } + } + h.Must(ioutil.WriteFile(filepath.Join(h.tempdir, path), bytes, 0644)) +} + +// WriteTestFile writes a file to the testdata directory from memory. src is +// relative to ./testdata. +func (h *Helper) WriteTestFile(src string, content string) error { + err := ioutil.WriteFile(filepath.Join(h.origWd, "testdata", src), []byte(content), 0666) + return err +} + +// GetFile reads a file into memory +func (h *Helper) GetFile(path string) io.ReadCloser { + content, err := os.Open(path) + if err != nil { + h.t.Fatalf("%+v", errors.Wrapf(err, "Unable to open file: %s", path)) + } + return content +} + +// GetTestFile reads a file from the testdata directory into memory. src is +// relative to ./testdata. +func (h *Helper) GetTestFile(src string) io.ReadCloser { + fullPath := filepath.Join(h.origWd, "testdata", src) + return h.GetFile(fullPath) +} + +// GetTestFileString reads a file from the testdata directory into memory. src is +// relative to ./testdata. +func (h *Helper) GetTestFileString(src string) string { + srcf := h.GetTestFile(src) + defer srcf.Close() + content, err := ioutil.ReadAll(srcf) + if err != nil { + h.t.Fatalf("%+v", err) + } + return string(content) +} + +// TempCopy copies a temporary file from testdata into the temporary directory. +// dest is relative to the temp directory location, and src is relative to +// ./testdata. +func (h *Helper) TempCopy(dest, src string) { + in := h.GetTestFile(src) + defer in.Close() + h.TempDir(filepath.Dir(dest)) + out, err := os.Create(filepath.Join(h.tempdir, dest)) + if err != nil { + panic(err) + } + defer out.Close() + io.Copy(out, in) +} + +// TempDir adds a temporary directory for a run of testgo. +func (h *Helper) TempDir(path string) { + h.makeTempdir() + fullPath := filepath.Join(h.tempdir, path) + if err := os.MkdirAll(fullPath, 0755); err != nil && !os.IsExist(err) { + h.t.Fatalf("%+v", errors.Errorf("Unable to create temp directory: %s", fullPath)) + } +} + +// Path returns the absolute pathname to file with the temporary +// directory. +func (h *Helper) Path(name string) string { + if h.tempdir == "" { + h.t.Fatalf("%+v", errors.Errorf("internal testsuite error: path(%q) with no tempdir", name)) + } + + var joined string + if name == "." { + joined = h.tempdir + } else { + joined = filepath.Join(h.tempdir, name) + } + + // Ensure it's the absolute, symlink-less path we're returning + abs, err := filepath.EvalSymlinks(joined) + if err != nil { + h.t.Fatalf("%+v", errors.Wrapf(err, "internal testsuite error: could not get absolute path for dir(%q)", joined)) + } + return abs +} + +// MustExist fails if path does not exist. +func (h *Helper) MustExist(path string) { + if err := h.ShouldExist(path); err != nil { + h.t.Fatalf("%+v", err) + } +} + +// ShouldExist returns an error if path does not exist. +func (h *Helper) ShouldExist(path string) error { + if !h.Exist(path) { + return errors.Errorf("%s does not exist but should", path) + } + + return nil +} + +// Exist returns whether or not a path exists +func (h *Helper) Exist(path string) bool { + if _, err := os.Stat(path); err != nil { + if os.IsNotExist(err) { + return false + } + h.t.Fatalf("%+v", errors.Wrapf(err, "Error checking if path exists: %s", path)) + } + + return true +} + +// MustNotExist fails if path exists. +func (h *Helper) MustNotExist(path string) { + if err := h.ShouldNotExist(path); err != nil { + h.t.Fatalf("%+v", err) + } +} + +// ShouldNotExist returns an error if path exists. +func (h *Helper) ShouldNotExist(path string) error { + if h.Exist(path) { + return errors.Errorf("%s exists but should not", path) + } + + return nil +} + +// Cleanup cleans up a test that runs testgo. +func (h *Helper) Cleanup() { + if h.wd != "" { + if err := os.Chdir(h.wd); err != nil { + // We are unlikely to be able to continue. + fmt.Fprintln(os.Stderr, "could not restore working directory, crashing:", err) + os.Exit(2) + } + } + // NOTE(mattn): It seems that sometimes git.exe is not dead + // when cleanup() is called. But we do not know any way to wait for it. + if runtime.GOOS == "windows" { + mu.Lock() + exec.Command(`taskkill`, `/F`, `/IM`, `git.exe`).Run() + mu.Unlock() + } + for _, path := range h.temps { + h.check(os.RemoveAll(path)) + } + if h.tempdir != "" { + h.check(os.RemoveAll(h.tempdir)) + } +} + +// ReadManifest returns the manifest in the current directory. +func (h *Helper) ReadManifest() string { + m := filepath.Join(h.pwd(), manifestName) + h.MustExist(m) + + f, err := ioutil.ReadFile(m) + h.Must(err) + return string(f) +} + +// ReadLock returns the lock in the current directory. +func (h *Helper) ReadLock() string { + l := filepath.Join(h.pwd(), lockName) + h.MustExist(l) + + f, err := ioutil.ReadFile(l) + h.Must(err) + return string(f) +} + +// GetCommit treats repo as a path to a git repository and returns the current +// revision. +func (h *Helper) GetCommit(repo string) string { + repoPath := h.Path("pkg/dep/sources/https---" + strings.Replace(repo, "/", "-", -1)) + cmd := exec.Command("git", "rev-parse", "HEAD") + cmd.Dir = repoPath + out, err := cmd.CombinedOutput() + if err != nil { + h.t.Fatalf("%+v", errors.Wrapf(err, "git commit failed: out -> %s", string(out))) + } + return strings.TrimSpace(string(out)) +} diff --git a/vendor/github.com/golang/dep/internal/test/writer.go b/vendor/github.com/golang/dep/internal/test/writer.go new file mode 100644 index 00000000..7fd3a4d9 --- /dev/null +++ b/vendor/github.com/golang/dep/internal/test/writer.go @@ -0,0 +1,31 @@ +// Copyright 2017 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 test + +import ( + "strings" + "testing" + "unicode" +) + +// Writer adapts a testing.TB to the io.Writer interface +type Writer struct { + testing.TB +} + +func (t Writer) Write(b []byte) (n int, err error) { + str := string(b) + if len(str) == 0 { + return 0, nil + } + + for _, part := range strings.Split(str, "\n") { + str := strings.TrimRightFunc(part, unicode.IsSpace) + if len(str) != 0 { + t.Log(str) + } + } + return len(b), err +} diff --git a/vendor/github.com/golang/dep/lock.go b/vendor/github.com/golang/dep/lock.go new file mode 100644 index 00000000..3f3f563c --- /dev/null +++ b/vendor/github.com/golang/dep/lock.go @@ -0,0 +1,203 @@ +// Copyright 2016 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 dep + +import ( + "bytes" + "encoding/hex" + "io" + "sort" + + "github.com/golang/dep/gps" + "github.com/pelletier/go-toml" + "github.com/pkg/errors" +) + +// LockName is the lock file name used by dep. +const LockName = "Gopkg.lock" + +// Lock holds lock file data and implements gps.Lock. +type Lock struct { + SolveMeta SolveMeta + P []gps.LockedProject +} + +// SolveMeta holds solver meta data. +type SolveMeta struct { + InputsDigest []byte + AnalyzerName string + AnalyzerVersion int + SolverName string + SolverVersion int +} + +type rawLock struct { + SolveMeta solveMeta `toml:"solve-meta"` + Projects []rawLockedProject `toml:"projects"` +} + +type solveMeta struct { + InputsDigest string `toml:"inputs-digest"` + AnalyzerName string `toml:"analyzer-name"` + AnalyzerVersion int `toml:"analyzer-version"` + SolverName string `toml:"solver-name"` + SolverVersion int `toml:"solver-version"` +} + +type rawLockedProject struct { + Name string `toml:"name"` + Branch string `toml:"branch,omitempty"` + Revision string `toml:"revision"` + Version string `toml:"version,omitempty"` + Source string `toml:"source,omitempty"` + Packages []string `toml:"packages"` +} + +func readLock(r io.Reader) (*Lock, error) { + buf := &bytes.Buffer{} + _, err := buf.ReadFrom(r) + if err != nil { + return nil, errors.Wrap(err, "Unable to read byte stream") + } + + raw := rawLock{} + err = toml.Unmarshal(buf.Bytes(), &raw) + if err != nil { + return nil, errors.Wrap(err, "Unable to parse the lock as TOML") + } + + return fromRawLock(raw) +} + +func fromRawLock(raw rawLock) (*Lock, error) { + var err error + l := &Lock{ + P: make([]gps.LockedProject, len(raw.Projects)), + } + + l.SolveMeta.InputsDigest, err = hex.DecodeString(raw.SolveMeta.InputsDigest) + if err != nil { + return nil, errors.Errorf("invalid hash digest in lock's memo field") + } + + l.SolveMeta.AnalyzerName = raw.SolveMeta.AnalyzerName + l.SolveMeta.AnalyzerVersion = raw.SolveMeta.AnalyzerVersion + l.SolveMeta.SolverName = raw.SolveMeta.SolverName + l.SolveMeta.SolverVersion = raw.SolveMeta.SolverVersion + + for i, ld := range raw.Projects { + r := gps.Revision(ld.Revision) + + var v gps.Version = r + if ld.Version != "" { + if ld.Branch != "" { + return nil, errors.Errorf("lock file specified both a branch (%s) and version (%s) for %s", ld.Branch, ld.Version, ld.Name) + } + v = gps.NewVersion(ld.Version).Pair(r) + } else if ld.Branch != "" { + v = gps.NewBranch(ld.Branch).Pair(r) + } else if r == "" { + return nil, errors.Errorf("lock file has entry for %s, but specifies no branch or version", ld.Name) + } + + id := gps.ProjectIdentifier{ + ProjectRoot: gps.ProjectRoot(ld.Name), + Source: ld.Source, + } + l.P[i] = gps.NewLockedProject(id, v, ld.Packages) + } + + return l, nil +} + +// InputsDigest returns the hash of inputs which produced this lock data. +func (l *Lock) InputsDigest() []byte { + return l.SolveMeta.InputsDigest +} + +// Projects returns the list of LockedProjects contained in the lock data. +func (l *Lock) Projects() []gps.LockedProject { + return l.P +} + +// HasProjectWithRoot checks if the lock contains a project with the provided +// ProjectRoot. +// +// This check is O(n) in the number of projects. +func (l *Lock) HasProjectWithRoot(root gps.ProjectRoot) bool { + for _, p := range l.P { + if p.Ident().ProjectRoot == root { + return true + } + } + + return false +} + +// toRaw converts the manifest into a representation suitable to write to the lock file +func (l *Lock) toRaw() rawLock { + raw := rawLock{ + SolveMeta: solveMeta{ + InputsDigest: hex.EncodeToString(l.SolveMeta.InputsDigest), + AnalyzerName: l.SolveMeta.AnalyzerName, + AnalyzerVersion: l.SolveMeta.AnalyzerVersion, + SolverName: l.SolveMeta.SolverName, + SolverVersion: l.SolveMeta.SolverVersion, + }, + Projects: make([]rawLockedProject, len(l.P)), + } + + sort.Slice(l.P, func(i, j int) bool { + return l.P[i].Ident().Less(l.P[j].Ident()) + }) + + for k, lp := range l.P { + id := lp.Ident() + ld := rawLockedProject{ + Name: string(id.ProjectRoot), + Source: id.Source, + Packages: lp.Packages(), + } + + v := lp.Version() + ld.Revision, ld.Branch, ld.Version = gps.VersionComponentStrings(v) + + raw.Projects[k] = ld + } + + return raw +} + +// MarshalTOML serializes this lock into TOML via an intermediate raw form. +func (l *Lock) MarshalTOML() ([]byte, error) { + raw := l.toRaw() + var buf bytes.Buffer + enc := toml.NewEncoder(&buf).ArraysWithOneElementPerLine(true) + err := enc.Encode(raw) + return buf.Bytes(), errors.Wrap(err, "Unable to marshal lock to TOML string") +} + +// LockFromSolution converts a gps.Solution to dep's representation of a lock. +// +// Data is defensively copied wherever necessary to ensure the resulting *lock +// shares no memory with the original lock. +func LockFromSolution(in gps.Solution) *Lock { + h, p := in.InputsDigest(), in.Projects() + + l := &Lock{ + SolveMeta: SolveMeta{ + InputsDigest: make([]byte, len(h)), + AnalyzerName: in.AnalyzerName(), + AnalyzerVersion: in.AnalyzerVersion(), + SolverName: in.SolverName(), + SolverVersion: in.SolverVersion(), + }, + P: make([]gps.LockedProject, len(p)), + } + + copy(l.SolveMeta.InputsDigest, h) + copy(l.P, p) + return l +} diff --git a/vendor/github.com/golang/dep/lock_test.go b/vendor/github.com/golang/dep/lock_test.go new file mode 100644 index 00000000..8f55c916 --- /dev/null +++ b/vendor/github.com/golang/dep/lock_test.go @@ -0,0 +1,165 @@ +// Copyright 2016 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 dep + +import ( + "encoding/hex" + "reflect" + "strings" + "testing" + + "github.com/golang/dep/gps" + "github.com/golang/dep/internal/test" +) + +func TestReadLock(t *testing.T) { + h := test.NewHelper(t) + defer h.Cleanup() + + golden := "lock/golden0.toml" + g0f := h.GetTestFile(golden) + defer g0f.Close() + got, err := readLock(g0f) + if err != nil { + t.Fatalf("Should have read Lock correctly, but got err %q", err) + } + + b, _ := hex.DecodeString("2252a285ab27944a4d7adcba8dbd03980f59ba652f12db39fa93b927c345593e") + want := &Lock{ + SolveMeta: SolveMeta{ + InputsDigest: b, + }, + P: []gps.LockedProject{ + gps.NewLockedProject( + gps.ProjectIdentifier{ProjectRoot: gps.ProjectRoot("github.com/golang/dep")}, + gps.NewBranch("master").Pair(gps.Revision("d05d5aca9f895d19e9265839bffeadd74a2d2ecb")), + []string{"."}, + ), + }, + } + + if !reflect.DeepEqual(got, want) { + t.Error("Valid lock did not parse as expected") + } + + golden = "lock/golden1.toml" + g1f := h.GetTestFile(golden) + defer g1f.Close() + got, err = readLock(g1f) + if err != nil { + t.Fatalf("Should have read Lock correctly, but got err %q", err) + } + + b, _ = hex.DecodeString("2252a285ab27944a4d7adcba8dbd03980f59ba652f12db39fa93b927c345593e") + want = &Lock{ + SolveMeta: SolveMeta{ + InputsDigest: b, + }, + P: []gps.LockedProject{ + gps.NewLockedProject( + gps.ProjectIdentifier{ProjectRoot: gps.ProjectRoot("github.com/golang/dep")}, + gps.NewVersion("0.12.2").Pair(gps.Revision("d05d5aca9f895d19e9265839bffeadd74a2d2ecb")), + []string{"."}, + ), + }, + } + + if !reflect.DeepEqual(got, want) { + t.Error("Valid lock did not parse as expected") + } +} + +func TestWriteLock(t *testing.T) { + h := test.NewHelper(t) + defer h.Cleanup() + + golden := "lock/golden0.toml" + want := h.GetTestFileString(golden) + memo, _ := hex.DecodeString("2252a285ab27944a4d7adcba8dbd03980f59ba652f12db39fa93b927c345593e") + l := &Lock{ + SolveMeta: SolveMeta{ + InputsDigest: memo, + }, + P: []gps.LockedProject{ + gps.NewLockedProject( + gps.ProjectIdentifier{ProjectRoot: gps.ProjectRoot("github.com/golang/dep")}, + gps.NewBranch("master").Pair(gps.Revision("d05d5aca9f895d19e9265839bffeadd74a2d2ecb")), + []string{"."}, + ), + }, + } + + got, err := l.MarshalTOML() + if err != nil { + t.Fatalf("Error while marshaling valid lock to TOML: %q", err) + } + + if string(got) != want { + if *test.UpdateGolden { + if err = h.WriteTestFile(golden, string(got)); err != nil { + t.Fatal(err) + } + } else { + t.Errorf("Valid lock did not marshal to TOML as expected:\n\t(GOT): %s\n\t(WNT): %s", string(got), want) + } + } + + golden = "lock/golden1.toml" + want = h.GetTestFileString(golden) + memo, _ = hex.DecodeString("2252a285ab27944a4d7adcba8dbd03980f59ba652f12db39fa93b927c345593e") + l = &Lock{ + SolveMeta: SolveMeta{ + InputsDigest: memo, + }, + P: []gps.LockedProject{ + gps.NewLockedProject( + gps.ProjectIdentifier{ProjectRoot: gps.ProjectRoot("github.com/golang/dep")}, + gps.NewVersion("0.12.2").Pair(gps.Revision("d05d5aca9f895d19e9265839bffeadd74a2d2ecb")), + []string{"."}, + ), + }, + } + + got, err = l.MarshalTOML() + if err != nil { + t.Fatalf("Error while marshaling valid lock to TOML: %q", err) + } + + if string(got) != want { + if *test.UpdateGolden { + if err = h.WriteTestFile(golden, string(got)); err != nil { + t.Fatal(err) + } + } else { + t.Errorf("Valid lock did not marshal to TOML as expected:\n\t(GOT): %s\n\t(WNT): %s", string(got), want) + } + } +} + +func TestReadLockErrors(t *testing.T) { + h := test.NewHelper(t) + defer h.Cleanup() + var err error + + tests := []struct { + name string + file string + }{ + {"specified both", "lock/error0.toml"}, + {"invalid hash", "lock/error1.toml"}, + {"no branch or version", "lock/error2.toml"}, + } + + for _, tst := range tests { + lf := h.GetTestFile(tst.file) + defer lf.Close() + _, err = readLock(lf) + if err == nil { + t.Errorf("Reading lock with %s should have caused error, but did not", tst.name) + } else if !strings.Contains(err.Error(), tst.name) { + t.Errorf("Unexpected error %q; expected %s error", err, tst.name) + } + } +} diff --git a/vendor/github.com/golang/dep/manifest.go b/vendor/github.com/golang/dep/manifest.go new file mode 100644 index 00000000..add9236f --- /dev/null +++ b/vendor/github.com/golang/dep/manifest.go @@ -0,0 +1,640 @@ +// Copyright 2016 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 dep + +import ( + "bytes" + "fmt" + "io" + "reflect" + "regexp" + "sort" + "sync" + + "github.com/golang/dep/gps" + "github.com/golang/dep/gps/pkgtree" + toml "github.com/pelletier/go-toml" + "github.com/pkg/errors" +) + +// ManifestName is the manifest file name used by dep. +const ManifestName = "Gopkg.toml" + +// Errors +var ( + errInvalidConstraint = errors.Errorf("%q must be a TOML array of tables", "constraint") + errInvalidOverride = errors.Errorf("%q must be a TOML array of tables", "override") + errInvalidRequired = errors.Errorf("%q must be a TOML list of strings", "required") + errInvalidIgnored = errors.Errorf("%q must be a TOML list of strings", "ignored") + errInvalidPrune = errors.Errorf("%q must be a TOML table of booleans", "prune") + errInvalidPruneProject = errors.Errorf("%q must be a TOML array of tables", "prune.project") + errInvalidMetadata = errors.New("metadata should be a TOML table") + + errInvalidProjectRoot = errors.New("ProjectRoot name validation failed") + + errInvalidPruneValue = errors.New("prune options values must be booleans") + errPruneSubProject = errors.New("prune projects should not contain sub projects") + + errRootPruneContainsName = errors.Errorf("%q should not include a name", "prune") + errInvalidRootPruneValue = errors.New("root prune options must be omitted instead of being set to false") + errInvalidPruneProjectName = errors.Errorf("%q in %q must be a string", "name", "prune.project") + errNoName = errors.New("no name provided") +) + +// Manifest holds manifest file data and implements gps.RootManifest. +type Manifest struct { + Constraints gps.ProjectConstraints + Ovr gps.ProjectConstraints + + Ignored []string + Required []string + + PruneOptions gps.CascadingPruneOptions +} + +type rawManifest struct { + Constraints []rawProject `toml:"constraint,omitempty"` + Overrides []rawProject `toml:"override,omitempty"` + Ignored []string `toml:"ignored,omitempty"` + Required []string `toml:"required,omitempty"` + PruneOptions rawPruneOptions `toml:"prune,omitempty"` +} + +type rawProject struct { + Name string `toml:"name"` + Branch string `toml:"branch,omitempty"` + Revision string `toml:"revision,omitempty"` + Version string `toml:"version,omitempty"` + Source string `toml:"source,omitempty"` +} + +type rawPruneOptions struct { + UnusedPackages bool `toml:"unused-packages,omitempty"` + NonGoFiles bool `toml:"non-go,omitempty"` + GoTests bool `toml:"go-tests,omitempty"` + + //Projects []map[string]interface{} `toml:"project,omitempty"` + Projects []map[string]interface{} +} + +const ( + pruneOptionUnusedPackages = "unused-packages" + pruneOptionGoTests = "go-tests" + pruneOptionNonGo = "non-go" +) + +// Constants to represents per-project prune uint8 values. +const ( + pvnone uint8 = 0 // No per-project prune value was set in Gopkg.toml. + pvtrue uint8 = 1 // Per-project prune value was explicitly set to true. + pvfalse uint8 = 2 // Per-project prune value was explicitly set to false. +) + +// NewManifest instantites a new manifest. +func NewManifest() *Manifest { + return &Manifest{ + Constraints: make(gps.ProjectConstraints), + Ovr: make(gps.ProjectConstraints), + PruneOptions: gps.CascadingPruneOptions{ + DefaultOptions: gps.PruneNestedVendorDirs, + PerProjectOptions: map[gps.ProjectRoot]gps.PruneOptionSet{}, + }, + } +} + +func validateManifest(s string) ([]error, error) { + var warns []error + // Load the TomlTree from string + tree, err := toml.Load(s) + if err != nil { + return warns, errors.Wrap(err, "unable to load TomlTree from string") + } + // Convert tree to a map + manifest := tree.ToMap() + + // match abbreviated git hash (7chars) or hg hash (12chars) + abbrevRevHash := regexp.MustCompile("^[a-f0-9]{7}([a-f0-9]{5})?$") + // Look for unknown fields and collect errors + for prop, val := range manifest { + switch prop { + case "metadata": + // Check if metadata is of Map type + if reflect.TypeOf(val).Kind() != reflect.Map { + warns = append(warns, errInvalidMetadata) + } + case "constraint", "override": + valid := true + // Invalid if type assertion fails. Not a TOML array of tables. + if rawProj, ok := val.([]interface{}); ok { + // Check element type. Must be a map. Checking one element would be + // enough because TOML doesn't allow mixing of types. + if reflect.TypeOf(rawProj[0]).Kind() != reflect.Map { + valid = false + } + + if valid { + // Iterate through each array of tables + for _, v := range rawProj { + ruleProvided := false + props := v.(map[string]interface{}) + // Check the individual field's key to be valid + for key, value := range props { + // Check if the key is valid + switch key { + case "name": + case "branch", "version", "source": + ruleProvided = true + case "revision": + ruleProvided = true + if valueStr, ok := value.(string); ok { + if abbrevRevHash.MatchString(valueStr) { + warns = append(warns, fmt.Errorf("revision %q should not be in abbreviated form", valueStr)) + } + } + case "metadata": + // Check if metadata is of Map type + if reflect.TypeOf(value).Kind() != reflect.Map { + warns = append(warns, fmt.Errorf("metadata in %q should be a TOML table", prop)) + } + default: + // unknown/invalid key + warns = append(warns, fmt.Errorf("invalid key %q in %q", key, prop)) + } + } + if _, ok := props["name"]; !ok { + warns = append(warns, errNoName) + } else if !ruleProvided && prop == "constraint" { + warns = append(warns, fmt.Errorf("branch, version, revision, or source should be provided for %q", props["name"])) + } + } + } + } else { + valid = false + } + + if !valid { + if prop == "constraint" { + return warns, errInvalidConstraint + } + if prop == "override" { + return warns, errInvalidOverride + } + } + case "ignored", "required": + valid := true + if rawList, ok := val.([]interface{}); ok { + // Check element type of the array. TOML doesn't let mixing of types in + // array. Checking one element would be enough. Empty array is valid. + if len(rawList) > 0 && reflect.TypeOf(rawList[0]).Kind() != reflect.String { + valid = false + } + } else { + valid = false + } + + if !valid { + if prop == "ignored" { + return warns, errInvalidIgnored + } + if prop == "required" { + return warns, errInvalidRequired + } + } + case "prune": + pruneWarns, err := validatePruneOptions(val, true) + warns = append(warns, pruneWarns...) + if err != nil { + return warns, err + } + default: + warns = append(warns, fmt.Errorf("unknown field in manifest: %v", prop)) + } + } + + return warns, nil +} + +func validatePruneOptions(val interface{}, root bool) (warns []error, err error) { + if reflect.TypeOf(val).Kind() != reflect.Map { + return warns, errInvalidPrune + } + + for key, value := range val.(map[string]interface{}) { + switch key { + case pruneOptionNonGo, pruneOptionGoTests, pruneOptionUnusedPackages: + if option, ok := value.(bool); !ok { + return warns, errInvalidPruneValue + } else if root && !option { + return warns, errInvalidRootPruneValue + } + case "name": + if root { + warns = append(warns, errRootPruneContainsName) + } else if _, ok := value.(string); !ok { + return warns, errInvalidPruneProjectName + } + case "project": + if !root { + return warns, errPruneSubProject + } + if reflect.TypeOf(value).Kind() != reflect.Slice { + return warns, errInvalidPruneProject + } + + for _, project := range value.([]interface{}) { + projectWarns, err := validatePruneOptions(project, false) + warns = append(warns, projectWarns...) + if err != nil { + return nil, err + } + } + + default: + if root { + warns = append(warns, errors.Errorf("unknown field %q in %q", key, "prune")) + } else { + warns = append(warns, errors.Errorf("unknown field %q in %q", key, "prune.project")) + } + } + } + + return warns, err +} + +func checkRedundantPruneOptions(co gps.CascadingPruneOptions) (warns []error) { + for name, project := range co.PerProjectOptions { + if project.UnusedPackages != pvnone { + if (co.DefaultOptions&gps.PruneUnusedPackages != 0) == (project.UnusedPackages == pvtrue) { + warns = append(warns, errors.Errorf("redundant prune option %q set for %q", pruneOptionUnusedPackages, name)) + } + } + + if project.NonGoFiles != pvnone { + if (co.DefaultOptions&gps.PruneNonGoFiles != 0) == (project.NonGoFiles == pvtrue) { + warns = append(warns, errors.Errorf("redundant prune option %q set for %q", pruneOptionNonGo, name)) + } + } + + if project.GoTests != pvnone { + if (co.DefaultOptions&gps.PruneGoTestFiles != 0) == (project.GoTests == pvtrue) { + warns = append(warns, errors.Errorf("redundant prune option %q set for %q", pruneOptionGoTests, name)) + } + } + } + + return warns +} + +// ValidateProjectRoots validates the project roots present in manifest. +func ValidateProjectRoots(c *Ctx, m *Manifest, sm gps.SourceManager) error { + // Channel to receive all the errors + errorCh := make(chan error, len(m.Constraints)+len(m.Ovr)) + + var wg sync.WaitGroup + + validate := func(pr gps.ProjectRoot) { + defer wg.Done() + origPR, err := sm.DeduceProjectRoot(string(pr)) + if err != nil { + errorCh <- err + } else if origPR != pr { + errorCh <- fmt.Errorf("the name for %q should be changed to %q", pr, origPR) + } + } + + for pr := range m.Constraints { + wg.Add(1) + go validate(pr) + } + for pr := range m.Ovr { + wg.Add(1) + go validate(pr) + } + for pr := range m.PruneOptions.PerProjectOptions { + wg.Add(1) + go validate(pr) + } + + wg.Wait() + close(errorCh) + + var valErr error + if len(errorCh) > 0 { + valErr = errInvalidProjectRoot + c.Err.Printf("The following issues were found in Gopkg.toml:\n\n") + for err := range errorCh { + c.Err.Println(" ✗", err.Error()) + } + c.Err.Println() + } + + return valErr +} + +// readManifest returns a Manifest read from r and a slice of validation warnings. +func readManifest(r io.Reader) (*Manifest, []error, error) { + buf := &bytes.Buffer{} + _, err := buf.ReadFrom(r) + if err != nil { + return nil, nil, errors.Wrap(err, "unable to read byte stream") + } + + warns, err := validateManifest(buf.String()) + if err != nil { + return nil, warns, errors.Wrap(err, "manifest validation failed") + } + + raw := rawManifest{} + err = toml.Unmarshal(buf.Bytes(), &raw) + if err != nil { + return nil, warns, errors.Wrap(err, "unable to parse the manifest as TOML") + } + + m, err := fromRawManifest(raw, buf) + if err != nil { + return nil, warns, err + } + + warns = append(warns, checkRedundantPruneOptions(m.PruneOptions)...) + return m, warns, nil +} + +func fromRawManifest(raw rawManifest, buf *bytes.Buffer) (*Manifest, error) { + m := NewManifest() + + m.Constraints = make(gps.ProjectConstraints, len(raw.Constraints)) + m.Ovr = make(gps.ProjectConstraints, len(raw.Overrides)) + m.Ignored = raw.Ignored + m.Required = raw.Required + + for i := 0; i < len(raw.Constraints); i++ { + name, prj, err := toProject(raw.Constraints[i]) + if err != nil { + return nil, err + } + if _, exists := m.Constraints[name]; exists { + return nil, errors.Errorf("multiple dependencies specified for %s, can only specify one", name) + } + m.Constraints[name] = prj + } + + for i := 0; i < len(raw.Overrides); i++ { + name, prj, err := toProject(raw.Overrides[i]) + if err != nil { + return nil, err + } + if _, exists := m.Ovr[name]; exists { + return nil, errors.Errorf("multiple overrides specified for %s, can only specify one", name) + } + m.Ovr[name] = prj + } + + // TODO(sdboyer) it is awful that we have to do this manual extraction + tree, err := toml.Load(buf.String()) + if err != nil { + return nil, errors.Wrap(err, "unable to load TomlTree from string") + } + + iprunemap := tree.Get("prune") + if iprunemap == nil { + return m, nil + } + // Previous validation already guaranteed that, if it exists, it's this map + // type. + m.PruneOptions = fromRawPruneOptions(iprunemap.(*toml.Tree).ToMap()) + + return m, nil +} + +func fromRawPruneOptions(prunemap map[string]interface{}) gps.CascadingPruneOptions { + opts := gps.CascadingPruneOptions{ + DefaultOptions: gps.PruneNestedVendorDirs, + PerProjectOptions: make(map[gps.ProjectRoot]gps.PruneOptionSet), + } + + if val, has := prunemap[pruneOptionUnusedPackages]; has && val.(bool) { + opts.DefaultOptions |= gps.PruneUnusedPackages + } + if val, has := prunemap[pruneOptionNonGo]; has && val.(bool) { + opts.DefaultOptions |= gps.PruneNonGoFiles + } + if val, has := prunemap[pruneOptionGoTests]; has && val.(bool) { + opts.DefaultOptions |= gps.PruneGoTestFiles + } + + trinary := func(v interface{}) uint8 { + b := v.(bool) + if b { + return pvtrue + } + return pvfalse + } + + if projprunes, has := prunemap["project"]; has { + for _, proj := range projprunes.([]interface{}) { + var pr gps.ProjectRoot + // This should be redundant, but being explicit doesn't hurt. + pos := gps.PruneOptionSet{NestedVendor: pvtrue} + + for key, val := range proj.(map[string]interface{}) { + switch key { + case "name": + pr = gps.ProjectRoot(val.(string)) + case pruneOptionNonGo: + pos.NonGoFiles = trinary(val) + case pruneOptionGoTests: + pos.GoTests = trinary(val) + case pruneOptionUnusedPackages: + pos.UnusedPackages = trinary(val) + } + } + opts.PerProjectOptions[pr] = pos + } + } + + return opts +} + +// toRawPruneOptions converts a gps.RootPruneOption's PruneOptions to rawPruneOptions +// +// Will panic if gps.RootPruneOption includes ProjectPruneOptions +// See https://github.com/golang/dep/pull/1460#discussion_r158128740 for more information +func toRawPruneOptions(co gps.CascadingPruneOptions) rawPruneOptions { + if len(co.PerProjectOptions) != 0 { + panic("toRawPruneOptions cannot convert ProjectOptions to rawPruneOptions") + } + raw := rawPruneOptions{} + + if (co.DefaultOptions & gps.PruneUnusedPackages) != 0 { + raw.UnusedPackages = true + } + + if (co.DefaultOptions & gps.PruneNonGoFiles) != 0 { + raw.NonGoFiles = true + } + + if (co.DefaultOptions & gps.PruneGoTestFiles) != 0 { + raw.GoTests = true + } + return raw +} + +// toProject interprets the string representations of project information held in +// a rawProject, converting them into a proper gps.ProjectProperties. An +// error is returned if the rawProject contains some invalid combination - +// for example, if both a branch and version constraint are specified. +func toProject(raw rawProject) (n gps.ProjectRoot, pp gps.ProjectProperties, err error) { + n = gps.ProjectRoot(raw.Name) + if raw.Branch != "" { + if raw.Version != "" || raw.Revision != "" { + return n, pp, errors.Errorf("multiple constraints specified for %s, can only specify one", n) + } + pp.Constraint = gps.NewBranch(raw.Branch) + } else if raw.Version != "" { + if raw.Revision != "" { + return n, pp, errors.Errorf("multiple constraints specified for %s, can only specify one", n) + } + + // always semver if we can + pp.Constraint, err = gps.NewSemverConstraintIC(raw.Version) + if err != nil { + // but if not, fall back on plain versions + pp.Constraint = gps.NewVersion(raw.Version) + } + } else if raw.Revision != "" { + pp.Constraint = gps.Revision(raw.Revision) + } else { + // If the user specifies nothing, it means an open constraint (accept + // anything). + pp.Constraint = gps.Any() + } + + pp.Source = raw.Source + + return n, pp, nil +} + +// MarshalTOML serializes this manifest into TOML via an intermediate raw form. +func (m *Manifest) MarshalTOML() ([]byte, error) { + raw := m.toRaw() + var buf bytes.Buffer + enc := toml.NewEncoder(&buf).ArraysWithOneElementPerLine(true) + err := enc.Encode(raw) + return buf.Bytes(), errors.Wrap(err, "unable to marshal the lock to a TOML string") +} + +// toRaw converts the manifest into a representation suitable to write to the manifest file +func (m *Manifest) toRaw() rawManifest { + raw := rawManifest{ + Constraints: make([]rawProject, 0, len(m.Constraints)), + Overrides: make([]rawProject, 0, len(m.Ovr)), + Ignored: m.Ignored, + Required: m.Required, + } + + for n, prj := range m.Constraints { + raw.Constraints = append(raw.Constraints, toRawProject(n, prj)) + } + sort.Sort(sortedRawProjects(raw.Constraints)) + + for n, prj := range m.Ovr { + raw.Overrides = append(raw.Overrides, toRawProject(n, prj)) + } + sort.Sort(sortedRawProjects(raw.Overrides)) + + raw.PruneOptions = toRawPruneOptions(m.PruneOptions) + + return raw +} + +type sortedRawProjects []rawProject + +func (s sortedRawProjects) Len() int { return len(s) } +func (s sortedRawProjects) Swap(i, j int) { s[i], s[j] = s[j], s[i] } +func (s sortedRawProjects) Less(i, j int) bool { + l, r := s[i], s[j] + + if l.Name < r.Name { + return true + } + if r.Name < l.Name { + return false + } + + return l.Source < r.Source +} + +func toRawProject(name gps.ProjectRoot, project gps.ProjectProperties) rawProject { + raw := rawProject{ + Name: string(name), + Source: project.Source, + } + + if v, ok := project.Constraint.(gps.Version); ok { + switch v.Type() { + case gps.IsRevision: + raw.Revision = v.String() + case gps.IsBranch: + raw.Branch = v.String() + case gps.IsSemver, gps.IsVersion: + raw.Version = v.ImpliedCaretString() + } + return raw + } + + // We simply don't allow for a case where the user could directly + // express a 'none' constraint, so we can ignore it here. We also ignore + // the 'any' case, because that's the other possibility, and it's what + // we interpret not having any constraint expressions at all to mean. + // if !gps.IsAny(pp.Constraint) && !gps.IsNone(pp.Constraint) { + if !gps.IsAny(project.Constraint) && project.Constraint != nil { + // Has to be a semver range. + raw.Version = project.Constraint.ImpliedCaretString() + } + + return raw +} + +// DependencyConstraints returns a list of project-level constraints. +func (m *Manifest) DependencyConstraints() gps.ProjectConstraints { + return m.Constraints +} + +// Overrides returns a list of project-level override constraints. +func (m *Manifest) Overrides() gps.ProjectConstraints { + return m.Ovr +} + +// IgnoredPackages returns a set of import paths to ignore. +func (m *Manifest) IgnoredPackages() *pkgtree.IgnoredRuleset { + return pkgtree.NewIgnoredRuleset(m.Ignored) +} + +// HasConstraintsOn checks if the manifest contains either constraints or +// overrides on the provided ProjectRoot. +func (m *Manifest) HasConstraintsOn(root gps.ProjectRoot) bool { + if _, has := m.Constraints[root]; has { + return true + } + if _, has := m.Ovr[root]; has { + return true + } + + return false +} + +// RequiredPackages returns a set of import paths to require. +func (m *Manifest) RequiredPackages() map[string]bool { + if len(m.Required) == 0 { + return nil + } + + mp := make(map[string]bool, len(m.Required)) + for _, i := range m.Required { + mp[i] = true + } + + return mp +} diff --git a/vendor/github.com/golang/dep/manifest_test.go b/vendor/github.com/golang/dep/manifest_test.go new file mode 100644 index 00000000..28d5e43b --- /dev/null +++ b/vendor/github.com/golang/dep/manifest_test.go @@ -0,0 +1,821 @@ +// Copyright 2016 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 dep + +import ( + "bytes" + "errors" + "fmt" + "io/ioutil" + "log" + "reflect" + "strings" + "testing" + + "github.com/golang/dep/gps" + "github.com/golang/dep/internal/test" +) + +func TestReadManifest(t *testing.T) { + h := test.NewHelper(t) + defer h.Cleanup() + + mf := h.GetTestFile("manifest/golden.toml") + defer mf.Close() + got, _, err := readManifest(mf) + if err != nil { + t.Fatalf("should have read manifest correctly, but got err %q", err) + } + + c, _ := gps.NewSemverConstraint("^0.12.0") + want := Manifest{ + Constraints: map[gps.ProjectRoot]gps.ProjectProperties{ + gps.ProjectRoot("github.com/golang/dep"): { + Constraint: c, + }, + gps.ProjectRoot("github.com/babble/brook"): { + Constraint: gps.Revision("d05d5aca9f895d19e9265839bffeadd74a2d2ecb"), + }, + }, + Ovr: map[gps.ProjectRoot]gps.ProjectProperties{ + gps.ProjectRoot("github.com/golang/dep"): { + Source: "https://github.com/golang/dep", + Constraint: gps.NewBranch("master"), + }, + }, + Ignored: []string{"github.com/foo/bar"}, + PruneOptions: gps.CascadingPruneOptions{ + DefaultOptions: gps.PruneNestedVendorDirs | gps.PruneNonGoFiles, + PerProjectOptions: make(map[gps.ProjectRoot]gps.PruneOptionSet), + }, + } + + if !reflect.DeepEqual(got.Constraints, want.Constraints) { + t.Error("Valid manifest's dependencies did not parse as expected") + } + if !reflect.DeepEqual(got.Ovr, want.Ovr) { + t.Error("Valid manifest's overrides did not parse as expected") + } + if !reflect.DeepEqual(got.Ignored, want.Ignored) { + t.Error("Valid manifest's ignored did not parse as expected") + } + if !reflect.DeepEqual(got.PruneOptions, want.PruneOptions) { + t.Error("Valid manifest's prune options did not parse as expected") + t.Error(got.PruneOptions, want.PruneOptions) + } +} + +func TestWriteManifest(t *testing.T) { + h := test.NewHelper(t) + defer h.Cleanup() + + golden := "manifest/golden.toml" + want := h.GetTestFileString(golden) + c, _ := gps.NewSemverConstraint("^0.12.0") + m := NewManifest() + m.Constraints[gps.ProjectRoot("github.com/golang/dep")] = gps.ProjectProperties{ + Constraint: c, + } + m.Constraints[gps.ProjectRoot("github.com/babble/brook")] = gps.ProjectProperties{ + Constraint: gps.Revision("d05d5aca9f895d19e9265839bffeadd74a2d2ecb"), + } + m.Ovr[gps.ProjectRoot("github.com/golang/dep")] = gps.ProjectProperties{ + Source: "https://github.com/golang/dep", + Constraint: gps.NewBranch("master"), + } + m.Ignored = []string{"github.com/foo/bar"} + m.PruneOptions = gps.CascadingPruneOptions{ + DefaultOptions: gps.PruneNestedVendorDirs | gps.PruneNonGoFiles, + PerProjectOptions: make(map[gps.ProjectRoot]gps.PruneOptionSet), + } + + got, err := m.MarshalTOML() + if err != nil { + t.Fatalf("error while marshaling valid manifest to TOML: %q", err) + } + + if string(got) != want { + if *test.UpdateGolden { + if err = h.WriteTestFile(golden, string(got)); err != nil { + t.Fatal(err) + } + } else { + t.Errorf("valid manifest did not marshal to TOML as expected:\n(GOT):\n%s\n(WNT):\n%s", string(got), want) + } + } +} + +func TestReadManifestErrors(t *testing.T) { + h := test.NewHelper(t) + defer h.Cleanup() + var err error + + tests := []struct { + name string + file string + }{ + {"multiple constraints", "manifest/error1.toml"}, + {"multiple dependencies", "manifest/error2.toml"}, + {"multiple overrides", "manifest/error3.toml"}, + } + + for _, tst := range tests { + mf := h.GetTestFile(tst.file) + defer mf.Close() + _, _, err = readManifest(mf) + if err == nil { + t.Errorf("reading manifest with %s should have caused error, but did not", tst.name) + } else if !strings.Contains(err.Error(), tst.name) { + t.Errorf("unexpected error %q; expected %s error", err, tst.name) + } + } +} + +func TestValidateManifest(t *testing.T) { + cases := []struct { + name string + tomlString string + wantWarn []error + wantError error + }{ + { + name: "valid required", + tomlString: ` + required = ["github.com/foo/bar"] + `, + wantWarn: []error{}, + wantError: nil, + }, + { + name: "invalid required", + tomlString: ` + required = "github.com/foo/bar" + `, + wantWarn: []error{}, + wantError: errInvalidRequired, + }, + { + name: "empty required", + tomlString: ` + required = [] + `, + wantWarn: []error{}, + wantError: nil, + }, + { + name: "invalid required list", + tomlString: ` + required = [1, 2, 3] + `, + wantWarn: []error{}, + wantError: errInvalidRequired, + }, + { + name: "invalid required format", + tomlString: ` + [[required]] + name = "foo" + `, + wantWarn: []error{}, + wantError: errInvalidRequired, + }, + { + name: "valid ignored", + tomlString: ` + ignored = ["foo"] + `, + wantWarn: []error{}, + wantError: nil, + }, + { + name: "invalid ignored", + tomlString: ` + ignored = "foo" + `, + wantWarn: []error{}, + wantError: errInvalidIgnored, + }, + { + name: "empty ignored", + tomlString: ` + ignored = [] + `, + wantWarn: []error{}, + wantError: nil, + }, + { + name: "invalid ignored list", + tomlString: ` + ignored = [1, 2, 3] + `, + wantWarn: []error{}, + wantError: errInvalidIgnored, + }, + { + name: "invalid ignored format", + tomlString: ` + [[ignored]] + name = "foo" + `, + wantWarn: []error{}, + wantError: errInvalidIgnored, + }, + { + name: "valid metadata", + tomlString: ` + [metadata] + authors = "foo" + version = "1.0.0" + `, + wantWarn: []error{}, + wantError: nil, + }, + { + name: "invalid metadata", + tomlString: ` + foo = "some-value" + version = 14 + + [[bar]] + author = "xyz" + + [[constraint]] + name = "github.com/foo/bar" + version = "" + `, + wantWarn: []error{ + errors.New("unknown field in manifest: foo"), + errors.New("unknown field in manifest: bar"), + errors.New("unknown field in manifest: version"), + }, + wantError: nil, + }, + { + name: "invalid metadata format", + tomlString: ` + metadata = "project-name" + + [[constraint]] + name = "github.com/foo/bar" + `, + wantWarn: []error{ + errInvalidMetadata, + errors.New("branch, version, revision, or source should be provided for \"github.com/foo/bar\""), + }, + wantError: nil, + }, + { + name: "plain constraint", + tomlString: ` + [[constraint]] + name = "github.com/foo/bar" + `, + wantWarn: []error{ + errors.New("branch, version, revision, or source should be provided for \"github.com/foo/bar\""), + }, + wantError: nil, + }, + { + name: "empty constraint", + tomlString: ` + [[constraint]] + `, + wantWarn: []error{ + errNoName, + }, + wantError: nil, + }, + { + name: "invalid constraint", + tomlString: ` + constraint = "foo" + `, + wantWarn: []error{}, + wantError: errInvalidConstraint, + }, + { + name: "invalid constraint list", + tomlString: ` + constraint = ["foo", "bar"] + `, + wantWarn: []error{}, + wantError: errInvalidConstraint, + }, + { + name: "valid override", + tomlString: ` + [[override]] + name = "github.com/foo/bar" + `, + wantWarn: []error{}, + wantError: nil, + }, + { + name: "empty override", + tomlString: ` + [[override]] + `, + wantWarn: []error{ + errNoName, + }, + wantError: nil, + }, + { + name: "invalid override", + tomlString: ` + override = "bar" + `, + wantWarn: []error{}, + wantError: errInvalidOverride, + }, + { + name: "invalid override list", + tomlString: ` + override = ["foo", "bar"] + `, + wantWarn: []error{}, + wantError: errInvalidOverride, + }, + { + name: "invalid fields", + tomlString: ` + [[constraint]] + name = "github.com/foo/bar" + location = "some-value" + link = "some-other-value" + metadata = "foo" + + [[override]] + nick = "foo" + `, + wantWarn: []error{ + errors.New("invalid key \"location\" in \"constraint\""), + errors.New("invalid key \"link\" in \"constraint\""), + errors.New("metadata in \"constraint\" should be a TOML table"), + errors.New("branch, version, revision, or source should be provided for \"github.com/foo/bar\""), + errors.New("invalid key \"nick\" in \"override\""), + errNoName, + }, + wantError: nil, + }, + { + name: "constraint metadata", + tomlString: ` + [[constraint]] + name = "github.com/foo/bar" + + [constraint.metadata] + color = "blue" + `, + wantWarn: []error{ + errors.New("branch, version, revision, or source should be provided for \"github.com/foo/bar\""), + }, + wantError: nil, + }, + { + name: "invalid revision", + tomlString: ` + [[constraint]] + name = "github.com/foo/bar" + revision = "b86ad16" + `, + wantWarn: []error{ + errors.New("revision \"b86ad16\" should not be in abbreviated form"), + }, + wantError: nil, + }, + { + name: "invalid hg revision", + tomlString: ` + [[constraint]] + name = "foobar.com/hg" + revision = "8d43f8c0b836" + `, + wantWarn: []error{errors.New("revision \"8d43f8c0b836\" should not be in abbreviated form")}, + wantError: nil, + }, + { + name: "valid prune options", + tomlString: ` + [prune] + non-go = true + `, + wantWarn: []error{}, + wantError: nil, + }, + { + name: "invalid root prune options", + tomlString: ` + [prune] + non-go = false + `, + wantWarn: []error{}, + wantError: errInvalidRootPruneValue, + }, + { + name: "root options should not contain a name", + tomlString: ` + [prune] + go-tests = true + name = "github.com/golang/dep" + `, + wantWarn: []error{ + errRootPruneContainsName, + }, + wantError: nil, + }, + { + name: "invalid prune project", + tomlString: ` + [prune] + non-go = true + + [prune.project] + name = "github.com/org/project" + non-go = true + `, + wantWarn: []error{}, + wantError: errInvalidPruneProject, + }, + } + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + errs, err := validateManifest(c.tomlString) + + // compare validation errors + if err != c.wantError { + t.Fatalf("manifest errors are not as expected: \n\t(GOT) %v \n\t(WNT) %v", err, c.wantError) + } + + // compare length of error slice + if len(errs) != len(c.wantWarn) { + t.Fatalf("number of manifest errors are not as expected: \n\t(GOT) %v errors(%v)\n\t(WNT) %v errors(%v).", len(errs), errs, len(c.wantWarn), c.wantWarn) + } + + // check if the expected errors exist in actual errors slice + for _, er := range errs { + if !containsErr(c.wantWarn, er) { + t.Fatalf("manifest errors are not as expected: \n\t(MISSING) %v\n\t(FROM) %v", er, c.wantWarn) + } + } + }) + } +} + +func TestCheckRedundantPruneOptions(t *testing.T) { + cases := []struct { + name string + pruneOptions gps.CascadingPruneOptions + wantWarn []error + }{ + { + name: "all redundant on true", + pruneOptions: gps.CascadingPruneOptions{ + DefaultOptions: 15, + PerProjectOptions: map[gps.ProjectRoot]gps.PruneOptionSet{ + "github.com/golang/dep": gps.PruneOptionSet{ + NestedVendor: pvtrue, + UnusedPackages: pvtrue, + NonGoFiles: pvtrue, + GoTests: pvtrue, + }, + }, + }, + wantWarn: []error{ + fmt.Errorf("redundant prune option %q set for %q", "unused-packages", "github.com/golang/dep"), + fmt.Errorf("redundant prune option %q set for %q", "non-go", "github.com/golang/dep"), + fmt.Errorf("redundant prune option %q set for %q", "go-tests", "github.com/golang/dep"), + }, + }, + { + name: "all redundant on false", + pruneOptions: gps.CascadingPruneOptions{ + DefaultOptions: 1, + PerProjectOptions: map[gps.ProjectRoot]gps.PruneOptionSet{ + "github.com/golang/dep": gps.PruneOptionSet{ + NestedVendor: pvtrue, + UnusedPackages: pvfalse, + NonGoFiles: pvfalse, + GoTests: pvfalse, + }, + }, + }, + wantWarn: []error{ + fmt.Errorf("redundant prune option %q set for %q", "unused-packages", "github.com/golang/dep"), + fmt.Errorf("redundant prune option %q set for %q", "non-go", "github.com/golang/dep"), + fmt.Errorf("redundant prune option %q set for %q", "go-tests", "github.com/golang/dep"), + }, + }, + { + name: "redundancy mix across multiple projects", + pruneOptions: gps.CascadingPruneOptions{ + DefaultOptions: 7, + PerProjectOptions: map[gps.ProjectRoot]gps.PruneOptionSet{ + "github.com/golang/dep": gps.PruneOptionSet{ + NestedVendor: pvtrue, + NonGoFiles: pvtrue, + GoTests: pvtrue, + }, + "github.com/other/project": gps.PruneOptionSet{ + NestedVendor: pvtrue, + UnusedPackages: pvfalse, + GoTests: pvfalse, + }, + }, + }, + wantWarn: []error{ + fmt.Errorf("redundant prune option %q set for %q", "non-go", "github.com/golang/dep"), + fmt.Errorf("redundant prune option %q set for %q", "go-tests", "github.com/other/project"), + }, + }, + } + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + errs := checkRedundantPruneOptions(c.pruneOptions) + + // compare length of error slice + if len(errs) != len(c.wantWarn) { + t.Fatalf("number of manifest errors are not as expected:\n\t(GOT) %v errors(%v)\n\t(WNT) %v errors(%v).", len(errs), errs, len(c.wantWarn), c.wantWarn) + } + + for _, er := range errs { + if !containsErr(c.wantWarn, er) { + t.Fatalf("manifest errors are not as expected:\n\t(MISSING)\n%v\n\t(FROM)\n%v", er, c.wantWarn) + } + } + }) + } +} + +func TestValidateProjectRoots(t *testing.T) { + cases := []struct { + name string + manifest Manifest + wantError error + wantWarn []string + }{ + { + name: "empty Manifest", + manifest: Manifest{}, + wantError: nil, + wantWarn: []string{}, + }, + { + name: "valid project root", + manifest: Manifest{ + Constraints: map[gps.ProjectRoot]gps.ProjectProperties{ + gps.ProjectRoot("github.com/golang/dep"): { + Constraint: gps.Any(), + }, + }, + }, + wantError: nil, + wantWarn: []string{}, + }, + { + name: "invalid project roots in Constraints and Overrides", + manifest: Manifest{ + Constraints: map[gps.ProjectRoot]gps.ProjectProperties{ + gps.ProjectRoot("github.com/golang/dep/foo"): { + Constraint: gps.Any(), + }, + gps.ProjectRoot("github.com/golang/go/xyz"): { + Constraint: gps.Any(), + }, + gps.ProjectRoot("github.com/golang/fmt"): { + Constraint: gps.Any(), + }, + }, + Ovr: map[gps.ProjectRoot]gps.ProjectProperties{ + gps.ProjectRoot("github.com/golang/mock/bar"): { + Constraint: gps.Any(), + }, + gps.ProjectRoot("github.com/golang/mock"): { + Constraint: gps.Any(), + }, + }, + }, + wantError: errInvalidProjectRoot, + wantWarn: []string{ + "the name for \"github.com/golang/dep/foo\" should be changed to \"github.com/golang/dep\"", + "the name for \"github.com/golang/mock/bar\" should be changed to \"github.com/golang/mock\"", + "the name for \"github.com/golang/go/xyz\" should be changed to \"github.com/golang/go\"", + }, + }, + { + name: "invalid source path", + manifest: Manifest{ + Constraints: map[gps.ProjectRoot]gps.ProjectProperties{ + gps.ProjectRoot("github.com/golang"): { + Constraint: gps.Any(), + }, + }, + }, + wantError: errInvalidProjectRoot, + wantWarn: []string{}, + }, + } + + h := test.NewHelper(t) + defer h.Cleanup() + + h.TempDir("src") + pwd := h.Path(".") + + // Capture the stderr to verify the warnings + stderrOutput := &bytes.Buffer{} + errLogger := log.New(stderrOutput, "", 0) + ctx := &Ctx{ + GOPATH: pwd, + Out: log.New(ioutil.Discard, "", 0), + Err: errLogger, + } + + sm, err := ctx.SourceManager() + h.Must(err) + defer sm.Release() + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + // Empty the buffer for every case + stderrOutput.Reset() + err := ValidateProjectRoots(ctx, &c.manifest, sm) + if err != c.wantError { + t.Fatalf("unexpected error while validating project roots:\n\t(GOT): %v\n\t(WNT): %v", err, c.wantError) + } + + warnings := stderrOutput.String() + for _, warn := range c.wantWarn { + if !strings.Contains(warnings, warn) { + t.Fatalf("expected ValidateProjectRoot errors to contain: %q", warn) + } + } + }) + } +} + +//func TestFromRawPruneOptions(t *testing.T) { +//cases := []struct { +//name string +//rawPruneOptions rawPruneOptions +//wantOptions gps.CascadingPruneOptions +//}{ +//{ +//name: "global all options project no options", +//rawPruneOptions: rawPruneOptions{ +//UnusedPackages: true, +//NonGoFiles: true, +//GoTests: true, +//Projects: []map[string]interface{}{ +//{ +//"name": "github.com/golang/dep", +//pruneOptionUnusedPackages: false, +//pruneOptionNonGo: false, +//pruneOptionGoTests: false, +//}, +//}, +//}, +//wantOptions: gps.CascadingPruneOptions{ +//DefaultOptions: 15, +//PerProjectOptions: map[gps.ProjectRoot]gps.PruneOptionSet{ +//"github.com/golang/dep": gps.PruneOptionSet{ +//NestedVendor: pvtrue, +//UnusedPackages: pvfalse, +//NonGoFiles: pvfalse, +//GoTests: pvfalse, +//}, +//}, +//}, +//}, +//{ +//name: "global all options project mixed options", +//rawPruneOptions: rawPruneOptions{ +//UnusedPackages: true, +//NonGoFiles: true, +//GoTests: true, +//Projects: []map[string]interface{}{ +//{ +//"name": "github.com/golang/dep", +//pruneOptionUnusedPackages: false, +//}, +//}, +//}, +//wantOptions: gps.CascadingPruneOptions{ +//DefaultOptions: 15, +//PerProjectOptions: map[gps.ProjectRoot]gps.PruneOptionSet{ +//"github.com/golang/dep": gps.PruneOptionSet{ +//NestedVendor: pvtrue, +//UnusedPackages: pvfalse, +//}, +//}, +//}, +//}, +//{ +//name: "global no options project all options", +//rawPruneOptions: rawPruneOptions{ +//UnusedPackages: false, +//NonGoFiles: false, +//GoTests: false, +//Projects: []map[string]interface{}{ +//{ +//"name": "github.com/golang/dep", +//pruneOptionUnusedPackages: true, +//pruneOptionNonGo: true, +//pruneOptionGoTests: true, +//}, +//}, +//}, +//wantOptions: gps.CascadingPruneOptions{ +//DefaultOptions: 1, +//PerProjectOptions: map[gps.ProjectRoot]gps.PruneOptionSet{ +//"github.com/golang/dep": gps.PruneOptionSet{ +//NestedVendor: pvtrue, +//UnusedPackages: pvtrue, +//NonGoFiles: pvtrue, +//GoTests: pvtrue, +//}, +//}, +//}, +//}, +//} + +//for _, c := range cases { +//t.Run(c.name, func(t *testing.T) { +//opts, err := fromRawPruneOptions(c.rawPruneOptions) +//if err != nil { +//t.Fatal(err) +//} + +//if !reflect.DeepEqual(opts, c.wantOptions) { +//t.Fatalf("rawPruneOptions are not as expected:\n\t(GOT) %v\n\t(WNT) %v", opts, c.wantOptions) +//} +//}) +//} +//} + +func TestToRawPruneOptions(t *testing.T) { + cases := []struct { + name string + pruneOptions gps.CascadingPruneOptions + wantOptions rawPruneOptions + }{ + { + name: "all options", + pruneOptions: gps.CascadingPruneOptions{DefaultOptions: 15}, + wantOptions: rawPruneOptions{ + UnusedPackages: true, + NonGoFiles: true, + GoTests: true, + }, + }, + { + name: "no options", + pruneOptions: gps.CascadingPruneOptions{DefaultOptions: 1}, + wantOptions: rawPruneOptions{ + UnusedPackages: false, + NonGoFiles: false, + GoTests: false, + }, + }, + } + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + raw := toRawPruneOptions(c.pruneOptions) + + if !reflect.DeepEqual(raw, c.wantOptions) { + t.Fatalf("rawPruneOptions are not as expected:\n\t(GOT) %v\n\t(WNT) %v", raw, c.wantOptions) + } + }) + } +} + +func TestToRawPruneOptions_Panic(t *testing.T) { + pruneOptions := gps.CascadingPruneOptions{ + DefaultOptions: 1, + PerProjectOptions: map[gps.ProjectRoot]gps.PruneOptionSet{ + "github.com/carolynvs/deptest": gps.PruneOptionSet{ + NestedVendor: pvtrue, + }, + }, + } + defer func() { + if err := recover(); err == nil { + t.Error("toRawPruneOptions did not panic with non-empty ProjectOptions") + } + }() + _ = toRawPruneOptions(pruneOptions) +} + +func containsErr(s []error, e error) bool { + for _, a := range s { + if a.Error() == e.Error() { + return true + } + } + return false +} diff --git a/vendor/github.com/golang/dep/project.go b/vendor/github.com/golang/dep/project.go new file mode 100644 index 00000000..d2677e88 --- /dev/null +++ b/vendor/github.com/golang/dep/project.go @@ -0,0 +1,276 @@ +// Copyright 2016 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 dep + +import ( + "fmt" + "os" + "path/filepath" + "sort" + + "github.com/golang/dep/gps" + "github.com/golang/dep/gps/paths" + "github.com/golang/dep/gps/pkgtree" + "github.com/golang/dep/internal/fs" + "github.com/pkg/errors" +) + +var ( + errProjectNotFound = fmt.Errorf("could not find project %s, use dep init to initiate a manifest", ManifestName) + errVendorBackupFailed = fmt.Errorf("failed to create vendor backup. File with same name exists") +) + +// findProjectRoot searches from the starting directory upwards looking for a +// manifest file until we get to the root of the filesystem. +func findProjectRoot(from string) (string, error) { + for { + mp := filepath.Join(from, ManifestName) + + _, err := os.Stat(mp) + if err == nil { + return from, nil + } + if !os.IsNotExist(err) { + // Some err other than non-existence - return that out + return "", err + } + + parent := filepath.Dir(from) + if parent == from { + return "", errProjectNotFound + } + from = parent + } +} + +// checkGopkgFilenames validates filename case for the manifest and lock files. +// +// This is relevant on case-insensitive file systems like the defaults in Windows and +// macOS. +// +// If manifest file is not found, it returns an error indicating the project could not be +// found. If it is found but the case does not match, an error is returned. If a lock +// file is not found, no error is returned as lock file is optional. If it is found but +// the case does not match, an error is returned. +func checkGopkgFilenames(projectRoot string) error { + // ReadActualFilenames is actually costly. Since the check to validate filename case + // for Gopkg filenames is not relevant to case-sensitive filesystems like + // ext4(linux), try for an early return. + caseSensitive, err := fs.IsCaseSensitiveFilesystem(projectRoot) + if err != nil { + return errors.Wrap(err, "could not check validity of configuration filenames") + } + if caseSensitive { + return nil + } + + actualFilenames, err := fs.ReadActualFilenames(projectRoot, []string{ManifestName, LockName}) + + if err != nil { + return errors.Wrap(err, "could not check validity of configuration filenames") + } + + actualMfName, found := actualFilenames[ManifestName] + if !found { + // Ideally this part of the code won't ever be executed if it is called after + // `findProjectRoot`. But be thorough and handle it anyway. + return errProjectNotFound + } + if actualMfName != ManifestName { + return fmt.Errorf("manifest filename %q does not match %q", actualMfName, ManifestName) + } + + // If a file is not found, the string map returned by `fs.ReadActualFilenames` will + // not have an entry for the given filename. Since the lock file is optional, we + // should check for equality only if it was found. + actualLfName, found := actualFilenames[LockName] + if found && actualLfName != LockName { + return fmt.Errorf("lock filename %q does not match %q", actualLfName, LockName) + } + + return nil +} + +// A Project holds a Manifest and optional Lock for a project. +type Project struct { + // AbsRoot is the absolute path to the root directory of the project. + AbsRoot string + // ResolvedAbsRoot is the resolved absolute path to the root directory of the project. + // If AbsRoot is not a symlink, then ResolvedAbsRoot should equal AbsRoot. + ResolvedAbsRoot string + // ImportRoot is the import path of the project's root directory. + ImportRoot gps.ProjectRoot + Manifest *Manifest + Lock *Lock // Optional + RootPackageTree pkgtree.PackageTree +} + +// SetRoot sets the project AbsRoot and ResolvedAbsRoot. If root is not a symlink, ResolvedAbsRoot will be set to root. +func (p *Project) SetRoot(root string) error { + rroot, err := filepath.EvalSymlinks(root) + if err != nil { + return err + } + + p.ResolvedAbsRoot, p.AbsRoot = rroot, root + return nil +} + +// MakeParams is a simple helper to create a gps.SolveParameters without setting +// any nils incorrectly. +func (p *Project) MakeParams() gps.SolveParameters { + params := gps.SolveParameters{ + RootDir: p.AbsRoot, + ProjectAnalyzer: Analyzer{}, + } + + if p.Manifest != nil { + params.Manifest = p.Manifest + } + + if p.Lock != nil { + params.Lock = p.Lock + } + + return params +} + +// ParseRootPackageTree analyzes the root project's disk contents to create a +// PackageTree, trimming out packages that are not relevant for root projects +// along the way. +// +// The resulting tree is cached internally at p.RootPackageTree. +func (p *Project) ParseRootPackageTree() (pkgtree.PackageTree, error) { + if p.RootPackageTree.Packages == nil { + ptree, err := pkgtree.ListPackages(p.ResolvedAbsRoot, string(p.ImportRoot)) + if err != nil { + return pkgtree.PackageTree{}, errors.Wrap(err, "analysis of current project's packages failed") + } + // We don't care about (unreachable) hidden packages for the root project, + // so drop all of those. + var ig *pkgtree.IgnoredRuleset + if p.Manifest != nil { + ig = p.Manifest.IgnoredPackages() + } + p.RootPackageTree = ptree.TrimHiddenPackages(true, true, ig) + } + return p.RootPackageTree, nil +} + +// GetDirectDependencyNames returns the set of unique Project Roots that are the +// direct dependencies of this Project. +// +// A project is considered a direct dependency if at least one of packages in it +// is named in either this Project's required list, or if there is at least one +// non-ignored import statement from a non-ignored package in the current +// project's package tree. +// +// The returned map of Project Roots contains only boolean true values; this +// makes a "false" value always indicate an absent key, which makes conditional +// checks against the map more ergonomic. +// +// This function will correctly utilize ignores and requireds from an existing +// manifest, if one is present, but will also do the right thing without a +// manifest. +func (p *Project) GetDirectDependencyNames(sm gps.SourceManager) (pkgtree.PackageTree, map[gps.ProjectRoot]bool, error) { + ptree, err := p.ParseRootPackageTree() + if err != nil { + return pkgtree.PackageTree{}, nil, err + } + + var ig *pkgtree.IgnoredRuleset + var req map[string]bool + if p.Manifest != nil { + ig = p.Manifest.IgnoredPackages() + req = p.Manifest.RequiredPackages() + } + + rm, _ := ptree.ToReachMap(true, true, false, ig) + reach := rm.FlattenFn(paths.IsStandardImportPath) + + if len(req) > 0 { + // Make a map of imports that are both in the import path list and the + // required list to avoid duplication. + skip := make(map[string]bool, len(req)) + for _, r := range reach { + if req[r] { + skip[r] = true + } + } + + for r := range req { + if !skip[r] { + reach = append(reach, r) + } + } + } + + directDeps := map[gps.ProjectRoot]bool{} + for _, ip := range reach { + pr, err := sm.DeduceProjectRoot(ip) + if err != nil { + return pkgtree.PackageTree{}, nil, err + } + directDeps[pr] = true + } + + return ptree, directDeps, nil +} + +// FindIneffectualConstraints looks for constraint rules expressed in the +// manifest that will have no effect during solving, as they are specified for +// projects that are not direct dependencies of the Project. +// +// "Direct dependency" here is as implemented by GetDirectDependencyNames(); +// it correctly incorporates all "ignored" and "required" rules. +func (p *Project) FindIneffectualConstraints(sm gps.SourceManager) []gps.ProjectRoot { + if p.Manifest == nil { + return nil + } + + _, dd, err := p.GetDirectDependencyNames(sm) + if err != nil { + return nil + } + + var ineff []gps.ProjectRoot + for pr := range p.Manifest.DependencyConstraints() { + if !dd[pr] { + ineff = append(ineff, pr) + } + } + + sort.Slice(ineff, func(i, j int) bool { + return ineff[i] < ineff[j] + }) + return ineff +} + +// BackupVendor looks for existing vendor directory and if it's not empty, +// creates a backup of it to a new directory with the provided suffix. +func BackupVendor(vpath, suffix string) (string, error) { + // Check if there's a non-empty vendor directory + vendorExists, err := fs.IsNonEmptyDir(vpath) + if err != nil && !os.IsNotExist(err) { + return "", err + } + if vendorExists { + // vpath is a full filepath. We need to split it to prefix the backup dir + // with an "_" + vpathDir, name := filepath.Split(vpath) + vendorbak := filepath.Join(vpathDir, "_"+name+"-"+suffix) + // Check if a directory with same name exists + if _, err = os.Stat(vendorbak); os.IsNotExist(err) { + // Copy existing vendor to vendor-{suffix} + if err := fs.CopyDir(vpath, vendorbak); err != nil { + return "", err + } + return vendorbak, nil + } + return "", errVendorBackupFailed + } + + return "", nil +} diff --git a/vendor/github.com/golang/dep/project_test.go b/vendor/github.com/golang/dep/project_test.go new file mode 100644 index 00000000..eff7d30e --- /dev/null +++ b/vendor/github.com/golang/dep/project_test.go @@ -0,0 +1,222 @@ +// Copyright 2017 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 dep + +import ( + "fmt" + "os" + "path/filepath" + "runtime" + "strings" + "testing" + + "github.com/golang/dep/gps" + "github.com/golang/dep/internal/test" +) + +func TestFindRoot(t *testing.T) { + wd, err := os.Getwd() + if err != nil { + t.Fatal(err) + } + + want := filepath.Join(wd, "testdata", "rootfind") + got1, err := findProjectRoot(want) + if err != nil { + t.Errorf("Unexpected error while finding root: %s", err) + } else if want != got1 { + t.Errorf("findProjectRoot directly on root dir should have found %s, got %s", want, got1) + } + + got2, err := findProjectRoot(filepath.Join(want, "subdir")) + if err != nil { + t.Errorf("Unexpected error while finding root: %s", err) + } else if want != got2 { + t.Errorf("findProjectRoot on subdir should have found %s, got %s", want, got2) + } + + got3, err := findProjectRoot(filepath.Join(want, "nonexistent")) + if err != nil { + t.Errorf("Unexpected error while finding root: %s", err) + } else if want != got3 { + t.Errorf("findProjectRoot on nonexistent subdir should still work and give %s, got %s", want, got3) + } + + root := "/" + p, err := findProjectRoot(root) + if p != "" { + t.Errorf("findProjectRoot with path %s returned non empty string: %s", root, p) + } + if err != errProjectNotFound { + t.Errorf("findProjectRoot want: %#v got: %#v", errProjectNotFound, err) + } + + // The following test does not work on windows because syscall.Stat does not + // return a "not a directory" error. + if runtime.GOOS != "windows" { + got4, err := findProjectRoot(filepath.Join(want, ManifestName)) + if err == nil { + t.Errorf("Should have err'd when trying subdir of file, but returned %s", got4) + } + } +} + +func TestCheckGopkgFilenames(t *testing.T) { + // We are trying to skip this test on file systems which are case-sensiive. We could + // have used `fs.IsCaseSensitiveFilesystem` for this check. However, the code we are + // testing also relies on `fs.IsCaseSensitiveFilesystem`. So a bug in + // `fs.IsCaseSensitiveFilesystem` could prevent this test from being run. This is the + // only scenario where we prefer the OS heuristic over doing the actual work of + // validating filesystem case sensitivity via `fs.IsCaseSensitiveFilesystem`. + if runtime.GOOS != "windows" && runtime.GOOS != "darwin" { + t.Skip("skip this test on non-Windows, non-macOS") + } + + errMsgFor := func(filetype, filename string) func(string) string { + return func(name string) string { + return fmt.Sprintf("%s filename %q does not match %q", filetype, name, filename) + } + } + + manifestErrMsg := errMsgFor("manifest", ManifestName) + lockErrMsg := errMsgFor("lock", LockName) + + invalidMfName := strings.ToLower(ManifestName) + invalidLfName := strings.ToLower(LockName) + + cases := []struct { + wantErr bool + createFiles []string + wantErrMsg string + }{ + // No error should be returned when the project contains a valid manifest file + // but no lock file. + {false, []string{ManifestName}, ""}, + // No error should be returned when the project contains a valid manifest file as + // well as a valid lock file. + {false, []string{ManifestName, LockName}, ""}, + // Error indicating the project was not found should be returned if a manifest + // file is not found. + {true, nil, errProjectNotFound.Error()}, + // Error should be returned if the project has a manifest file with invalid name + // but no lock file. + {true, []string{invalidMfName}, manifestErrMsg(invalidMfName)}, + // Error should be returned if the project has a valid manifest file and an + // invalid lock file. + {true, []string{ManifestName, invalidLfName}, lockErrMsg(invalidLfName)}, + } + + for _, c := range cases { + h := test.NewHelper(t) + defer h.Cleanup() + + // Create a temporary directory which we will use as the project folder. + h.TempDir("") + tmpPath := h.Path(".") + + // Create any files that are needed for the test before invoking + // `checkGopkgFilenames`. + for _, file := range c.createFiles { + h.TempFile(file, "") + } + err := checkGopkgFilenames(tmpPath) + + if c.wantErr { + if err == nil { + // We were expecting an error but did not get one. + t.Fatalf("unexpected error message: \n\t(GOT) nil\n\t(WNT) %s", c.wantErrMsg) + } else if err.Error() != c.wantErrMsg { + // We got an error but it is not the one we were expecting. + t.Fatalf("unexpected error message: \n\t(GOT) %s\n\t(WNT) %s", err.Error(), c.wantErrMsg) + } + } else if err != nil { + // Error was not expected but still we got one + t.Fatalf("unexpected error message: \n\t(GOT) %+v", err) + } + } +} + +func TestProjectMakeParams(t *testing.T) { + m := NewManifest() + m.Ignored = []string{"ignoring this"} + + p := Project{ + AbsRoot: "someroot", + ImportRoot: gps.ProjectRoot("Some project root"), + Manifest: m, + Lock: &Lock{}, + } + + solveParam := p.MakeParams() + + if solveParam.Manifest != p.Manifest { + t.Error("makeParams() returned gps.SolveParameters with incorrect Manifest") + } + + if solveParam.Lock != p.Lock { + t.Error("makeParams() returned gps.SolveParameters with incorrect Lock") + } +} + +func TestBackupVendor(t *testing.T) { + h := test.NewHelper(t) + defer h.Cleanup() + + pc := NewTestProjectContext(h, "vendorbackupproject") + defer pc.Release() + + dummyFile := filepath.Join("vendor", "badinput_fileroot") + pc.CopyFile(dummyFile, "txn_writer/badinput_fileroot") + pc.Load() + + if err := pc.VendorShouldExist(); err != nil { + t.Fatal(err) + } + + // Create a backup + wantName := "_vendor-sfx" + vendorbak, err := BackupVendor("vendor", "sfx") + if err != nil { + t.Fatal(err) + } + + if vendorbak != wantName { + t.Fatalf("Vendor backup name is not as expected: \n\t(GOT) %v\n\t(WNT) %v", vendorbak, wantName) + } + + if err = pc.h.ShouldExist(vendorbak); err != nil { + t.Fatal(err) + } + + if err = pc.h.ShouldExist(vendorbak + string(filepath.Separator) + "badinput_fileroot"); err != nil { + t.Fatal(err) + } + + // Should return error on creating backup with existing filename + vendorbak, err = BackupVendor("vendor", "sfx") + + if err != errVendorBackupFailed { + t.Fatalf("Vendor backup error is not as expected: \n\t(GOT) %v\n\t(WNT) %v", err, errVendorBackupFailed) + } + + if vendorbak != "" { + t.Fatalf("Vendor backup name is not as expected: \n\t(GOT) %v\n\t(WNT) %v", vendorbak, "") + } + + // Delete vendor + if err = os.RemoveAll("vendor"); err != nil { + t.Fatal(err) + } + + // Should return empty backup file name when no vendor exists + vendorbak, err = BackupVendor("vendor", "sfx") + if err != nil { + t.Fatal(err) + } + + if vendorbak != "" { + t.Fatalf("Vendor backup name is not as expected: \n\t(GOT) %v\n\t(WNT) %v", vendorbak, "") + } +} diff --git a/vendor/github.com/golang/dep/test_project_context_test.go b/vendor/github.com/golang/dep/test_project_context_test.go new file mode 100644 index 00000000..c8ab6692 --- /dev/null +++ b/vendor/github.com/golang/dep/test_project_context_test.go @@ -0,0 +1,168 @@ +// Copyright 2016 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 dep + +import ( + "path/filepath" + + "github.com/golang/dep/gps" + "github.com/golang/dep/internal/test" + "github.com/pkg/errors" +) + +// TestProjectContext groups together test project files and helps test them +type TestProjectContext struct { + h *test.Helper + tempDir string // Full path to the temp directory + tempProjectDir string // Relative path of the project under the temp directory + + Context *Ctx + Project *Project + SourceManager gps.SourceManager +} + +// NewTestProjectContext creates a new on-disk test project +func NewTestProjectContext(h *test.Helper, projectName string) *TestProjectContext { + pc := &TestProjectContext{h: h} + + // Create the test project directory + pc.tempProjectDir = filepath.Join("src", projectName) + h.TempDir(pc.tempProjectDir) + pc.tempDir = h.Path(".") + pc.Project = &Project{AbsRoot: filepath.Join(pc.tempDir, pc.tempProjectDir)} + h.Cd(pc.Project.AbsRoot) + h.Setenv("GOPATH", pc.tempDir) + + // Set up a Source Manager + var err error + pc.Context = &Ctx{ + GOPATH: pc.tempDir, + Out: discardLogger(), + Err: discardLogger(), + } + pc.SourceManager, err = pc.Context.SourceManager() + h.Must(errors.Wrap(err, "Unable to create a SourceManager")) + + return pc +} + +// CopyFile copies a file from the testdata directory into the project +// projectPath is the destination file path, relative to the project directory +// testdataPath is the source path, relative to the testdata directory +func (pc *TestProjectContext) CopyFile(projectPath string, testdataPath string) string { + path := filepath.Join(pc.tempProjectDir, projectPath) + pc.h.TempCopy(path, testdataPath) + return path +} + +func (pc *TestProjectContext) Load() { + // TODO(carolynvs): Can't use Ctx.LoadProject until dep doesn't require a manifest at the project root or it also looks for lock + var err error + var m *Manifest + mp := pc.getManifestPath() + if pc.h.Exist(mp) { + mf := pc.h.GetFile(mp) + defer mf.Close() + var warns []error + m, warns, err = readManifest(mf) + for _, warn := range warns { + pc.Context.Err.Printf("dep: WARNING: %v\n", warn) + } + pc.h.Must(errors.Wrapf(err, "Unable to read manifest at %s", mp)) + } + var l *Lock + lp := pc.getLockPath() + if pc.h.Exist(lp) { + lf := pc.h.GetFile(lp) + defer lf.Close() + l, err = readLock(lf) + pc.h.Must(errors.Wrapf(err, "Unable to read lock at %s", lp)) + } + pc.Project.Manifest = m + pc.Project.Lock = l +} + +// GetLockPath returns the full path to the lock +func (pc *TestProjectContext) getLockPath() string { + return filepath.Join(pc.Project.AbsRoot, LockName) +} + +// GetManifestPath returns the full path to the manifest +func (pc *TestProjectContext) getManifestPath() string { + return filepath.Join(pc.Project.AbsRoot, ManifestName) +} + +// GetVendorPath returns the full path to the vendor directory +func (pc *TestProjectContext) getVendorPath() string { + return filepath.Join(pc.Project.AbsRoot, "vendor") +} + +// LockShouldMatchGolden returns an error when the lock does not match the golden lock. +// goldenLockPath is the path to the golden lock file relative to the testdata directory +// Updates the golden file when -UpdateGolden flag is present. +func (pc *TestProjectContext) LockShouldMatchGolden(goldenLockPath string) error { + got := pc.h.ReadLock() + return pc.ShouldMatchGolden(goldenLockPath, got) +} + +// LockShouldNotExist returns an error when the lock exists. +func (pc *TestProjectContext) LockShouldNotExist() error { + return pc.h.ShouldNotExist(pc.getLockPath()) +} + +// ManifestShouldMatchGolden returns an error when the manifest does not match the golden manifest. +// goldenManifestPath is the path to the golden manifest file, relative to the testdata directory +// Updates the golden file when -UpdateGolden flag is present +func (pc *TestProjectContext) ManifestShouldMatchGolden(goldenManifestPath string) error { + got := pc.h.ReadManifest() + return pc.ShouldMatchGolden(goldenManifestPath, got) +} + +// ManifestShouldNotExist returns an error when the lock exists. +func (pc *TestProjectContext) ManifestShouldNotExist() error { + return pc.h.ShouldNotExist(pc.getManifestPath()) +} + +// ShouldMatchGolden returns an error when a file does not match the golden file. +// goldenFile is the path to the golden file, relative to the testdata directory +// Updates the golden file when -UpdateGolden flag is present +func (pc *TestProjectContext) ShouldMatchGolden(goldenFile string, got string) error { + want := pc.h.GetTestFileString(goldenFile) + if want != got { + if *test.UpdateGolden { + if err := pc.h.WriteTestFile(goldenFile, got); err != nil { + return errors.Wrapf(err, "Unable to write updated golden file %s", goldenFile) + } + } else { + return errors.Errorf("expected %s, got %s", want, got) + } + } + + return nil +} + +// VendorShouldExist returns an error when the vendor directory does not exist. +func (pc *TestProjectContext) VendorShouldExist() error { + return pc.h.ShouldExist(pc.getVendorPath()) +} + +// VendorFileShouldExist returns an error when the specified file does not exist in vendor. +// filePath is the relative path to the file within vendor +func (pc *TestProjectContext) VendorFileShouldExist(filePath string) error { + fullPath := filepath.Join(pc.getVendorPath(), filePath) + return pc.h.ShouldExist(fullPath) +} + +// VendorShouldNotExist returns an error when the vendor directory exists. +func (pc *TestProjectContext) VendorShouldNotExist() error { + return pc.h.ShouldNotExist(pc.getVendorPath()) +} + +// Release cleans up after test objects created by this instance +func (pc *TestProjectContext) Release() { + if pc.SourceManager != nil { + pc.SourceManager.Release() + } +} diff --git a/vendor/github.com/golang/dep/testdata/analyzer/Gopkg.toml b/vendor/github.com/golang/dep/testdata/analyzer/Gopkg.toml new file mode 100644 index 00000000..a86104fe --- /dev/null +++ b/vendor/github.com/golang/dep/testdata/analyzer/Gopkg.toml @@ -0,0 +1,8 @@ + +[[constraint]] + name = "github.com/golang/dep" + version = ">=0.12.0, <1.0.0" + +[[constraint]] + name = "github.com/pkg/errors" + version = ">=0.8.0, <1.0.0" diff --git a/vendor/github.com/golang/dep/testdata/lock/error0.toml b/vendor/github.com/golang/dep/testdata/lock/error0.toml new file mode 100644 index 00000000..80eb22b1 --- /dev/null +++ b/vendor/github.com/golang/dep/testdata/lock/error0.toml @@ -0,0 +1,9 @@ +[solve-meta] + inputs-digest = "2252a285ab27944a4d7adcba8dbd03980f59ba652f12db39fa93b927c345593e" + +[[projects]] + name = "github.com/golang/dep" + branch = "master" + version = "v0.12.0" + revision = "d05d5aca9f895d19e9265839bffeadd74a2d2ecb" + packages = ["."] diff --git a/vendor/github.com/golang/dep/testdata/lock/error1.toml b/vendor/github.com/golang/dep/testdata/lock/error1.toml new file mode 100644 index 00000000..2d83237f --- /dev/null +++ b/vendor/github.com/golang/dep/testdata/lock/error1.toml @@ -0,0 +1,8 @@ +[[projects]] + name = "github.com/golang/dep" + branch = "master" + revision = "d05d5aca9f895d19e9265839bffeadd74a2d2ecb" + packages = ["."] + +[solve-meta] + inputs-digest = "000aaa2a285ab27944a4d7adcba8dbd03980f59ba652f12db39fa93b927c345593e" diff --git a/vendor/github.com/golang/dep/testdata/lock/error2.toml b/vendor/github.com/golang/dep/testdata/lock/error2.toml new file mode 100644 index 00000000..f692f4d9 --- /dev/null +++ b/vendor/github.com/golang/dep/testdata/lock/error2.toml @@ -0,0 +1,6 @@ +[[projects]] + name = "github.com/golang/dep" + packages = ["."] + +[solve-meta] + inputs-digest = "2252a285ab27944a4d7adcba8dbd03980f59ba652f12db39fa93b927c345593e" diff --git a/vendor/github.com/golang/dep/testdata/lock/golden0.toml b/vendor/github.com/golang/dep/testdata/lock/golden0.toml new file mode 100644 index 00000000..2ba4a82d --- /dev/null +++ b/vendor/github.com/golang/dep/testdata/lock/golden0.toml @@ -0,0 +1,13 @@ + +[[projects]] + branch = "master" + name = "github.com/golang/dep" + packages = ["."] + revision = "d05d5aca9f895d19e9265839bffeadd74a2d2ecb" + +[solve-meta] + analyzer-name = "" + analyzer-version = 0 + inputs-digest = "2252a285ab27944a4d7adcba8dbd03980f59ba652f12db39fa93b927c345593e" + solver-name = "" + solver-version = 0 diff --git a/vendor/github.com/golang/dep/testdata/lock/golden1.toml b/vendor/github.com/golang/dep/testdata/lock/golden1.toml new file mode 100644 index 00000000..1a0e183a --- /dev/null +++ b/vendor/github.com/golang/dep/testdata/lock/golden1.toml @@ -0,0 +1,13 @@ + +[[projects]] + name = "github.com/golang/dep" + packages = ["."] + revision = "d05d5aca9f895d19e9265839bffeadd74a2d2ecb" + version = "0.12.2" + +[solve-meta] + analyzer-name = "" + analyzer-version = 0 + inputs-digest = "2252a285ab27944a4d7adcba8dbd03980f59ba652f12db39fa93b927c345593e" + solver-name = "" + solver-version = 0 diff --git a/vendor/github.com/golang/dep/testdata/manifest/error1.toml b/vendor/github.com/golang/dep/testdata/manifest/error1.toml new file mode 100644 index 00000000..fddf02a2 --- /dev/null +++ b/vendor/github.com/golang/dep/testdata/manifest/error1.toml @@ -0,0 +1,15 @@ +ignored = ["github.com/foo/bar"] + +[[constraint]] + name = "github.com/golang/dep" + branch = "master" + revision = "d05d5aca9f895d19e9265839bffeadd74a2d2ecb" + version = "^v0.12.0" + source = "https://github.com/golang/dep" + +[[override]] + name = "github.com/golang/dep" + branch = "master" + revision = "d05d5aca9f895d19e9265839bffeadd74a2d2ecb" + version = "^v0.12.0" + source = "https://github.com/golang/dep" diff --git a/vendor/github.com/golang/dep/testdata/manifest/error2.toml b/vendor/github.com/golang/dep/testdata/manifest/error2.toml new file mode 100644 index 00000000..6b140836 --- /dev/null +++ b/vendor/github.com/golang/dep/testdata/manifest/error2.toml @@ -0,0 +1,9 @@ +ignored = ["github.com/foo/bar"] + +[[constraint]] + name = "github.com/golang/dep" + branch = "master" + +[[constraint]] + name = "github.com/golang/dep" + branch = "master" diff --git a/vendor/github.com/golang/dep/testdata/manifest/error3.toml b/vendor/github.com/golang/dep/testdata/manifest/error3.toml new file mode 100644 index 00000000..4d96624b --- /dev/null +++ b/vendor/github.com/golang/dep/testdata/manifest/error3.toml @@ -0,0 +1,9 @@ +ignored = ["github.com/foo/bar"] + +[[override]] + name = "github.com/golang/dep" + branch = "master" + +[[override]] + name = "github.com/golang/dep" + branch = "master" diff --git a/vendor/github.com/golang/dep/testdata/manifest/golden.toml b/vendor/github.com/golang/dep/testdata/manifest/golden.toml new file mode 100644 index 00000000..62af53fa --- /dev/null +++ b/vendor/github.com/golang/dep/testdata/manifest/golden.toml @@ -0,0 +1,17 @@ +ignored = ["github.com/foo/bar"] + +[[constraint]] + name = "github.com/babble/brook" + revision = "d05d5aca9f895d19e9265839bffeadd74a2d2ecb" + +[[constraint]] + name = "github.com/golang/dep" + version = "0.12.0" + +[[override]] + branch = "master" + name = "github.com/golang/dep" + source = "https://github.com/golang/dep" + +[prune] + non-go = true diff --git a/vendor/github.com/golang/dep/testdata/rootfind/Gopkg.toml b/vendor/github.com/golang/dep/testdata/rootfind/Gopkg.toml new file mode 100644 index 00000000..e69de29b diff --git a/vendor/github.com/golang/dep/testdata/rootfind/subdir/.gitkeep b/vendor/github.com/golang/dep/testdata/rootfind/subdir/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/vendor/github.com/golang/dep/testdata/txn_writer/badinput_fileroot b/vendor/github.com/golang/dep/testdata/txn_writer/badinput_fileroot new file mode 100644 index 00000000..e69de29b diff --git a/vendor/github.com/golang/dep/testdata/txn_writer/expected_diff_output.txt b/vendor/github.com/golang/dep/testdata/txn_writer/expected_diff_output.txt new file mode 100644 index 00000000..bbfe78f8 --- /dev/null +++ b/vendor/github.com/golang/dep/testdata/txn_writer/expected_diff_output.txt @@ -0,0 +1,31 @@ +Memo: 595716d270828e763c811ef79c9c41f85b1d1bfbdfe85280036405c03772206c -> 2252a285ab27944a4d7adcba8dbd03980f59ba652f12db39fa93b927c345593e + +Add: +[[projects]] + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "ff2948a2ac8f538c4ecd55962e919d1e13e74baf" + version = "v1.0.0" + +[[projects]] + name = "github.com/stuff/realthing" + packages = ["."] + revision = "1f02e52d6bac308da54ab84a234c58a98ca82347" + version = "2.0.0" + +Remove: +[[projects]] + name = "github.com/stuff/placeholder" + packages = ["."] + revision = "6694017eeb4e20fd277b049bf29dba4895c97234" + version = "2.0.0" + +Modify: +[[projects]] + branch = "- master" + name = "github.com/foo/bar" + packages = ["- placeholder","+ thing"] + revision = "f24338400f072ef18125ae0fbe6b06fe6d1783e7 -> 2a3a211e171803acb82d1d5d42ceb53228f51751" + source = "+ http://github.example.com/foo/bar" + version = "+ 1.2.0" + diff --git a/vendor/github.com/golang/dep/testdata/txn_writer/expected_lock.toml b/vendor/github.com/golang/dep/testdata/txn_writer/expected_lock.toml new file mode 100644 index 00000000..8c9310fd --- /dev/null +++ b/vendor/github.com/golang/dep/testdata/txn_writer/expected_lock.toml @@ -0,0 +1,15 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/sdboyer/dep-test" + packages = ["."] + revision = "2a3a211e171803acb82d1d5d42ceb53228f51751" + version = "1.0.0" + +[solve-meta] + analyzer-name = "" + analyzer-version = 0 + inputs-digest = "595716d270828e763c811ef79c9c41f85b1d1bfbdfe85280036405c03772206c" + solver-name = "" + solver-version = 0 diff --git a/vendor/github.com/golang/dep/testdata/txn_writer/expected_manifest.toml b/vendor/github.com/golang/dep/testdata/txn_writer/expected_manifest.toml new file mode 100644 index 00000000..bf8ef54e --- /dev/null +++ b/vendor/github.com/golang/dep/testdata/txn_writer/expected_manifest.toml @@ -0,0 +1,30 @@ +# Gopkg.toml example +# +# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md +# for detailed Gopkg.toml documentation. +# +# required = ["github.com/user/thing/cmd/thing"] +# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] +# +# [[constraint]] +# name = "github.com/user/project" +# version = "1.0.0" +# +# [[constraint]] +# name = "github.com/user/project2" +# branch = "dev" +# source = "github.com/myfork/project2" +# +# [[override]] +# name = "github.com/x/y" +# version = "2.4.0" +# +# [prune] +# non-go = false +# go-tests = true +# unused-packages = true + + +[[constraint]] + name = "github.com/sdboyer/dep-test" + version = "1.0.0" diff --git a/vendor/github.com/golang/dep/testdata/txn_writer/original_lock.toml b/vendor/github.com/golang/dep/testdata/txn_writer/original_lock.toml new file mode 100644 index 00000000..26510648 --- /dev/null +++ b/vendor/github.com/golang/dep/testdata/txn_writer/original_lock.toml @@ -0,0 +1,14 @@ +[solve-meta] + inputs-digest = "595716d270828e763c811ef79c9c41f85b1d1bfbdfe85280036405c03772206c" + +[[projects]] + name = "github.com/foo/bar" + branch = "master" + revision = "f24338400f072ef18125ae0fbe6b06fe6d1783e7" + packages = ["placeholder", "util"] + +[[projects]] + name = "github.com/stuff/placeholder" + version = "2.0.0" + revision = "6694017eeb4e20fd277b049bf29dba4895c97234" + packages = ["."] diff --git a/vendor/github.com/golang/dep/testdata/txn_writer/updated_lock.toml b/vendor/github.com/golang/dep/testdata/txn_writer/updated_lock.toml new file mode 100644 index 00000000..81ae83ba --- /dev/null +++ b/vendor/github.com/golang/dep/testdata/txn_writer/updated_lock.toml @@ -0,0 +1,21 @@ +[solve-meta] + inputs-digest = "2252a285ab27944a4d7adcba8dbd03980f59ba652f12db39fa93b927c345593e" + +[[projects]] + name = "github.com/foo/bar" + source = "http://github.example.com/foo/bar" + version = "1.2.0" + revision = "2a3a211e171803acb82d1d5d42ceb53228f51751" + packages = ["thing","util"] + +[[projects]] + name = "github.com/stuff/realthing" + version = "2.0.0" + revision = "1f02e52d6bac308da54ab84a234c58a98ca82347" + packages = ["."] + +[[projects]] + name = "github.com/sdboyer/deptest" + packages = ["."] + revision = "ff2948a2ac8f538c4ecd55962e919d1e13e74baf" + version = "v1.0.0" diff --git a/vendor/github.com/golang/dep/txn_writer.go b/vendor/github.com/golang/dep/txn_writer.go new file mode 100644 index 00000000..0cb19706 --- /dev/null +++ b/vendor/github.com/golang/dep/txn_writer.go @@ -0,0 +1,481 @@ +// Copyright 2016 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 dep + +import ( + "bytes" + "fmt" + "io/ioutil" + "log" + "os" + "path/filepath" + + "github.com/golang/dep/gps" + "github.com/golang/dep/internal/fs" + "github.com/pelletier/go-toml" + "github.com/pkg/errors" +) + +// Example string to be written to the manifest file +// if no dependencies are found in the project +// during `dep init` +var exampleTOML = []byte(`# Gopkg.toml example +# +# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md +# for detailed Gopkg.toml documentation. +# +# required = ["github.com/user/thing/cmd/thing"] +# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] +# +# [[constraint]] +# name = "github.com/user/project" +# version = "1.0.0" +# +# [[constraint]] +# name = "github.com/user/project2" +# branch = "dev" +# source = "github.com/myfork/project2" +# +# [[override]] +# name = "github.com/x/y" +# version = "2.4.0" +# +# [prune] +# non-go = false +# go-tests = true +# unused-packages = true + +`) + +// String added on top of lock file +var lockFileComment = []byte(`# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + +`) + +// SafeWriter transactionalizes writes of manifest, lock, and vendor dir, both +// individually and in any combination, into a pseudo-atomic action with +// transactional rollback. +// +// It is not impervious to errors (writing to disk is hard), but it should +// guard against non-arcane failure conditions. +type SafeWriter struct { + Manifest *Manifest + lock *Lock + lockDiff *gps.LockDiff + writeVendor bool + writeLock bool + pruneOptions gps.CascadingPruneOptions +} + +// NewSafeWriter sets up a SafeWriter to write a set of manifest, lock, and +// vendor tree. +// +// - If manifest is provided, it will be written to the standard manifest file +// name beneath root. +// +// - If newLock is provided, it will be written to the standard lock file +// name beneath root. +// +// - If vendor is VendorAlways, or is VendorOnChanged and the locks are different, +// the vendor directory will be written beneath root based on newLock. +// +// - If oldLock is provided without newLock, error. +// +// - If vendor is VendorAlways without a newLock, error. +func NewSafeWriter(manifest *Manifest, oldLock, newLock *Lock, vendor VendorBehavior, prune gps.CascadingPruneOptions) (*SafeWriter, error) { + sw := &SafeWriter{ + Manifest: manifest, + lock: newLock, + pruneOptions: prune, + } + + if oldLock != nil { + if newLock == nil { + return nil, errors.New("must provide newLock when oldLock is specified") + } + + sw.lockDiff = gps.DiffLocks(oldLock, newLock) + if sw.lockDiff != nil { + sw.writeLock = true + } + } else if newLock != nil { + sw.writeLock = true + } + + switch vendor { + case VendorAlways: + sw.writeVendor = true + case VendorOnChanged: + sw.writeVendor = sw.lockDiff != nil || (newLock != nil && oldLock == nil) + } + + if sw.writeVendor && newLock == nil { + return nil, errors.New("must provide newLock in order to write out vendor") + } + + return sw, nil +} + +// HasLock checks if a Lock is present in the SafeWriter +func (sw *SafeWriter) HasLock() bool { + return sw.lock != nil +} + +// HasManifest checks if a Manifest is present in the SafeWriter +func (sw *SafeWriter) HasManifest() bool { + return sw.Manifest != nil +} + +type rawStringDiff struct { + *gps.StringDiff +} + +// MarshalTOML serializes the diff as a string. +func (diff rawStringDiff) MarshalTOML() ([]byte, error) { + return []byte(diff.String()), nil +} + +type rawLockedProjectDiff struct { + Name gps.ProjectRoot `toml:"name"` + Source *rawStringDiff `toml:"source,omitempty"` + Version *rawStringDiff `toml:"version,omitempty"` + Branch *rawStringDiff `toml:"branch,omitempty"` + Revision *rawStringDiff `toml:"revision,omitempty"` + Packages []rawStringDiff `toml:"packages,omitempty"` +} + +func toRawLockedProjectDiff(diff gps.LockedProjectDiff) rawLockedProjectDiff { + // this is a shallow copy since we aren't modifying the raw diff + raw := rawLockedProjectDiff{Name: diff.Name} + if diff.Source != nil { + raw.Source = &rawStringDiff{diff.Source} + } + if diff.Version != nil { + raw.Version = &rawStringDiff{diff.Version} + } + if diff.Branch != nil { + raw.Branch = &rawStringDiff{diff.Branch} + } + if diff.Revision != nil { + raw.Revision = &rawStringDiff{diff.Revision} + } + raw.Packages = make([]rawStringDiff, len(diff.Packages)) + for i := 0; i < len(diff.Packages); i++ { + raw.Packages[i] = rawStringDiff{&diff.Packages[i]} + } + return raw +} + +type rawLockedProjectDiffs struct { + Projects []rawLockedProjectDiff `toml:"projects"` +} + +func toRawLockedProjectDiffs(diffs []gps.LockedProjectDiff) rawLockedProjectDiffs { + raw := rawLockedProjectDiffs{ + Projects: make([]rawLockedProjectDiff, len(diffs)), + } + + for i := 0; i < len(diffs); i++ { + raw.Projects[i] = toRawLockedProjectDiff(diffs[i]) + } + + return raw +} + +func formatLockDiff(diff gps.LockDiff) (string, error) { + var buf bytes.Buffer + + if diff.HashDiff != nil { + buf.WriteString(fmt.Sprintf("Memo: %s\n\n", diff.HashDiff)) + } + + writeDiffs := func(diffs []gps.LockedProjectDiff) error { + raw := toRawLockedProjectDiffs(diffs) + chunk, err := toml.Marshal(raw) + if err != nil { + return err + } + buf.Write(chunk) + buf.WriteString("\n") + return nil + } + + if len(diff.Add) > 0 { + buf.WriteString("Add:") + err := writeDiffs(diff.Add) + if err != nil { + return "", errors.Wrap(err, "Unable to format LockDiff.Add") + } + } + + if len(diff.Remove) > 0 { + buf.WriteString("Remove:") + err := writeDiffs(diff.Remove) + if err != nil { + return "", errors.Wrap(err, "Unable to format LockDiff.Remove") + } + } + + if len(diff.Modify) > 0 { + buf.WriteString("Modify:") + err := writeDiffs(diff.Modify) + if err != nil { + return "", errors.Wrap(err, "Unable to format LockDiff.Modify") + } + } + + return buf.String(), nil +} + +// VendorBehavior defines when the vendor directory should be written. +type VendorBehavior int + +const ( + // VendorOnChanged indicates that the vendor directory should be written when the lock is new or changed. + VendorOnChanged VendorBehavior = iota + // VendorAlways forces the vendor directory to always be written. + VendorAlways + // VendorNever indicates the vendor directory should never be written. + VendorNever +) + +func (sw SafeWriter) validate(root string, sm gps.SourceManager) error { + if root == "" { + return errors.New("root path must be non-empty") + } + if is, err := fs.IsDir(root); !is { + if err != nil && !os.IsNotExist(err) { + return err + } + return errors.Errorf("root path %q does not exist", root) + } + + if sw.writeVendor && sm == nil { + return errors.New("must provide a SourceManager if writing out a vendor dir") + } + + return nil +} + +// Write saves some combination of config yaml, lock, and a vendor tree. +// root is the absolute path of root dir in which to write. +// sm is only required if vendor is being written. +// +// It first writes to a temp dir, then moves them in place if and only if all the write +// operations succeeded. It also does its best to roll back if any moves fail. +// This mostly guarantees that dep cannot exit with a partial write that would +// leave an undefined state on disk. +func (sw *SafeWriter) Write(root string, sm gps.SourceManager, examples bool, logger *log.Logger) error { + err := sw.validate(root, sm) + if err != nil { + return err + } + + if !sw.HasManifest() && !sw.writeLock && !sw.writeVendor { + // nothing to do + return nil + } + + mpath := filepath.Join(root, ManifestName) + lpath := filepath.Join(root, LockName) + vpath := filepath.Join(root, "vendor") + + td, err := ioutil.TempDir(os.TempDir(), "dep") + if err != nil { + return errors.Wrap(err, "error while creating temp dir for writing manifest/lock/vendor") + } + defer os.RemoveAll(td) + + if sw.HasManifest() { + // Always write the example text to the bottom of the TOML file. + tb, err := sw.Manifest.MarshalTOML() + if err != nil { + return errors.Wrap(err, "failed to marshal manifest to TOML") + } + + var initOutput []byte + + // If examples are enabled, use the example text + if examples { + initOutput = exampleTOML + } + + if err = ioutil.WriteFile(filepath.Join(td, ManifestName), append(initOutput, tb...), 0666); err != nil { + return errors.Wrap(err, "failed to write manifest file to temp dir") + } + } + + if sw.writeLock { + l, err := sw.lock.MarshalTOML() + if err != nil { + return errors.Wrap(err, "failed to marshal lock to TOML") + } + + if err = ioutil.WriteFile(filepath.Join(td, LockName), append(lockFileComment, l...), 0666); err != nil { + return errors.Wrap(err, "failed to write lock file to temp dir") + } + } + + if sw.writeVendor { + err = gps.WriteDepTree(filepath.Join(td, "vendor"), sw.lock, sm, sw.pruneOptions, logger) + if err != nil { + return errors.Wrap(err, "error while writing out vendor tree") + } + } + + // Ensure vendor/.git is preserved if present + if hasDotGit(vpath) { + err = fs.RenameWithFallback(filepath.Join(vpath, ".git"), filepath.Join(td, "vendor/.git")) + if _, ok := err.(*os.LinkError); ok { + return errors.Wrap(err, "failed to preserve vendor/.git") + } + } + + // Move the existing files and dirs to the temp dir while we put the new + // ones in, to provide insurance against errors for as long as possible. + type pathpair struct { + from, to string + } + var restore []pathpair + var failerr error + var vendorbak string + + if sw.HasManifest() { + if _, err := os.Stat(mpath); err == nil { + // Move out the old one. + tmploc := filepath.Join(td, ManifestName+".orig") + failerr = fs.RenameWithFallback(mpath, tmploc) + if failerr != nil { + goto fail + } + restore = append(restore, pathpair{from: tmploc, to: mpath}) + } + + // Move in the new one. + failerr = fs.RenameWithFallback(filepath.Join(td, ManifestName), mpath) + if failerr != nil { + goto fail + } + } + + if sw.writeLock { + if _, err := os.Stat(lpath); err == nil { + // Move out the old one. + tmploc := filepath.Join(td, LockName+".orig") + + failerr = fs.RenameWithFallback(lpath, tmploc) + if failerr != nil { + goto fail + } + restore = append(restore, pathpair{from: tmploc, to: lpath}) + } + + // Move in the new one. + failerr = fs.RenameWithFallback(filepath.Join(td, LockName), lpath) + if failerr != nil { + goto fail + } + } + + if sw.writeVendor { + if _, err := os.Stat(vpath); err == nil { + // Move out the old vendor dir. just do it into an adjacent dir, to + // try to mitigate the possibility of a pointless cross-filesystem + // move with a temp directory. + vendorbak = vpath + ".orig" + if _, err := os.Stat(vendorbak); err == nil { + // If the adjacent dir already exists, bite the bullet and move + // to a proper tempdir. + vendorbak = filepath.Join(td, ".vendor.orig") + } + + failerr = fs.RenameWithFallback(vpath, vendorbak) + if failerr != nil { + goto fail + } + restore = append(restore, pathpair{from: vendorbak, to: vpath}) + } + + // Move in the new one. + failerr = fs.RenameWithFallback(filepath.Join(td, "vendor"), vpath) + if failerr != nil { + goto fail + } + } + + // Renames all went smoothly. The deferred os.RemoveAll will get the temp + // dir, but if we wrote vendor, we have to clean that up directly + if sw.writeVendor { + // Nothing we can really do about an error at this point, so ignore it + os.RemoveAll(vendorbak) + } + + return nil + +fail: + // If we failed at any point, move all the things back into place, then bail. + for _, pair := range restore { + // Nothing we can do on err here, as we're already in recovery mode. + fs.RenameWithFallback(pair.from, pair.to) + } + return failerr +} + +// PrintPreparedActions logs the actions a call to Write would perform. +func (sw *SafeWriter) PrintPreparedActions(output *log.Logger, verbose bool) error { + if sw.HasManifest() { + if verbose { + m, err := sw.Manifest.MarshalTOML() + if err != nil { + return errors.Wrap(err, "ensure DryRun cannot serialize manifest") + } + output.Printf("Would have written the following %s:\n%s\n", ManifestName, string(m)) + } else { + output.Printf("Would have written %s.\n", ManifestName) + } + } + + if sw.writeLock { + if sw.lockDiff == nil { + if verbose { + l, err := sw.lock.MarshalTOML() + if err != nil { + return errors.Wrap(err, "ensure DryRun cannot serialize lock") + } + output.Printf("Would have written the following %s:\n%s\n", LockName, string(l)) + } else { + output.Printf("Would have written %s.\n", LockName) + } + } else { + output.Printf("Would have written the following changes to %s:\n", LockName) + diff, err := formatLockDiff(*sw.lockDiff) + if err != nil { + return errors.Wrap(err, "ensure DryRun cannot serialize the lock diff") + } + output.Println(diff) + } + } + + if sw.writeVendor { + if verbose { + output.Printf("Would have written the following %d projects to the vendor directory:\n", len(sw.lock.Projects())) + lps := sw.lock.Projects() + for i, p := range lps { + output.Printf("(%d/%d) %s@%s\n", i+1, len(lps), p.Ident(), p.Version()) + } + } else { + output.Printf("Would have written %d projects to the vendor directory.\n", len(sw.lock.Projects())) + } + } + + return nil +} + +// hasDotGit checks if a given path has .git file or directory in it. +func hasDotGit(path string) bool { + gitfilepath := filepath.Join(path, ".git") + _, err := os.Stat(gitfilepath) + return err == nil +} diff --git a/vendor/github.com/golang/dep/txn_writer_test.go b/vendor/github.com/golang/dep/txn_writer_test.go new file mode 100644 index 00000000..4b55aa89 --- /dev/null +++ b/vendor/github.com/golang/dep/txn_writer_test.go @@ -0,0 +1,601 @@ +// Copyright 2017 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 dep + +import ( + "io/ioutil" + "os" + "path/filepath" + "strings" + "testing" + + "github.com/golang/dep/gps" + "github.com/golang/dep/internal/test" + "github.com/pkg/errors" +) + +const safeWriterProject = "safewritertest" +const safeWriterGoldenManifest = "txn_writer/expected_manifest.toml" +const safeWriterGoldenLock = "txn_writer/expected_lock.toml" + +func defaultCascadingPruneOptions() gps.CascadingPruneOptions { + return gps.CascadingPruneOptions{ + DefaultOptions: gps.PruneNestedVendorDirs, + PerProjectOptions: map[gps.ProjectRoot]gps.PruneOptionSet{}, + } +} + +func TestSafeWriter_BadInput_MissingRoot(t *testing.T) { + h := test.NewHelper(t) + defer h.Cleanup() + pc := NewTestProjectContext(h, safeWriterProject) + defer pc.Release() + + sw, _ := NewSafeWriter(nil, nil, nil, VendorOnChanged, defaultCascadingPruneOptions()) + err := sw.Write("", pc.SourceManager, true, discardLogger()) + + if err == nil { + t.Fatal("should have errored without a root path, but did not") + } else if !strings.Contains(err.Error(), "root path") { + t.Fatalf("expected root path error, got %s", err.Error()) + } +} + +func TestSafeWriter_BadInput_MissingSourceManager(t *testing.T) { + h := test.NewHelper(t) + defer h.Cleanup() + pc := NewTestProjectContext(h, safeWriterProject) + defer pc.Release() + pc.CopyFile(LockName, safeWriterGoldenLock) + pc.Load() + + sw, _ := NewSafeWriter(nil, nil, pc.Project.Lock, VendorAlways, defaultCascadingPruneOptions()) + err := sw.Write(pc.Project.AbsRoot, nil, true, discardLogger()) + + if err == nil { + t.Fatal("should have errored without a source manager when forceVendor is true, but did not") + } else if !strings.Contains(err.Error(), "SourceManager") { + t.Fatalf("expected SourceManager error, got %s", err.Error()) + } +} + +func TestSafeWriter_BadInput_ForceVendorMissingLock(t *testing.T) { + h := test.NewHelper(t) + defer h.Cleanup() + pc := NewTestProjectContext(h, safeWriterProject) + defer pc.Release() + + _, err := NewSafeWriter(nil, nil, nil, VendorAlways, defaultCascadingPruneOptions()) + if err == nil { + t.Fatal("should have errored without a lock when forceVendor is true, but did not") + } else if !strings.Contains(err.Error(), "newLock") { + t.Fatalf("expected newLock error, got %s", err.Error()) + } +} + +func TestSafeWriter_BadInput_OldLockOnly(t *testing.T) { + h := test.NewHelper(t) + defer h.Cleanup() + pc := NewTestProjectContext(h, safeWriterProject) + defer pc.Release() + pc.CopyFile(LockName, safeWriterGoldenLock) + pc.Load() + + _, err := NewSafeWriter(nil, pc.Project.Lock, nil, VendorAlways, defaultCascadingPruneOptions()) + if err == nil { + t.Fatal("should have errored with only an old lock, but did not") + } else if !strings.Contains(err.Error(), "oldLock") { + t.Fatalf("expected oldLock error, got %s", err.Error()) + } +} + +func TestSafeWriter_BadInput_NonexistentRoot(t *testing.T) { + h := test.NewHelper(t) + defer h.Cleanup() + pc := NewTestProjectContext(h, safeWriterProject) + defer pc.Release() + + sw, _ := NewSafeWriter(nil, nil, nil, VendorOnChanged, defaultCascadingPruneOptions()) + + missingroot := filepath.Join(pc.Project.AbsRoot, "nonexistent") + err := sw.Write(missingroot, pc.SourceManager, true, discardLogger()) + + if err == nil { + t.Fatal("should have errored with nonexistent dir for root path, but did not") + } else if !strings.Contains(err.Error(), "does not exist") { + t.Fatalf("expected does not exist error, got %s", err.Error()) + } +} + +func TestSafeWriter_BadInput_RootIsFile(t *testing.T) { + h := test.NewHelper(t) + defer h.Cleanup() + pc := NewTestProjectContext(h, safeWriterProject) + defer pc.Release() + + sw, _ := NewSafeWriter(nil, nil, nil, VendorOnChanged, defaultCascadingPruneOptions()) + + fileroot := pc.CopyFile("fileroot", "txn_writer/badinput_fileroot") + err := sw.Write(fileroot, pc.SourceManager, true, discardLogger()) + + if err == nil { + t.Fatal("should have errored when root path is a file, but did not") + } else if !strings.Contains(err.Error(), "does not exist") { + t.Fatalf("expected does not exist error, got %s", err.Error()) + } +} + +func TestSafeWriter_Manifest(t *testing.T) { + test.NeedsExternalNetwork(t) + test.NeedsGit(t) + + h := test.NewHelper(t) + defer h.Cleanup() + + pc := NewTestProjectContext(h, safeWriterProject) + defer pc.Release() + pc.CopyFile(ManifestName, safeWriterGoldenManifest) + pc.Load() + + sw, _ := NewSafeWriter(pc.Project.Manifest, nil, nil, VendorOnChanged, defaultCascadingPruneOptions()) + + // Verify prepared actions + if !sw.HasManifest() { + t.Fatal("Expected the payload to contain the manifest") + } + if sw.HasLock() { + t.Fatal("Did not expect the payload to contain the lock") + } + if sw.writeVendor { + t.Fatal("Did not expect the payload to contain the vendor directory") + } + + // Write changes + err := sw.Write(pc.Project.AbsRoot, pc.SourceManager, true, discardLogger()) + h.Must(errors.Wrap(err, "SafeWriter.Write failed")) + + // Verify file system changes + if err := pc.ManifestShouldMatchGolden(safeWriterGoldenManifest); err != nil { + t.Fatal(err) + } + if err := pc.LockShouldNotExist(); err != nil { + t.Fatal(err) + } + if err := pc.VendorShouldNotExist(); err != nil { + t.Fatal(err) + } +} + +func TestSafeWriter_ManifestAndUnmodifiedLock(t *testing.T) { + test.NeedsExternalNetwork(t) + test.NeedsGit(t) + + h := test.NewHelper(t) + defer h.Cleanup() + + pc := NewTestProjectContext(h, safeWriterProject) + defer pc.Release() + pc.CopyFile(ManifestName, safeWriterGoldenManifest) + pc.CopyFile(LockName, safeWriterGoldenLock) + pc.Load() + + sw, _ := NewSafeWriter(pc.Project.Manifest, pc.Project.Lock, pc.Project.Lock, VendorOnChanged, defaultCascadingPruneOptions()) + + // Verify prepared actions + if !sw.HasManifest() { + t.Fatal("Expected the payload to contain the manifest") + } + if !sw.HasLock() { + t.Fatal("Expected the payload to contain the lock.") + } + if sw.writeLock { + t.Fatal("Did not expect that the writer should plan to write the lock") + } + if sw.writeVendor { + t.Fatal("Did not expect the payload to contain the vendor directory") + } + + // Write changes + err := sw.Write(pc.Project.AbsRoot, pc.SourceManager, true, discardLogger()) + h.Must(errors.Wrap(err, "SafeWriter.Write failed")) + + // Verify file system changes + if err := pc.ManifestShouldMatchGolden(safeWriterGoldenManifest); err != nil { + t.Fatal(err) + } + if err := pc.LockShouldMatchGolden(safeWriterGoldenLock); err != nil { + t.Fatal(err) + } + if err := pc.VendorShouldNotExist(); err != nil { + t.Fatal(err) + } +} + +func TestSafeWriter_ManifestAndUnmodifiedLockWithForceVendor(t *testing.T) { + test.NeedsExternalNetwork(t) + test.NeedsGit(t) + + h := test.NewHelper(t) + defer h.Cleanup() + + pc := NewTestProjectContext(h, safeWriterProject) + defer pc.Release() + pc.CopyFile(ManifestName, safeWriterGoldenManifest) + pc.CopyFile(LockName, safeWriterGoldenLock) + pc.Load() + + sw, _ := NewSafeWriter(pc.Project.Manifest, pc.Project.Lock, pc.Project.Lock, VendorAlways, defaultCascadingPruneOptions()) + + // Verify prepared actions + if !sw.HasManifest() { + t.Fatal("Expected the payload to contain the manifest") + } + if !sw.HasLock() { + t.Fatal("Expected the payload to contain the lock") + } + if sw.writeLock { + t.Fatal("Did not expect that the writer should plan to write the lock") + } + if !sw.writeVendor { + t.Fatal("Expected the payload to contain the vendor directory") + } + + // Write changes + err := sw.Write(pc.Project.AbsRoot, pc.SourceManager, true, discardLogger()) + h.Must(errors.Wrap(err, "SafeWriter.Write failed")) + + // Verify file system changes + if err := pc.ManifestShouldMatchGolden(safeWriterGoldenManifest); err != nil { + t.Fatal(err) + } + if err := pc.LockShouldMatchGolden(safeWriterGoldenLock); err != nil { + t.Fatal(err) + } + if err := pc.VendorShouldExist(); err != nil { + t.Fatal(err) + } + if err := pc.VendorFileShouldExist("github.com/sdboyer/dep-test"); err != nil { + t.Fatal(err) + } +} + +func TestSafeWriter_ModifiedLock(t *testing.T) { + test.NeedsExternalNetwork(t) + test.NeedsGit(t) + + h := test.NewHelper(t) + defer h.Cleanup() + + pc := NewTestProjectContext(h, safeWriterProject) + defer pc.Release() + pc.CopyFile(LockName, safeWriterGoldenLock) + pc.Load() + + originalLock := new(Lock) + *originalLock = *pc.Project.Lock + originalLock.SolveMeta.InputsDigest = []byte{} // zero out the input hash to ensure non-equivalency + sw, _ := NewSafeWriter(nil, originalLock, pc.Project.Lock, VendorOnChanged, defaultCascadingPruneOptions()) + + // Verify prepared actions + if sw.HasManifest() { + t.Fatal("Did not expect the manifest to be written") + } + if !sw.HasLock() { + t.Fatal("Expected the payload to contain the lock") + } + if !sw.writeLock { + t.Fatal("Expected that the writer should plan to write the lock") + } + if !sw.writeVendor { + t.Fatal("Expected that the writer should plan to write the vendor directory") + } + + // Write changes + err := sw.Write(pc.Project.AbsRoot, pc.SourceManager, true, discardLogger()) + h.Must(errors.Wrap(err, "SafeWriter.Write failed")) + + // Verify file system changes + if err := pc.ManifestShouldNotExist(); err != nil { + t.Fatal(err) + } + if err := pc.LockShouldMatchGolden(safeWriterGoldenLock); err != nil { + t.Fatal(err) + } + if err := pc.VendorShouldExist(); err != nil { + t.Fatal(err) + } + if err := pc.VendorFileShouldExist("github.com/sdboyer/dep-test"); err != nil { + t.Fatal(err) + } +} + +func TestSafeWriter_ModifiedLockSkipVendor(t *testing.T) { + test.NeedsExternalNetwork(t) + test.NeedsGit(t) + + h := test.NewHelper(t) + defer h.Cleanup() + + pc := NewTestProjectContext(h, safeWriterProject) + defer pc.Release() + pc.CopyFile(LockName, safeWriterGoldenLock) + pc.Load() + + originalLock := new(Lock) + *originalLock = *pc.Project.Lock + originalLock.SolveMeta.InputsDigest = []byte{} // zero out the input hash to ensure non-equivalency + sw, _ := NewSafeWriter(nil, originalLock, pc.Project.Lock, VendorNever, defaultCascadingPruneOptions()) + + // Verify prepared actions + if sw.HasManifest() { + t.Fatal("Did not expect the payload to contain the manifest") + } + if !sw.HasLock() { + t.Fatal("Expected the payload to contain the lock") + } + if !sw.writeLock { + t.Fatal("Expected that the writer should plan to write the lock") + } + if sw.writeVendor { + t.Fatal("Did not expect the payload to contain the vendor directory") + } + + // Write changes + err := sw.Write(pc.Project.AbsRoot, pc.SourceManager, true, discardLogger()) + h.Must(errors.Wrap(err, "SafeWriter.Write failed")) + + // Verify file system changes + if err := pc.ManifestShouldNotExist(); err != nil { + t.Fatal(err) + } + if err := pc.LockShouldMatchGolden(safeWriterGoldenLock); err != nil { + t.Fatal(err) + } + if err := pc.VendorShouldNotExist(); err != nil { + t.Fatal(err) + } +} + +func TestSafeWriter_ForceVendorWhenVendorAlreadyExists(t *testing.T) { + test.NeedsExternalNetwork(t) + test.NeedsGit(t) + + h := test.NewHelper(t) + defer h.Cleanup() + + pc := NewTestProjectContext(h, safeWriterProject) + defer pc.Release() + pc.CopyFile(LockName, safeWriterGoldenLock) + pc.Load() + + sw, _ := NewSafeWriter(nil, pc.Project.Lock, pc.Project.Lock, VendorAlways, defaultCascadingPruneOptions()) + err := sw.Write(pc.Project.AbsRoot, pc.SourceManager, true, discardLogger()) + h.Must(errors.Wrap(err, "SafeWriter.Write failed")) + + // Verify prepared actions + sw, _ = NewSafeWriter(nil, nil, pc.Project.Lock, VendorAlways, defaultCascadingPruneOptions()) + if sw.HasManifest() { + t.Fatal("Did not expect the payload to contain the manifest") + } + if !sw.HasLock() { + t.Fatal("Expected the payload to contain the lock") + } + if !sw.writeLock { + t.Fatal("Expected that the writer should plan to write the lock") + } + if !sw.writeVendor { + t.Fatal("Expected the payload to contain the vendor directory ") + } + + err = sw.Write(pc.Project.AbsRoot, pc.SourceManager, true, discardLogger()) + h.Must(errors.Wrap(err, "SafeWriter.Write failed")) + + // Verify file system changes + if err := pc.ManifestShouldNotExist(); err != nil { + t.Fatal(err) + } + if err := pc.LockShouldMatchGolden(safeWriterGoldenLock); err != nil { + t.Fatal(err) + } + if err := pc.VendorShouldExist(); err != nil { + t.Fatal(err) + } + if err := pc.VendorFileShouldExist("github.com/sdboyer/dep-test"); err != nil { + t.Fatal(err) + } +} + +func TestSafeWriter_NewLock(t *testing.T) { + test.NeedsExternalNetwork(t) + test.NeedsGit(t) + + h := test.NewHelper(t) + defer h.Cleanup() + + pc := NewTestProjectContext(h, safeWriterProject) + defer pc.Release() + pc.Load() + + lf := h.GetTestFile(safeWriterGoldenLock) + defer lf.Close() + newLock, err := readLock(lf) + h.Must(err) + sw, _ := NewSafeWriter(nil, nil, newLock, VendorOnChanged, defaultCascadingPruneOptions()) + + // Verify prepared actions + if sw.HasManifest() { + t.Fatal("Did not expect the payload to contain the manifest") + } + if !sw.HasLock() { + t.Fatal("Expected the payload to contain the lock") + } + if !sw.writeLock { + t.Fatal("Expected that the writer should plan to write the lock") + } + if !sw.writeVendor { + t.Fatal("Expected the payload to contain the vendor directory") + } + + // Write changes + err = sw.Write(pc.Project.AbsRoot, pc.SourceManager, true, discardLogger()) + h.Must(errors.Wrap(err, "SafeWriter.Write failed")) + + // Verify file system changes + if err := pc.ManifestShouldNotExist(); err != nil { + t.Fatal(err) + } + if err := pc.LockShouldMatchGolden(safeWriterGoldenLock); err != nil { + t.Fatal(err) + } + if err := pc.VendorShouldExist(); err != nil { + t.Fatal(err) + } +} + +func TestSafeWriter_NewLockSkipVendor(t *testing.T) { + test.NeedsExternalNetwork(t) + test.NeedsGit(t) + + h := test.NewHelper(t) + defer h.Cleanup() + + pc := NewTestProjectContext(h, safeWriterProject) + defer pc.Release() + pc.Load() + + lf := h.GetTestFile(safeWriterGoldenLock) + defer lf.Close() + newLock, err := readLock(lf) + h.Must(err) + sw, _ := NewSafeWriter(nil, nil, newLock, VendorNever, defaultCascadingPruneOptions()) + + // Verify prepared actions + if sw.HasManifest() { + t.Fatal("Did not expect the payload to contain the manifest") + } + if !sw.HasLock() { + t.Fatal("Expected the payload to contain the lock") + } + if !sw.writeLock { + t.Fatal("Expected that the writer should plan to write the lock") + } + if sw.writeVendor { + t.Fatal("Did not expect the payload to contain the vendor directory") + } + + // Write changes + err = sw.Write(pc.Project.AbsRoot, pc.SourceManager, true, discardLogger()) + h.Must(errors.Wrap(err, "SafeWriter.Write failed")) + + // Verify file system changes + if err := pc.ManifestShouldNotExist(); err != nil { + t.Fatal(err) + } + if err := pc.LockShouldMatchGolden(safeWriterGoldenLock); err != nil { + t.Fatal(err) + } + if err := pc.VendorShouldNotExist(); err != nil { + t.Fatal(err) + } +} + +func TestSafeWriter_DiffLocks(t *testing.T) { + test.NeedsExternalNetwork(t) + test.NeedsGit(t) + + h := test.NewHelper(t) + defer h.Cleanup() + + pc := NewTestProjectContext(h, safeWriterProject) + defer pc.Release() + pc.CopyFile(LockName, "txn_writer/original_lock.toml") + pc.Load() + + ulf := h.GetTestFile("txn_writer/updated_lock.toml") + defer ulf.Close() + updatedLock, err := readLock(ulf) + h.Must(err) + + sw, _ := NewSafeWriter(nil, pc.Project.Lock, updatedLock, VendorOnChanged, defaultCascadingPruneOptions()) + + // Verify lock diff + diff := sw.lockDiff + if diff == nil { + t.Fatal("Expected the payload to contain a diff of the lock files") + } + + output, err := formatLockDiff(*diff) + h.Must(err) + goldenOutput := "txn_writer/expected_diff_output.txt" + if err = pc.ShouldMatchGolden(goldenOutput, output); err != nil { + t.Fatal(err) + } +} + +func TestHasDotGit(t *testing.T) { + // Create a tempdir with .git file + td, err := ioutil.TempDir(os.TempDir(), "dotGitFile") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(td) + + os.OpenFile(td+string(filepath.Separator)+".git", os.O_CREATE, 0777) + if !hasDotGit(td) { + t.Fatal("Expected hasDotGit to find .git") + } +} + +func TestSafeWriter_VendorDotGitPreservedWithForceVendor(t *testing.T) { + h := test.NewHelper(t) + defer h.Cleanup() + + pc := NewTestProjectContext(h, safeWriterProject) + defer pc.Release() + + gitDirPath := filepath.Join(pc.Project.AbsRoot, "vendor", ".git") + os.MkdirAll(gitDirPath, 0777) + dummyFile := filepath.Join("vendor", ".git", "badinput_fileroot") + pc.CopyFile(dummyFile, "txn_writer/badinput_fileroot") + pc.CopyFile(ManifestName, safeWriterGoldenManifest) + pc.CopyFile(LockName, safeWriterGoldenLock) + pc.Load() + + sw, _ := NewSafeWriter(pc.Project.Manifest, pc.Project.Lock, pc.Project.Lock, VendorAlways, defaultCascadingPruneOptions()) + + // Verify prepared actions + if !sw.HasManifest() { + t.Fatal("Expected the payload to contain the manifest") + } + if !sw.HasLock() { + t.Fatal("Expected the payload to contain the lock") + } + if sw.writeLock { + t.Fatal("Did not expect that the writer should plan to write the lock") + } + if !sw.writeVendor { + t.Fatal("Expected the payload to contain the vendor directory") + } + + err := sw.Write(pc.Project.AbsRoot, pc.SourceManager, true, discardLogger()) + h.Must(errors.Wrap(err, "SafeWriter.Write failed")) + + // Verify file system changes + if err := pc.ManifestShouldMatchGolden(safeWriterGoldenManifest); err != nil { + t.Fatal(err) + } + if err := pc.LockShouldMatchGolden(safeWriterGoldenLock); err != nil { + t.Fatal(err) + } + if err := pc.VendorShouldExist(); err != nil { + t.Fatal(err) + } + if err := pc.VendorFileShouldExist("github.com/sdboyer/dep-test"); err != nil { + t.Fatal(err) + } + if err := pc.VendorFileShouldExist(".git/badinput_fileroot"); err != nil { + t.Fatal(err) + } +} diff --git a/vendor/github.com/golang/dep/website/.gitignore b/vendor/github.com/golang/dep/website/.gitignore new file mode 100644 index 00000000..aeedda9b --- /dev/null +++ b/vendor/github.com/golang/dep/website/.gitignore @@ -0,0 +1,11 @@ +node_modules +.DS_Store +lib/core/metadata.js +lib/core/MetadataBlog.js +website/translated_docs +website/build/ +website/yarn.lock +website/node_modules + +website/i18n/* +!website/i18n/en.json diff --git a/vendor/github.com/golang/dep/website/blog/2018-01-23-announce-v0.4.0.md b/vendor/github.com/golang/dep/website/blog/2018-01-23-announce-v0.4.0.md new file mode 100644 index 00000000..bf431031 --- /dev/null +++ b/vendor/github.com/golang/dep/website/blog/2018-01-23-announce-v0.4.0.md @@ -0,0 +1,41 @@ +--- +title: Announcing dep v0.4.0 (with docs!) +author: sam boyer +authorURL: http://twitter.com/sdboyer +--- + +v0.4.0 of dep [has been released](https://github.com/golang/dep/releases/tag/v0.4.0) - and along with it, this site for documentation and announcements about dep! And, being that it's been nearly six months since [the last dep status update](https://sdboyer.io/dep-status/2017-08-17/) (which are now officially discontinued, in favor of this blog), and the roadmap hasn't been substantially updated in even longer, we'll use this release as an excuse to bring a bunch of things up to speed. + +_Note: there was [a significant omission](https://github.com/golang/dep/issues/1561) in v0.4.0's new pruning behavior, so we immediately shipped v0.4.1 with a fix._ + +### A new dep release! + +After three months of work, the next version of dep is stable and ready for public use. The big headline changes are: + +* `dep prune` no longer exists as a separate command. It has been absorbed into `dep ensure`, and its behavior can now be more granularly controlled by [directives in `Gopkg.toml`](https://golang.github.io/dep/docs/Gopkg.toml.html#prune). Calls to `dep prune` will not fail now, but will in future versions, so update your scripts! +* Support for govendor and glock have been added; `dep init` can now read their metadata files and attempt to automatically convert projects managed by those tools. + +Additional information is available in [the release notes](https://github.com/golang/dep/releases/tag/v0.4.0). The other major addition is this documentation site! + +### Docs docs docs + +Dep has had a documentation problem for a while. Having a single-command interface helped us get by with having only an FAQ, but as time wore on, it became increasingly clear that we needed a comprehensive set of documentation if people were to really feel comfortable with the tool. + +This site, which is automatically generated from the [docs directory](https://github.com/golang/dep/tree/master/docs) within the dep repository by [docusaurus](http://docusaurus.io/), is now that comprehensive source of docs. More so than any individual bit of information, it provides some broader benefits: + +* New user guides - reference documentation is not what folks need when starting with a new tool. Step-by-step instructions are. Now [we have that](https://golang.github.io/dep/docs/introduction.html), and it caters to users who are not only new to dep, but also to Go in general. +* Thematic organization of content - up until now, we were somewhat haphazardly flinging information into the FAQ. The body of documentation here is organized from the ground up, which will hopefully make it both more useful and easier to maintain. +* Versioning - docusaurus is capable of snapshotting doc versions on each release, and users will be able to select the version of the docs they want to view (though we've not enabled this just quite yet). Ideally, everyone should always be able to use the latest version, but this at least means you're not penalized if that's not feasible for you/your organization. +* A blog - you're reading it! This is great, as it provides us a canonical place to circulate information about what's happening with the project. + +At the same time, the docs aren't quite comprehensive _yet_. There's more reference material and guides to be written. For example, we're still missing a guide for project maintainers on how to make releases that align well with dep's happy path. + +Also, now that we have this whole docs apparatus, it would be particularly awesome if someone were to step up to help as a [docs maintainer](https://github.com/golang/dep/issues/629#issuecomment-359922251)! (Also also, the CSS on this site is terrible, [please halp](https://github.com/golang/dep/issues/1558)!) + +### The future + +Right now, there's two aspects to the future of dep. One is the roadmap of changes and features that make sense for dep as it exists today, in this standalone context. The other is the roadmap for moving dep into the toolchain. + +For the former, we have a fair bit of work underway that, now that this release is out the door, we can move on quickly. That includes major performance improvements, solver improvements to pick a sane version more of the time with less manual intervention, allowing the `source` field to work the way [most people expect it to](https://github.com/golang/dep/issues/860), and others. The goal is also to move dep towards a more regular release schedule. + +With respect to dep's movement towards the toolchain, discussions have already been ongoing between dep folks and the Go team for months. Movement into the toolchain is not a simple process. Some rules that dep, as a standalone tool, had to accept as law, become negotiable (for example, the semantics of vendor directories). There's also the question of how to best fit dep's commands themselves into the `go` tool. These present both interesting design opportunities and considerable risk. More information and opportunities for comment will be coming as we move into the Go 1.10 cycle. As has always been the plan, though, dep will continue to exist as a standalone tool until the toolchain has evolved sufficiently to supplant it. \ No newline at end of file diff --git a/vendor/github.com/golang/dep/website/core/Footer.js b/vendor/github.com/golang/dep/website/core/Footer.js new file mode 100644 index 00000000..98956ad5 --- /dev/null +++ b/vendor/github.com/golang/dep/website/core/Footer.js @@ -0,0 +1,29 @@ +const React = require('react'); + +const siteConfig = require(process.cwd() + '/siteConfig.js'); + +class Footer extends React.Component { + render() { + const currentYear = new Date().getFullYear(); + return ( +

    5sG8 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