diff --git a/NOTICE.txt b/NOTICE.txt index 36633355b85d..1e3810305b6f 100644 --- a/NOTICE.txt +++ b/NOTICE.txt @@ -1298,6 +1298,21 @@ Copyright 2017-2018 Elasticsearch B.V. This product includes software developed at Elasticsearch, B.V. (https://www.elastic.co/). +-------------------------------------------------------------------- +Dependency: github.com/elastic/go-licenser +Version: v0.2.1 +License type (autodetected): Apache-2.0 +./vendor/github.com/elastic/go-licenser/LICENSE: +-------------------------------------------------------------------- +Apache License 2.0 + +-------NOTICE----- +Elastic go-licenser +Copyright 2018 Elasticsearch B.V. + +This product includes software developed at +Elasticsearch, B.V. (https://www.elastic.co/). + -------------------------------------------------------------------- Dependency: github.com/elastic/go-lookslike Version: v0.3.0 @@ -3946,9 +3961,22 @@ 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. +-------------------------------------------------------------------- +Dependency: github.com/pierrre/gotestcover +Revision: 7b94f124d338 +License type (autodetected): MIT +./vendor/github.com/pierrre/gotestcover/LICENSE: +-------------------------------------------------------------------- +Copyright (C) 2015 Pierre Durand + +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. -------------------------------------------------------------------- Dependency: github.com/pkg/errors -Version: v0.8.1 +Version: v0.9.1 License type (autodetected): BSD-2-Clause ./vendor/github.com/pkg/errors/LICENSE: -------------------------------------------------------------------- @@ -4517,6 +4545,40 @@ 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. +-------------------------------------------------------------------- +Dependency: github.com/tsg/go-daemon +Revision: 4b60efc26d5f +License type (autodetected): BSD-2-Clause +./vendor/github.com/tsg/go-daemon/LICENSE: +-------------------------------------------------------------------- +Copyright (c) 2013-2014 Alexandre Fiori. 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. + * The names of authors or contributors may NOT 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. + -------------------------------------------------------------------- Dependency: github.com/tsg/gopacket Revision: dd3d0e41124a diff --git a/dev-tools/mage/fmt.go b/dev-tools/mage/fmt.go index 8851f67676ad..18a16d57be99 100644 --- a/dev-tools/mage/fmt.go +++ b/dev-tools/mage/fmt.go @@ -32,7 +32,7 @@ import ( var ( // GoImportsImportPath controls the import path used to install goimports. - GoImportsImportPath = "github.com/elastic/beats/vendor/golang.org/x/tools/cmd/goimports" + GoImportsImportPath = "golang.org/x/tools/cmd/goimports" // GoImportsLocalPrefix is a string prefix matching imports that should be // grouped after third-party packages. @@ -64,7 +64,10 @@ func GoImports() error { } fmt.Println(">> fmt - goimports: Formatting Go code") - if err := sh.Run("go", "get", GoImportsImportPath); err != nil { + if err := gotool.Install( + gotool.Install.Vendored(), + gotool.Install.Package(filepath.Join(GoImportsImportPath)), + ); err != nil { return err } diff --git a/dev-tools/mage/gotool/go.go b/dev-tools/mage/gotool/go.go index 64ea94a9ad78..7b185c80f597 100644 --- a/dev-tools/mage/gotool/go.go +++ b/dev-tools/mage/gotool/go.go @@ -37,6 +37,19 @@ type Args struct { // ArgOpt is a functional option adding info to Args once executed. type ArgOpt func(args *Args) +type goInstall func(opts ...ArgOpt) error + +// Install runs `go install` and provides optionals for adding command line arguments. +var Install goInstall = runGoInstall + +func runGoInstall(opts ...ArgOpt) error { + args := buildArgs(opts) + return runVGo("install", args) +} + +func (goInstall) Package(pkg string) ArgOpt { return posArg(pkg) } +func (goInstall) Vendored() ArgOpt { return flagArg("-mod", "vendor") } + type goTest func(opts ...ArgOpt) error // Test runs `go test` and provides optionals for adding command line arguments. diff --git a/dev-tools/mage/install.go b/dev-tools/mage/install.go index 9b2c7795c631..3340201e4660 100644 --- a/dev-tools/mage/install.go +++ b/dev-tools/mage/install.go @@ -37,9 +37,10 @@ func InstallVendored(importPath string) error { return errors.Wrap(err, "failed to obtain beats repository path") } - get := gotool.Get - return get( - get.Package(filepath.Join(beatDir, "vendor", importPath)), + install := gotool.Install + return install( + install.Vendored(), + install.Package(filepath.Join(beatDir, "vendor", importPath)), ) } diff --git a/dev-tools/make/mage.mk b/dev-tools/make/mage.mk index e3bc2631a744..76f507e3d67e 100644 --- a/dev-tools/make/mage.mk +++ b/dev-tools/make/mage.mk @@ -1,13 +1,13 @@ -MAGE_VERSION ?= v1.8.0 +MAGE_VERSION ?= v1.9.0 MAGE_PRESENT := $(shell mage --version 2> /dev/null | grep $(MAGE_VERSION)) -MAGE_IMPORT_PATH ?= github.com/elastic/beats/vendor/github.com/magefile/mage +MAGE_IMPORT_PATH ?= github.com/magefile/mage export MAGE_IMPORT_PATH .PHONY: mage mage: ifndef MAGE_PRESENT @echo Installing mage $(MAGE_VERSION) from vendor dir. - @go install -ldflags="-X $(MAGE_IMPORT_PATH)/mage.gitTag=$(MAGE_VERSION)" ${MAGE_IMPORT_PATH} + @go install -mod=vendor -ldflags="-X $(MAGE_IMPORT_PATH)/mage.gitTag=$(MAGE_VERSION)" ${MAGE_IMPORT_PATH} @-mage -clean endif @true diff --git a/filebeat/input/syslog/input.go b/filebeat/input/syslog/input.go index 71efa8bcfc71..b7da399952f5 100644 --- a/filebeat/input/syslog/input.go +++ b/filebeat/input/syslog/input.go @@ -36,7 +36,7 @@ import ( // Parser is generated from a ragel state machine using the following command: //go:generate ragel -Z -G2 parser.rl -o parser.go -//go:generate go fmt parser.go +//go:generate goimports -l -w parser.go // Severity and Facility are derived from the priority, theses are the human readable terms // defined in https://tools.ietf.org/html/rfc3164#section-4.1.1. diff --git a/go.mod b/go.mod index d8a1761d4536..bdb1ec9d9de3 100644 --- a/go.mod +++ b/go.mod @@ -51,6 +51,7 @@ require ( github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4 github.com/elastic/ecs v1.4.0 github.com/elastic/go-libaudit v0.4.0 + github.com/elastic/go-licenser v0.2.1 github.com/elastic/go-lookslike v0.3.0 github.com/elastic/go-lumber v0.1.0 github.com/elastic/go-perf v0.0.0-20191212140718-9c656876f595 @@ -98,15 +99,14 @@ require ( github.com/mattn/go-isatty v0.0.2 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect github.com/miekg/dns v1.1.15 - github.com/mitchellh/gox v1.0.1 // indirect github.com/mitchellh/hashstructure v0.0.0-20170116052023-ab25296c0f51 github.com/mitchellh/mapstructure v1.1.2 github.com/morikuni/aec v1.0.0 // indirect github.com/opencontainers/go-digest v1.0.0-rc1.0.20190228220655-ac19fd6e7483 // indirect github.com/opencontainers/image-spec v1.0.2-0.20190823105129-775207bd45b6 // indirect github.com/opencontainers/runc v1.0.0-rc9 // indirect - github.com/pierrre/gotestcover v0.0.0-20160113212533-7b94f124d338 // indirect - github.com/pkg/errors v0.8.1 + github.com/pierrre/gotestcover v0.0.0-20160113212533-7b94f124d338 + github.com/pkg/errors v0.9.1 github.com/pmezard/go-difflib v1.0.0 github.com/prometheus/client_golang v1.1.1-0.20190913103102-20428fa0bffc // indirect github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4 @@ -121,6 +121,7 @@ require ( github.com/spf13/pflag v1.0.3 github.com/stretchr/objx v0.1.2-0.20180702103455-b8b73a35e983 // indirect github.com/stretchr/testify v1.4.0 + github.com/tsg/go-daemon v0.0.0-20200123164349-4b60efc26d5f github.com/tsg/gopacket v0.0.0-20190320122513-dd3d0e41124a github.com/urso/magetools v0.0.0-20200106130147-61080ed7b22b // indirect github.com/vmware/govmomi v0.0.0-20170802214208-2cad15190b41 @@ -140,7 +141,6 @@ require ( google.golang.org/appengine v1.6.5 // indirect google.golang.org/genproto v0.0.0-20191115221424-83cc0476cb11 google.golang.org/grpc v1.25.1 // indirect - gopkg.in/goracle.v2 v2.16.3 // indirect gopkg.in/inf.v0 v0.9.0 gopkg.in/jcmturner/gokrb5.v7 v7.3.0 // indirect gopkg.in/mgo.v2 v2.0.0-20160818020120-3f83fa500528 diff --git a/go.sum b/go.sum index aad099947b40..6f1e97d40070 100644 --- a/go.sum +++ b/go.sum @@ -192,6 +192,8 @@ github.com/elastic/fsevents v0.0.0-20181029231046-e1d381a4d270 h1:cWPqxlPtir4RoQ github.com/elastic/fsevents v0.0.0-20181029231046-e1d381a4d270/go.mod h1:Msl1pdboCbArMF/nSCDUXgQuWTeoMmE/z8607X+k7ng= github.com/elastic/go-libaudit v0.4.0 h1:pxLCycMJKW91W8ZmZT74DQmryTZuXryKESo6sXdu1XY= github.com/elastic/go-libaudit v0.4.0/go.mod h1:lNJ7gX+arohEQTwqinAc8xycVuFNqsaunba1mwcBdvE= +github.com/elastic/go-licenser v0.2.1 h1:K76YI6XR2LRpewLGwhrTqasXZcNJG2yHY4/jit/IXGY= +github.com/elastic/go-licenser v0.2.1/go.mod h1:D8eNQk70FOCVBl3smCGQt/lv7meBeQno2eI1S5apiHQ= github.com/elastic/go-lookslike v0.3.0 h1:HDI/DQ65V85ZqM7D/sbxcK2wFFnh3+7iFvBk2v2FTHs= github.com/elastic/go-lookslike v0.3.0/go.mod h1:AhH+rdJux5RlVjs+6ej4jkvYyoNRkj2crxmqeHlj3hA= github.com/elastic/go-lumber v0.1.0 h1:HUjpyg36v2HoKtXlEC53EJ3zDFiDRn65d7B8dBHNius= @@ -257,8 +259,6 @@ github.com/gocarina/gocsv v0.0.0-20170324095351-ffef3ffc77be h1:zXHeEEJ231bTf/IX github.com/gocarina/gocsv v0.0.0-20170324095351-ffef3ffc77be/go.mod h1:/oj50ZdPq/cUjA02lMZhijk5kR31SEydKyqah1OgBuo= github.com/godbus/dbus v4.1.0+incompatible h1:WqqLRTsQic3apZUK9qC5sGNfXthmPXzUZ7nQPrNITa4= github.com/godbus/dbus v4.1.0+incompatible/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= -github.com/godror/godror v0.9.0 h1:IQ+HRUl00B1V03jR4AduWKkKlP9RsTq9E4iEG3gcCZY= -github.com/godror/godror v0.9.0/go.mod h1:06LLZykQEXjuUYiVKBa7Ls+AvbUZ8sbtolIALCeL/jw= github.com/godror/godror v0.10.4 h1:44FcfzDPp/PJZzen5Hm59SZQBhgrbR6E1KwCjg6gnJo= github.com/godror/godror v0.10.4/go.mod h1:9MVLtu25FBJBMHkPs0m3Ngf/VmwGcLpM2HS8PlNGw9U= github.com/gofrs/flock v0.7.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= @@ -307,7 +307,6 @@ github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXi github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/uuid v0.0.0-20170306145142-6a5e28554805/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2-0.20190416172445-c2e93f3ae59f h1:XXzyYlFbxK3kWfcmu3Wc+Tv8/QQl/VqwsWuSYF1Rj0s= @@ -329,8 +328,6 @@ github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FK github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I= github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-version v1.0.0 h1:21MVWPKDphxa7ineQQTrCU5brh7OuVVAzGOCnnCPtE8= -github.com/hashicorp/go-version v1.0.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.2-0.20190520140433-59383c442f7d h1:Ft6PtvobE9vwkCsuoNO5DZDbhKkKuktAlSsiOi1X5NA= @@ -405,12 +402,8 @@ github.com/miekg/dns v1.1.15 h1:CSSIDtllwGLMoA6zjdKnaE6Tx6eVUxQ29LUgGetiDCI= github.com/miekg/dns v1.1.15/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/gox v1.0.1 h1:x0jD3dcHk9a9xPSDN6YEL4xL6Qz0dvNYm8yZqui5chI= -github.com/mitchellh/gox v1.0.1/go.mod h1:ED6BioOGXMswlXa2zxfh/xdd5QhwYliBFn9V18Ap4z4= github.com/mitchellh/hashstructure v0.0.0-20170116052023-ab25296c0f51 h1:qdHlMllk/PTLUrX3XdtXDrLL1lPSfcqUmJD1eYfbapg= github.com/mitchellh/hashstructure v0.0.0-20170116052023-ab25296c0f51/go.mod h1:QjSHrPWS+BGUVBYkbTZWEnOh3G1DutKwClXU/ABz6AQ= -github.com/mitchellh/iochan v1.0.0 h1:C+X3KsSTLFVBr/tK1eYN/vs4rJcvsiLU338UhYPJWeY= -github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -458,6 +451,8 @@ github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -520,6 +515,8 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= +github.com/tsg/go-daemon v0.0.0-20200123164349-4b60efc26d5f h1:lODuUEyjN6TVt5qpv6ILzsVDcIkeV2DCbX63GdevhQ8= +github.com/tsg/go-daemon v0.0.0-20200123164349-4b60efc26d5f/go.mod h1:jAqhj/JBVC1PwcLTWd6rjQyGyItxxrhpiBl8LSuAGmw= github.com/tsg/gopacket v0.0.0-20190320122513-dd3d0e41124a h1:vVmCas8T0lbxAI1GuQO45L0o/OrWJSXtiK6vH27Qspg= github.com/tsg/gopacket v0.0.0-20190320122513-dd3d0e41124a/go.mod h1:RIkfovP3Y7my19aXEjjbNd9E5TlHozzAyt7B8AaEcwg= github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= @@ -532,9 +529,6 @@ github.com/urso/qcgen v0.0.0-20180131103024-0b059e7db4f4 h1:hhA8EBThzz9PztawVTyc github.com/urso/qcgen v0.0.0-20180131103024-0b059e7db4f4/go.mod h1:RspW+E2Yb7Fs7HclB2tiDaiu6Rp41BiIG4Wo1YaoXGc= github.com/vmware/govmomi v0.0.0-20170802214208-2cad15190b41 h1:NeNpIvfvaFOh0BH7nMEljE5Rk/VJlxhm58M41SeOD20= github.com/vmware/govmomi v0.0.0-20170802214208-2cad15190b41/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU= -github.com/vmware/govmomi v0.21.0 h1:jc8uMuxpcV2xMAA/cnEDlnsIjvqcMra5Y8onh/U3VuY= -github.com/vmware/govmomi v0.21.0/go.mod h1:zbnFoBQ9GIjs2RVETy8CNEpb+L+Lwkjs3XZUL0B3/m0= -github.com/vmware/vmw-guestinfo v0.0.0-20170707015358-25eff159a728/go.mod h1:x9oS4Wk2s2u4tS29nEaDLdzvuHdB19CvSGJjPgkZJNk= github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I= github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= @@ -715,8 +709,6 @@ gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= -gopkg.in/goracle.v2 v2.16.3 h1:XNxXVPxdd+lrubuD9dBte5cM0FKb57s6B0+UdvT86m4= -gopkg.in/goracle.v2 v2.16.3/go.mod h1:QhfGFGWSfZKBnBWnAkjd5GreYK1tan9ikkA7BMirttE= gopkg.in/inf.v0 v0.9.0 h1:3zYtXIO92bvsdS3ggAdA8Gb4Azj0YU+TVY1uGYNFA8o= gopkg.in/inf.v0 v0.9.0/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/jcmturner/aescts.v1 v1.0.1 h1:cVVZBK2b1zY26haWB4vbBiZrfFQnfbTVrE3xZq6hrEw= diff --git a/libbeat/scripts/Makefile b/libbeat/scripts/Makefile index db8236cdeef5..a6a0425625e9 100755 --- a/libbeat/scripts/Makefile +++ b/libbeat/scripts/Makefile @@ -22,7 +22,7 @@ SECCOMP_BINARY?=${BEAT_NAME} SECCOMP_BLACKLIST?=${ES_BEATS}/libbeat/common/seccomp/seccomp-profiler-blacklist.txt SECCOMP_ALLOWLIST?=${ES_BEATS}/libbeat/common/seccomp/seccomp-profiler-allow.txt MAGE_PRESENT := $(shell command -v mage 2> /dev/null) -MAGE_IMPORT_PATH?=github.com/elastic/beats/vendor/github.com/magefile/mage +MAGE_IMPORT_PATH?=github.com/magefile/mage export MAGE_IMPORT_PATH space:=$() # diff --git a/metricbeat/helper/windows/pdh/doc.go b/metricbeat/helper/windows/pdh/doc.go index fc6ec0cd1326..736bde4bec9a 100644 --- a/metricbeat/helper/windows/pdh/doc.go +++ b/metricbeat/helper/windows/pdh/doc.go @@ -21,4 +21,4 @@ package pdh //go:generate go run ../run.go -cmd "go tool cgo -godefs defs_pdh_windows.go" -goarch amd64 -output defs_pdh_windows_amd64.go //go:generate go run ../run.go -cmd "go tool cgo -godefs defs_pdh_windows.go" -goarch 386 -output defs_pdh_windows_386.go //go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -output zpdh_windows.go pdh_windows.go -//go:generate gofmt -w defs_pdh_windows_amd64.go defs_pdh_windows_386.go zpdh_windows.go +//go:generate goimports -w defs_pdh_windows_amd64.go defs_pdh_windows_386.go zpdh_windows.go diff --git a/metricbeat/module/windows/service/doc.go b/metricbeat/module/windows/service/doc.go index 1bcbc98e250c..a766843e5042 100644 --- a/metricbeat/module/windows/service/doc.go +++ b/metricbeat/module/windows/service/doc.go @@ -21,4 +21,4 @@ package service //go:generate go run ../../../helper/windows/run.go -cmd "go tool cgo -godefs defs_service_windows.go" -goarch amd64 -output defs_service_windows_amd64.go //go:generate go run ../../../helper/windows/run.go -cmd "go tool cgo -godefs defs_service_windows.go" -goarch 386 -output defs_service_windows_386.go //go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -output zservice_windows.go service_windows.go -//go:generate gofmt -w defs_service_windows_amd64.go defs_service_windows_386.go +//go:generate goimports -w defs_service_windows_amd64.go defs_service_windows_386.go diff --git a/tools/tools.go b/tools/tools.go new file mode 100644 index 000000000000..154ee78a982e --- /dev/null +++ b/tools/tools.go @@ -0,0 +1,32 @@ +// Licensed to Elasticsearch B.V. under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Elasticsearch B.V. licenses this file to you 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. + +// +build tools + +// This package contains the tool dependencies of the project. + +package tools + +import ( + _ "github.com/magefile/mage" + _ "github.com/pierrre/gotestcover" + _ "github.com/tsg/go-daemon" + _ "golang.org/x/tools/cmd/goimports" + _ "golang.org/x/tools/cmd/stringer" + + _ "github.com/elastic/go-licenser" +) diff --git a/vendor/github.com/elastic/go-licenser/.gitignore b/vendor/github.com/elastic/go-licenser/.gitignore new file mode 100644 index 000000000000..9148bfb22205 --- /dev/null +++ b/vendor/github.com/elastic/go-licenser/.gitignore @@ -0,0 +1,3 @@ +bin +testdata +dist diff --git a/vendor/github.com/elastic/go-licenser/.goreleaser.yml b/vendor/github.com/elastic/go-licenser/.goreleaser.yml new file mode 100644 index 000000000000..e8b484cc61d5 --- /dev/null +++ b/vendor/github.com/elastic/go-licenser/.goreleaser.yml @@ -0,0 +1,32 @@ +# This is an example goreleaser.yaml file with some sane defaults. +# Make sure to check the documentation at http://goreleaser.com +release: + github: + owner: elastic + name: go-licenser +builds: +- env: + - CGO_ENABLED=0 + ldflags: -s -w -X main.version={{.Env.VERSION }} -X main.commit={{.Commit}} + goos: + - linux + - darwin + - windows +archive: + replacements: + darwin: Darwin + linux: Linux + windows: Windows + 386: i386 + amd64: x86_64 +checksum: + name_template: 'checksums.txt' +snapshot: + name_template: "{{ .Env.VERSION }}-SNAPSHOT-{{ .Commit }}" +dist: dist +changelog: + sort: asc + filters: + exclude: + - '^docs:' + - '^test:' diff --git a/vendor/github.com/elastic/go-licenser/.travis.yml b/vendor/github.com/elastic/go-licenser/.travis.yml new file mode 100644 index 000000000000..ba9a4e51494a --- /dev/null +++ b/vendor/github.com/elastic/go-licenser/.travis.yml @@ -0,0 +1,22 @@ +language: go + +go: + - "1.x" + - "1.9.x" + - "1.10.x" + - "1.11.x" + +matrix: + fast_finish: true + allow_failures: + - os: osx + include: + - go: "1.x" + os: osx + +before_install: + - make deps + +script: + - make lint + - make unit diff --git a/vendor/github.com/elastic/go-licenser/CONTRIBUTING.md b/vendor/github.com/elastic/go-licenser/CONTRIBUTING.md new file mode 100644 index 000000000000..0c8d15b6f59e --- /dev/null +++ b/vendor/github.com/elastic/go-licenser/CONTRIBUTING.md @@ -0,0 +1,47 @@ +# Contributing + +Contributions are very welcome, this includes documentation, tutorials, bug reports, issues, feature requests, feature implementations, pull requests or simply organizing the repository issues. + +*Pull requests that contain changes on the code base **and** related documentation, e.g. for a new feature, shall remain a single, atomic one.* + +## Building From Source + +### Environment Prerequisites + +To install the latest changes directly from source code, you will need to have `go` installed with `$GOPATH` defined. If you need assistance with this please follow [golangbootcamp guide](http://www.golangbootcamp.com/book/get_setup#cha-get_setup). + +### Actual installation commands + +**Make sure you have followed through the environment requisites** + +```sh +go get -u github.com/elastic/go-licenser +``` + +## Reporting Issues + +If you have found an issue or defect in `go-licenser` or the latest documentation, use the GitHub [issue tracker](https://github.com/elastic/go-licenser/issues) to report the problem. Make sure to follow the template provided for you to provide all the useful details possible. + + +### Code Contribution Guidelines + +For the benefit of all, here are some recommendations with regards to your PR: + +* Go ahead and fork the project and make your changes. We encourage pull requests to allow for review and discussion of code changes. +* As a best practice it's best to open an Issue on the repository before submitting a PR. +* When you’re ready to create a pull request, be sure to: + * Sign your commit messages, see [DCO details](https://probot.github.io/apps/dco/) + * Have test cases for the new code. If you have questions about how to do this, please ask in your pull request. + * Run `make format` and `make lint`. + * Ensure that `make unit` succeeds. + + +### Golden Files + +If you're working with a function that relies on testdata or golden files, you might need to update those if your +change is modifying that logic. + +```console +$ make update-golden-files +ok github.com/elastic/go-licenser 0.029s +``` diff --git a/vendor/github.com/elastic/go-licenser/LICENSE b/vendor/github.com/elastic/go-licenser/LICENSE new file mode 100644 index 000000000000..0d4ee7515f06 --- /dev/null +++ b/vendor/github.com/elastic/go-licenser/LICENSE @@ -0,0 +1,202 @@ + + 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 2018 Elasticsearch B.V. + + 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/elastic/go-licenser/Makefile b/vendor/github.com/elastic/go-licenser/Makefile new file mode 100644 index 000000000000..9cdbf096ee3c --- /dev/null +++ b/vendor/github.com/elastic/go-licenser/Makefile @@ -0,0 +1,106 @@ +export VERSION := v0.3.0 +export GO111MODULE ?= on +OWNER ?= elastic +REPO ?= go-licenser +TEST_UNIT_FLAGS ?= -timeout 10s -p 4 -race -cover +TEST_UNIT_PACKAGE ?= ./... +GOLINT_PRESENT := $(shell command -v golint 2> /dev/null) +GOIMPORTS_PRESENT := $(shell command -v goimports 2> /dev/null) +GORELEASER_PRESENT := $(shell command -v goreleaser 2> /dev/null) +RELEASED = $(shell git tag -l $(VERSION)) +DEFAULT_LDFLAGS ?= -X main.version=$(VERSION)-dev -X main.commit=$(shell git rev-parse HEAD) + +define HELP +///////////////////////////////////////// +/\t$(REPO) Makefile \t\t/ +///////////////////////////////////////// + +## Build target + +- build: It will build $(REPO) for the current architecture in bin/$(REPO). +- install: It will install $(REPO) in the current system (by default in $(GOPATH)/bin/$(REPO)). + +## Development targets + +- deps: It will install the dependencies required to run developemtn targets. +- unit: Runs the unit tests. +- lint: Runs the linters. +- format: Formats the source files according to gofmt, goimports and go-licenser. +- update-golden-files: Updates the test golden files. + +## Release targets + +- release: Creates and publishes a new release matching the VERSION variable. +- snapshot: Creates a snapshot locally in the dist/ folder. + +endef +export HELP + +.DEFAULT: help +.PHONY: help +help: + @ echo "$$HELP" + +.PHONY: deps +deps: +ifndef GOLINT_PRESENT + @ go get -u golang.org/x/lint/golint +endif +ifndef GOIMPORTS_PRESENT + @ go get -u golang.org/x/tools/cmd/goimports +endif + +.PHONY: release_deps +release_deps: +ifndef GORELEASER_PRESENT + @ echo "-> goreleaser not found in path, please install it following the instructions:" + @ echo "-> https://goreleaser.com/introduction" + @ exit 1 +endif + +.PHONY: update-golden-files +update-golden-files: + $(eval GOLDEN_FILE_PACKAGES := "github.com/$(OWNER)/$(REPO)") + @ go test $(GOLDEN_FILE_PACKAGES) -update + +.PHONY: unit +unit: + @ go test $(TEST_UNIT_FLAGS) $(TEST_UNIT_PACKAGE) + +.PHONY: build +build: deps + @ go build -o bin/$(REPO) -ldflags="$(DEFAULT_LDFLAGS)" + +.PHONY: install +install: deps + @ go install + +.PHONY: lint +lint: build + @ golint -set_exit_status $(shell go list ./...) + @ gofmt -d -e -s . + @ ./bin/go-licenser -d -exclude golden + +.PHONY: format +format: deps build + @ gofmt -e -w -s . + @ goimports -w . + @ ./bin/go-licenser -exclude golden + +.PHONY: release +release: deps release_deps + @ echo "-> Releasing $(REPO) $(VERSION)..." + @ git fetch upstream +ifeq ($(strip $(RELEASED)),) + @ echo "-> Creating and pushing a new tag $(VERSION)..." + @ git tag $(VERSION) + @ git push upstream $(VERSION) + @ goreleaser release --rm-dist +else + @ echo "-> git tag $(VERSION) already present, skipping release..." +endif + +.PHONY: snapshot +snapshot: deps release_deps + @ echo "-> Snapshotting $(REPO) $(VERSION)..." + @ goreleaser release --snapshot --rm-dist diff --git a/vendor/github.com/elastic/go-licenser/NOTICE b/vendor/github.com/elastic/go-licenser/NOTICE new file mode 100644 index 000000000000..4972cec5acdd --- /dev/null +++ b/vendor/github.com/elastic/go-licenser/NOTICE @@ -0,0 +1,5 @@ +Elastic go-licenser +Copyright 2018 Elasticsearch B.V. + +This product includes software developed at +Elasticsearch, B.V. (https://www.elastic.co/). diff --git a/vendor/github.com/elastic/go-licenser/README.md b/vendor/github.com/elastic/go-licenser/README.md new file mode 100644 index 000000000000..ea3e81c7c315 --- /dev/null +++ b/vendor/github.com/elastic/go-licenser/README.md @@ -0,0 +1,49 @@ +# Go Licenser [![Build Status](https://travis-ci.org/elastic/go-licenser.svg?branch=master)](https://travis-ci.org/elastic/go-licenser) + +Small zero dependency license header checker for source files. The aim of this project is to provide a common +binary that can be used to ensure that code source files contain a license header. It's unlikely that this project +is useful outside of Elastic **_at the current stage_**, but the `licensing` package can be used as a building block. + +## Supported Licenses + +* Apache 2.0 +* Elastic +* Elastic Cloud + +## Supported languages + +* Go + +## Installing + +``` +go get -u github.com/elastic/go-licenser +``` + +## Usage + +``` +Usage: go-licenser [flags] [path] + + go-licenser walks the specified path recursiely and appends a license Header if the current + header doesn't match the one found in the file. + +Options: + + -d skips rewriting files and returns exitcode 1 if any discrepancies are found. + -exclude value + path to exclude (can be specified multiple times). + -ext string + sets the file extension to scan for. (default ".go") + -license string + sets the license type to check: ASL2, Elastic, Cloud (default "ASL2") + -licensor string + sets the name of the licensor (default "Elasticsearch B.V.") + -version + prints out the binary version. +``` + +## Contributing + +See [CONTRIBUTING.md](./CONTRIBUTING.md). + diff --git a/vendor/github.com/elastic/go-licenser/appveyor.yml b/vendor/github.com/elastic/go-licenser/appveyor.yml new file mode 100644 index 000000000000..2292bcb2d933 --- /dev/null +++ b/vendor/github.com/elastic/go-licenser/appveyor.yml @@ -0,0 +1,38 @@ +version: "{build}" + +# Source Config + +clone_folder: c:\gopath\src\github.com\elastic\go-licenser + +# Build host + +environment: + GOPATH: c:\gopath + GOVERSION: 1.10 + +# 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 + +before_build: + - go get -u golang.org/x/lint/golint + - go get -u golang.org/x/tools/cmd/goimports + - golint -set_exit_status . + - gofmt -d -e -s . + - goimports -d . + +build_script: + - appveyor AddCompilationMessage "Starting Compilation" + - go install github.com/elastic/go-licenser + +test_script: + - go-licenser -d -exclude golden + - go test -timeout 10s -p 4 -race -cover ./... diff --git a/vendor/github.com/elastic/go-licenser/error.go b/vendor/github.com/elastic/go-licenser/error.go new file mode 100644 index 000000000000..5c40faa3b2cb --- /dev/null +++ b/vendor/github.com/elastic/go-licenser/error.go @@ -0,0 +1,39 @@ +// Licensed to Elasticsearch B.V. under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Elasticsearch B.V. licenses this file to you 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. + +package main + +// Error wraps a normal error with an Exitcode. +type Error struct { + err error + code int +} + +func (e Error) Error() string { + if e.err != nil { + return e.err.Error() + } + return "" +} + +// Code returns the exitcode for the error +func Code(e error) int { + if err, ok := e.(*Error); ok { + return err.code + } + return 0 +} diff --git a/vendor/github.com/elastic/go-licenser/go.mod b/vendor/github.com/elastic/go-licenser/go.mod new file mode 100644 index 000000000000..89b964cbf36b --- /dev/null +++ b/vendor/github.com/elastic/go-licenser/go.mod @@ -0,0 +1 @@ +module github.com/elastic/go-licenser diff --git a/vendor/github.com/elastic/go-licenser/licensing/doc.go b/vendor/github.com/elastic/go-licenser/licensing/doc.go new file mode 100644 index 000000000000..3fcc1ac56b34 --- /dev/null +++ b/vendor/github.com/elastic/go-licenser/licensing/doc.go @@ -0,0 +1,20 @@ +// Licensed to Elasticsearch B.V. under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Elasticsearch B.V. licenses this file to you 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. + +// Package licensing provides a set of functions that read the top +// lines of a file and can determine if they match a specific header. +package licensing diff --git a/vendor/github.com/elastic/go-licenser/licensing/license.go b/vendor/github.com/elastic/go-licenser/licensing/license.go new file mode 100644 index 000000000000..fad14c14ed9a --- /dev/null +++ b/vendor/github.com/elastic/go-licenser/licensing/license.go @@ -0,0 +1,132 @@ +// Licensed to Elasticsearch B.V. under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Elasticsearch B.V. licenses this file to you 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. + +package licensing + +import ( + "bufio" + "bytes" + "errors" + "io" + "io/ioutil" + "os" + "reflect" + "strings" +) + +var ( + startPrefixes = []string{"// Copyright", "// copyright", "// Licensed", "// licensed"} + endPrefixes = []string{"package ", "// Package ", "// +build ", "// Code generated by", "// code generated by"} + + errHeaderIsTooShort = errors.New("header is too short") +) + +// ContainsHeader reads the first N lines of a file and checks if the header +// matches the one that is expected +func ContainsHeader(r io.Reader, headerLines []string) bool { + var found []string + var scanner = bufio.NewScanner(r) + + for scanner.Scan() { + found = append(found, scanner.Text()) + } + + if len(found) < len(headerLines) { + return false + } + + if !reflect.DeepEqual(found[:len(headerLines)], headerLines) { + return false + } + + return true +} + +// RewriteFileWithHeader reads a file from a path and rewrites it with a header +func RewriteFileWithHeader(path string, header []byte) error { + if len(header) < 2 { + return errHeaderIsTooShort + } + + info, err := os.Stat(path) + if err != nil { + return err + } + + origin, err := ioutil.ReadFile(path) + if err != nil { + return err + } + + data := RewriteWithHeader(origin, header) + return ioutil.WriteFile(path, data, info.Mode()) +} + +// RewriteWithHeader rewrites the src byte buffers header with the new header. +func RewriteWithHeader(src []byte, header []byte) []byte { + // Ensures that the header includes two break lines as the last bytes + for !reflect.DeepEqual(header[len(header)-2:], []byte("\n\n")) { + header = append(header, []byte("\n")...) + } + + var oldHeader = headerBytes(bytes.NewReader(src)) + return bytes.Replace(src, oldHeader, header, 1) +} + +// headerBytes detects the header lines of an io.Reader contents and returns +// what it considerst to be the header as a slice of bytes. +func headerBytes(r io.Reader) []byte { + var scanner = bufio.NewScanner(r) + var replaceableHeader []byte + var continuedHeader bool + for scanner.Scan() { + var t = scanner.Text() + + for i := range endPrefixes { + if strings.HasPrefix(t, endPrefixes[i]) { + return replaceableHeader + } + } + + for i := range startPrefixes { + if strings.HasPrefix(t, startPrefixes[i]) { + continuedHeader = true + } + } + + if continuedHeader { + replaceableHeader = append(replaceableHeader, []byte(t+"\n")...) + } + } + + return replaceableHeader +} + +// containsHeaderLine reads the first N lines of a file and checks if the header +// matches the one that is expected +func containsHeaderLine(r io.Reader, headerLines []string) bool { + var scanner = bufio.NewScanner(r) + for scanner.Scan() { + for i := range headerLines { + if scanner.Text() == headerLines[i] { + return true + } + } + } + + return false +} diff --git a/vendor/github.com/elastic/go-licenser/main.go b/vendor/github.com/elastic/go-licenser/main.go new file mode 100644 index 000000000000..dd35fa88538a --- /dev/null +++ b/vendor/github.com/elastic/go-licenser/main.go @@ -0,0 +1,258 @@ +// Licensed to Elasticsearch B.V. under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Elasticsearch B.V. licenses this file to you 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. + +package main + +import ( + "flag" + "fmt" + "io" + "os" + "path/filepath" + "strings" + + "github.com/elastic/go-licenser/licensing" +) + +const ( + defaultExt = ".go" + defaultPath = "." + defaultLicense = "ASL2" + defaultLicensor = "Elasticsearch B.V." + defaultFormat = "%s: is missing the license header\n" +) + +const ( + exitDefault = iota + exitSourceNeedsToBeRewritten + exitFailedToStatTree + exitFailedToStatFile + exitFailedToWalkPath + exitFailedToOpenWalkFile + errFailedRewrittingFile + errUnknownLicense +) + +var usageText = ` +Usage: go-licenser [flags] [path] + + go-licenser walks the specified path recursiely and appends a license Header if the current + header doesn't match the one found in the file. + +Options: + +`[1:] + +// Headers is the map of supported licenses +var Headers = map[string][]string{ + "ASL2": { + `// Licensed to %s under one or more contributor`, + `// license agreements. See the NOTICE file distributed with`, + `// this work for additional information regarding copyright`, + `// ownership. %s licenses this file to you 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.`, + }, + "Elastic": { + `// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one`, + `// or more contributor license agreements. Licensed under the Elastic License;`, + `// you may not use this file except in compliance with the Elastic License.`, + }, + "Cloud": { + `// ELASTICSEARCH CONFIDENTIAL`, + `// __________________`, + `//`, + `// Copyright Elasticsearch B.V. All rights reserved.`, + `//`, + `// NOTICE: All information contained herein is, and remains`, + `// the property of Elasticsearch B.V. and its suppliers, if any.`, + `// The intellectual and technical concepts contained herein`, + `// are proprietary to Elasticsearch B.V. and its suppliers and`, + `// may be covered by U.S. and Foreign Patents, patents in`, + `// process, and are protected by trade secret or copyright`, + `// law. Dissemination of this information or reproduction of`, + `// this material is strictly forbidden unless prior written`, + `// permission is obtained from Elasticsearch B.V.`, + }, +} + +var ( + dryRun bool + showVersion bool + extension string + args []string + license string + licensor string + exclude sliceFlag + defaultExludedDirs = []string{"vendor", ".git"} +) + +type sliceFlag []string + +func (f *sliceFlag) String() string { + var s string + for _, i := range *f { + s += i + " " + } + return s +} + +func (f *sliceFlag) Set(value string) error { + *f = append(*f, value) + return nil +} + +func init() { + flag.Var(&exclude, "exclude", `path to exclude (can be specified multiple times).`) + flag.BoolVar(&dryRun, "d", false, `skips rewriting files and returns exitcode 1 if any discrepancies are found.`) + flag.BoolVar(&showVersion, "version", false, `prints out the binary version.`) + flag.StringVar(&extension, "ext", defaultExt, "sets the file extension to scan for.") + flag.StringVar(&license, "license", defaultLicense, "sets the license type to check: ASL2, Elastic, Cloud") + flag.StringVar(&licensor, "licensor", defaultLicensor, "sets the name of the licensor") + flag.Usage = usageFlag + flag.Parse() + args = flag.Args() +} + +func main() { + if showVersion { + fmt.Printf("go-licenser %s (%s)\n", version, commit) + return + } + + err := run(args, license, licensor, exclude, extension, dryRun, os.Stdout) + if err != nil && err.Error() != "" { + fmt.Fprint(os.Stderr, err) + } + + os.Exit(Code(err)) +} + +func run(args []string, license, licensor string, exclude []string, ext string, dry bool, out io.Writer) error { + header, ok := Headers[license] + if !ok { + return &Error{err: fmt.Errorf("unknown license: %s", license), code: errUnknownLicense} + } + + var headerBytes []byte + for i, line := range header { + if strings.Contains(line, "%s") { + header[i] = fmt.Sprintf(line, licensor) + } + headerBytes = append(headerBytes, []byte(header[i])...) + headerBytes = append(headerBytes, []byte("\n")...) + } + + var path = defaultPath + if len(args) > 0 { + path = args[0] + } + + if _, err := os.Stat(path); err != nil { + return &Error{err: err, code: exitFailedToStatTree} + } + + return walk(path, ext, license, headerBytes, exclude, dry, out) +} + +func reportFile(out io.Writer, f string) { + cwd, _ := filepath.Abs(filepath.Dir(os.Args[0])) + rel, err := filepath.Rel(cwd, f) + if err != nil { + rel = f + } + fmt.Fprintf(out, defaultFormat, rel) +} + +func walk(p, ext, license string, headerBytes []byte, exclude []string, dry bool, out io.Writer) error { + var err error + filepath.Walk(p, func(path string, info os.FileInfo, walkErr error) error { + if walkErr != nil { + err = &Error{err: walkErr, code: exitFailedToWalkPath} + return walkErr + } + + var currentPath = cleanPathPrefixes( + strings.Replace(path, p, "", 1), + []string{string(os.PathSeparator)}, + ) + + var excludedDir = info.IsDir() && stringInSlice(info.Name(), defaultExludedDirs) + if needsExclusion(currentPath, exclude) || excludedDir { + return filepath.SkipDir + } + + if e := addOrCheckLicense(path, ext, license, headerBytes, info, dry, out); e != nil { + err = e + } + + return nil + }) + + return err +} + +func addOrCheckLicense(path, ext, license string, headerBytes []byte, info os.FileInfo, dry bool, out io.Writer) error { + if info.IsDir() || filepath.Ext(path) != ext { + return nil + } + + f, e := os.Open(path) + if e != nil { + return &Error{err: e, code: exitFailedToOpenWalkFile} + } + defer f.Close() + + if licensing.ContainsHeader(f, Headers[license]) { + return nil + } + + if dry { + reportFile(out, path) + return &Error{code: exitSourceNeedsToBeRewritten} + } + + if err := licensing.RewriteFileWithHeader(path, headerBytes); err != nil { + return &Error{err: err, code: errFailedRewrittingFile} + } + + return nil +} + +func stringInSlice(a string, list []string) bool { + for _, b := range list { + if b == a { + return true + } + } + return false +} + +func usageFlag() { + fmt.Fprintf(os.Stderr, usageText) + flag.PrintDefaults() +} diff --git a/vendor/github.com/elastic/go-licenser/path.go b/vendor/github.com/elastic/go-licenser/path.go new file mode 100644 index 000000000000..fad555b0592d --- /dev/null +++ b/vendor/github.com/elastic/go-licenser/path.go @@ -0,0 +1,54 @@ +// Licensed to Elasticsearch B.V. under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Elasticsearch B.V. licenses this file to you 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. + +package main + +import ( + "os" + "strings" +) + +func needsExclusion(path string, exclude []string) bool { + for _, excluded := range exclude { + excluded = cleanPathSuffixes(excluded, []string{"*", string(os.PathSeparator)}) + if strings.HasPrefix(path, excluded) { + return true + } + } + + return false +} + +func cleanPathSuffixes(path string, sufixes []string) string { + for _, suffix := range sufixes { + for strings.HasSuffix(path, suffix) && len(path) > 0 { + path = path[:len(path)-len(suffix)] + } + } + + return path +} + +func cleanPathPrefixes(path string, prefixes []string) string { + for _, prefix := range prefixes { + for strings.HasPrefix(path, prefix) && len(path) > 0 { + path = path[len(prefix):] + } + } + + return path +} diff --git a/vendor/github.com/elastic/go-licenser/version.go b/vendor/github.com/elastic/go-licenser/version.go new file mode 100644 index 000000000000..426d12340859 --- /dev/null +++ b/vendor/github.com/elastic/go-licenser/version.go @@ -0,0 +1,23 @@ +// Licensed to Elasticsearch B.V. under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Elasticsearch B.V. licenses this file to you 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. + +package main + +var ( + version string + commit string +) diff --git a/vendor/github.com/magefile/mage/.gitattributes b/vendor/github.com/magefile/mage/.gitattributes new file mode 100644 index 000000000000..571c1ad444ff --- /dev/null +++ b/vendor/github.com/magefile/mage/.gitattributes @@ -0,0 +1,2 @@ +site/* linguist-documentation +vendor/* linguist-vendored \ No newline at end of file diff --git a/vendor/github.com/magefile/mage/.gitignore b/vendor/github.com/magefile/mage/.gitignore new file mode 100644 index 000000000000..29d96346b1db --- /dev/null +++ b/vendor/github.com/magefile/mage/.gitignore @@ -0,0 +1,27 @@ +# Binaries for programs and plugins +*.exe +*.dll +*.so +*.dylib + +# Test binary, build with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736 +.glide/ + +# Magefile output +mage_output_file.go + +# VScode +.vscode + +# stupid osx +.DS_Store + +# Goland +.idea +*.iml diff --git a/vendor/github.com/magefile/mage/.goreleaser.yml b/vendor/github.com/magefile/mage/.goreleaser.yml new file mode 100644 index 000000000000..1f7ba274af0a --- /dev/null +++ b/vendor/github.com/magefile/mage/.goreleaser.yml @@ -0,0 +1,53 @@ +project_name: mage +release: + github: + owner: magefile + name: mage + draft: true +build: + binary: mage + main: . + ldflags: -s -w -X github.com/magefile/mage/mage.timestamp={{.Date}} -X github.com/magefile/mage/mage.commitHash={{.Commit}} -X github.com/magefile/mage/mage.gitTag={{.Version}} + goos: + - darwin + - linux + - windows + - freebsd + - netbsd + - openbsd + - dragonfly + goarch: + - amd64 + - 386 + - arm + - arm64 + ignore: + - goos: openbsd + goarch: arm + goarm: 6 + env: + - CGO_ENABLED=0 +archive: + name_template: "{{.Binary}}_{{.Version}}_{{.Os}}-{{.Arch}}" + replacements: + amd64: 64bit + 386: 32bit + arm: ARM + arm64: ARM64 + darwin: macOS + linux: Linux + windows: Windows + openbsd: OpenBSD + netbsd: NetBSD + freebsd: FreeBSD + dragonfly: DragonFlyBSD + format: tar.gz + format_overrides: + - goos: windows + format: zip + files: + - LICENSE +snapshot: + name_template: SNAPSHOT-{{ .Commit }} +checksum: + name_template: '{{ .ProjectName }}_{{ .Version }}_checksums.txt' diff --git a/vendor/github.com/magefile/mage/.travis.yml b/vendor/github.com/magefile/mage/.travis.yml new file mode 100644 index 000000000000..86afc134a593 --- /dev/null +++ b/vendor/github.com/magefile/mage/.travis.yml @@ -0,0 +1,28 @@ +language: go + +# prevent double test runs for PRs +branches: + only: + - "master" + +# In theory, older versions would probably work fine, but since this isn't a +# library, I'm not going to worry about older versions for now. +go: + - tip + - 1.13.x + - 1.12.x + - 1.11.x + - 1.10.x + - 1.9.x + - 1.8.x + - 1.7.x + +# don't call go get ./... because this hides when deps are +# not packaged into the vendor directory. +install: true + +# don't call go test -v because we want to be able to only show t.Log output when +# a test fails +script: + - go vet ./... + - go test -tags CI -race ./... \ No newline at end of file diff --git a/vendor/github.com/magefile/mage/CONTRIBUTING.md b/vendor/github.com/magefile/mage/CONTRIBUTING.md new file mode 100644 index 000000000000..e1394d20452c --- /dev/null +++ b/vendor/github.com/magefile/mage/CONTRIBUTING.md @@ -0,0 +1,42 @@ +# Contributing + +Of course, contributions are more than welcome. Please read these guidelines for +making the process as painless as possible. + +## Discussion + +Development discussion should take place on the #mage channel of [gopher +slack](https://gophers.slack.com/). + +There is a separate #mage-dev channel that has the github app to post github +activity to the channel, to make it easy to follow. + +## Issues + +If there's an issue you'd like to work on, please comment on it, so we can +discuss approach, etc. and make sure no one else is currently working on that +issue. + +Please always create an issue before sending a PR unless it's an obvious typo +or other trivial change. + +## Dependency Management + +Currently mage has no dependencies(!) outside the standard libary. Let's keep +it that way. Since it's likely that mage will be vendored into a project, +adding dependencies to mage adds dependencies to every project that uses mage. + +## Versions + +Please avoid using features of go and the stdlib that prevent mage from being +buildable with older versions of Go. The CI tests currently check that mage is +buildable with go 1.7 and later. You may build with whatever version you like, +but CI has the final say. + +## Testing + +Please write tests for any new features. Tests must use the normal go testing +package. + +Tests must pass the race detector (run `go test -race ./...`). + diff --git a/vendor/github.com/magefile/mage/README.md b/vendor/github.com/magefile/mage/README.md new file mode 100644 index 000000000000..eed068dcdee7 --- /dev/null +++ b/vendor/github.com/magefile/mage/README.md @@ -0,0 +1,80 @@ +[![Built with Mage](https://magefile.org/badge.svg)](https://magefile.org) +[![Build Status](https://travis-ci.org/magefile/mage.svg?branch=master)](https://travis-ci.org/magefile/mage) [![Build status](https://ci.appveyor.com/api/projects/status/n6h146y79xgxkidl/branch/master?svg=true)](https://ci.appveyor.com/project/natefinch/mage/branch/master) + +

+ +## About + +Mage is a make-like build tool using Go. You write plain-old go functions, +and Mage automatically uses them as Makefile-like runnable targets. + +## Installation + +Mage has no dependencies outside the Go standard library, and builds with Go 1.7 +and above (possibly even lower versions, but they're not regularly tested). + +**Using GOPATH** + +``` +go get -u -d github.com/magefile/mage +cd $GOPATH/src/github.com/magefile/mage +go run bootstrap.go +``` + +**Using Go Modules** + +``` +git clone https://github.com/magefile/mage +cd mage +go run bootstrap.go +``` + +This will download the code and then run the bootstrap script to build mage with +version infomation embedded in it. A normal `go get` (without -d) or `go +install` will build the binary correctly, but no version info will be embedded. +If you've done this, no worries, just go to `$GOPATH/src/github.com/magefile/mage` +and run `mage install` or `go run bootstrap.go` and a new binary will be created +with the correct version information. + +The mage binary will be created in your $GOPATH/bin directory. + +You may also install a binary release from our +[releases](https://github.com/magefile/mage/releases) page. + +## Demo + +[![Mage Demo](https://img.youtube.com/vi/GOqbD0lF-iA/maxresdefault.jpg)](https://www.youtube.com/watch?v=GOqbD0lF-iA) + +## Discussion + +Join the `#mage` channel on [gophers slack](https://gophers.slack.com/messages/general/) +or post on the [magefile google group](https://groups.google.com/forum/#!forum/magefile) +for discussion of usage, development, etc. + +# Documentation + +see [magefile.org](https://magefile.org) for full docs + +see [godoc.org/github.com/magefile/mage/mage](https://godoc.org/github.com/magefile/mage/mage) for how to use mage as a library. + +# Why? + +Makefiles are hard to read and hard to write. Mostly because makefiles are +essentially fancy bash scripts with significant white space and additional +make-related syntax. + +Mage lets you have multiple magefiles, name your magefiles whatever you want, +and they're easy to customize for multiple operating systems. Mage has no +dependencies (aside from go) and runs just fine on all major operating systems, +whereas make generally uses bash which is not well supported on Windows. Go is +superior to bash for any non-trivial task involving branching, looping, anything +that's not just straight line execution of commands. And if your project is +written in Go, why introduce another language as idiosyncratic as bash? Why not +use the language your contributors are already comfortable with? + +# Thanks + +If you use mage and like it, or any of my other software, and you'd like to show your appreciation, you can do so on my patreon: + +[](https://www.patreon.com/join/natefinch?) + diff --git a/vendor/github.com/magefile/mage/go.mod b/vendor/github.com/magefile/mage/go.mod new file mode 100644 index 000000000000..8261fa131181 --- /dev/null +++ b/vendor/github.com/magefile/mage/go.mod @@ -0,0 +1,3 @@ +module github.com/magefile/mage + +go 1.12 diff --git a/vendor/github.com/magefile/mage/go.sum b/vendor/github.com/magefile/mage/go.sum new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/vendor/github.com/magefile/mage/internal/run.go b/vendor/github.com/magefile/mage/internal/run.go new file mode 100644 index 000000000000..4e698891b14b --- /dev/null +++ b/vendor/github.com/magefile/mage/internal/run.go @@ -0,0 +1,114 @@ +package internal + +import ( + "bytes" + "fmt" + "io/ioutil" + "log" + "os" + "os/exec" + "runtime" + "strings" +) + +var debug *log.Logger = log.New(ioutil.Discard, "", 0) + +func SetDebug(l *log.Logger) { + debug = l +} + +func RunDebug(cmd string, args ...string) error { + env, err := EnvWithCurrentGOOS() + if err != nil { + return err + } + buf := &bytes.Buffer{} + errbuf := &bytes.Buffer{} + debug.Println("running", cmd, strings.Join(args, " ")) + c := exec.Command(cmd, args...) + c.Env = env + c.Stderr = errbuf + c.Stdout = buf + if err := c.Run(); err != nil { + debug.Print("error running '", cmd, strings.Join(args, " "), "': ", err, ": ", errbuf) + return err + } + debug.Println(buf) + return nil +} + +func OutputDebug(cmd string, args ...string) (string, error) { + env, err := EnvWithCurrentGOOS() + if err != nil { + return "", err + } + buf := &bytes.Buffer{} + errbuf := &bytes.Buffer{} + debug.Println("running", cmd, strings.Join(args, " ")) + c := exec.Command(cmd, args...) + c.Env = env + c.Stderr = errbuf + c.Stdout = buf + if err := c.Run(); err != nil { + debug.Print("error running '", cmd, strings.Join(args, " "), "': ", err, ": ", errbuf) + return "", err + } + return strings.TrimSpace(buf.String()), nil +} + +// splitEnv takes the results from os.Environ() (a []string of foo=bar values) +// and makes a map[string]string out of it. +func splitEnv(env []string) (map[string]string, error) { + out := map[string]string{} + + for _, s := range env { + parts := strings.SplitN(s, "=", 2) + if len(parts) != 2 { + return nil, fmt.Errorf("badly formatted environment variable: %v", s) + } + out[parts[0]] = parts[1] + } + return out, nil +} + +// joinEnv converts the given map into a list of foo=bar environment variables, +// such as that outputted by os.Environ(). +func joinEnv(env map[string]string) []string { + vals := make([]string, 0, len(env)) + for k, v := range env { + vals = append(vals, k+"="+v) + } + return vals +} + +// EnvWithCurrentGOOS returns a copy of os.Environ with the GOOS and GOARCH set +// to runtime.GOOS and runtime.GOARCH. +func EnvWithCurrentGOOS() ([]string, error) { + vals, err := splitEnv(os.Environ()) + if err != nil { + return nil, err + } + vals["GOOS"] = runtime.GOOS + vals["GOARCH"] = runtime.GOARCH + return joinEnv(vals), nil +} + +// EnvWithGOOS retuns the os.Environ() values with GOOS and/or GOARCH either set +// to their runtime value, or the given value if non-empty. +func EnvWithGOOS(goos, goarch string) ([]string, error) { + env, err := splitEnv(os.Environ()) + if err != nil { + return nil, err + } + if goos == "" { + env["GOOS"] = runtime.GOOS + } else { + env["GOOS"] = goos + } + if goarch == "" { + env["GOARCH"] = runtime.GOARCH + } else { + env["GOARCH"] = goarch + } + return joinEnv(env), nil +} diff --git a/vendor/github.com/magefile/mage/mage/command_string.go b/vendor/github.com/magefile/mage/mage/command_string.go new file mode 100644 index 000000000000..fcdaf9f94944 --- /dev/null +++ b/vendor/github.com/magefile/mage/mage/command_string.go @@ -0,0 +1,16 @@ +// Code generated by "stringer -type=Command"; DO NOT EDIT. + +package mage + +import "strconv" + +const _Command_name = "NoneVersionInitCleanCompileStatic" + +var _Command_index = [...]uint8{0, 4, 11, 15, 20, 33} + +func (i Command) String() string { + if i < 0 || i >= Command(len(_Command_index)-1) { + return "Command(" + strconv.FormatInt(int64(i), 10) + ")" + } + return _Command_name[_Command_index[i]:_Command_index[i+1]] +} diff --git a/vendor/github.com/magefile/mage/mage/magefile_tmpl.go b/vendor/github.com/magefile/mage/mage/magefile_tmpl.go new file mode 100644 index 000000000000..01b878600641 --- /dev/null +++ b/vendor/github.com/magefile/mage/mage/magefile_tmpl.go @@ -0,0 +1,46 @@ +package mage + +var mageTpl = `// +build mage + +package main + +import ( + "fmt" + "os" + "os/exec" + + "github.com/magefile/mage/mg" // mg contains helpful utility functions, like Deps +) + +// Default target to run when none is specified +// If not set, running mage will list available targets +// var Default = Build + +// A build step that requires additional params, or platform specific steps for example +func Build() error { + mg.Deps(InstallDeps) + fmt.Println("Building...") + cmd := exec.Command("go", "build", "-o", "MyApp", ".") + return cmd.Run() +} + +// A custom install step if you need your bin someplace other than go/bin +func Install() error { + mg.Deps(Build) + fmt.Println("Installing...") + return os.Rename("./MyApp", "/usr/bin/MyApp") +} + +// Manage your deps, or running package managers. +func InstallDeps() error { + fmt.Println("Installing Deps...") + cmd := exec.Command("go", "get", "github.com/stretchr/piglatin") + return cmd.Run() +} + +// Clean up after yourself +func Clean() { + fmt.Println("Cleaning...") + os.RemoveAll("MyApp") +} +` diff --git a/vendor/github.com/magefile/mage/mage/main.go b/vendor/github.com/magefile/mage/mage/main.go new file mode 100644 index 000000000000..4325ce95aa35 --- /dev/null +++ b/vendor/github.com/magefile/mage/mage/main.go @@ -0,0 +1,681 @@ +package mage + +import ( + "bytes" + "crypto/sha1" + "errors" + "flag" + "fmt" + "io" + "io/ioutil" + "log" + "os" + "os/exec" + "path/filepath" + "regexp" + "runtime" + "sort" + "strings" + "text/template" + "time" + + "github.com/magefile/mage/internal" + "github.com/magefile/mage/mg" + "github.com/magefile/mage/parse" + "github.com/magefile/mage/sh" +) + +// magicRebuildKey is used when hashing the output binary to ensure that we get +// a new binary even if nothing in the input files or generated mainfile has +// changed. This can be used when we change how we parse files, or otherwise +// change the inputs to the compiling process. +const magicRebuildKey = "v0.3" + +// (Aaaa)(Bbbb) -> aaaaBbbb +var firstWordRx = regexp.MustCompile(`^([[:upper:]][^[:upper:]]+)([[:upper:]].*)$`) + +// (AAAA)(Bbbb) -> aaaaBbbb +var firstAbbrevRx = regexp.MustCompile(`^([[:upper:]]+)([[:upper:]][^[:upper:]].*)$`) + +func lowerFirstWord(s string) string { + if match := firstWordRx.FindStringSubmatch(s); match != nil { + return strings.ToLower(match[1]) + match[2] + } + if match := firstAbbrevRx.FindStringSubmatch(s); match != nil { + return strings.ToLower(match[1]) + match[2] + } + return strings.ToLower(s) +} + +var mainfileTemplate = template.Must(template.New("").Funcs(map[string]interface{}{ + "lower": strings.ToLower, + "lowerFirst": func(s string) string { + parts := strings.Split(s, ":") + for i, t := range parts { + parts[i] = lowerFirstWord(t) + } + return strings.Join(parts, ":") + }, +}).Parse(mageMainfileTplString)) +var initOutput = template.Must(template.New("").Parse(mageTpl)) + +const mainfile = "mage_output_file.go" +const initFile = "magefile.go" + +var debug = log.New(ioutil.Discard, "DEBUG: ", log.Ltime|log.Lmicroseconds) + +// set by ldflags when you "mage build" +var ( + commitHash = "" + timestamp = "" + gitTag = "" +) + +//go:generate stringer -type=Command + +// Command tracks invocations of mage that run without targets or other flags. +type Command int + +// The various command types +const ( + None Command = iota + Version // report the current version of mage + Init // create a starting template for mage + Clean // clean out old compiled mage binaries from the cache + CompileStatic // compile a static binary of the current directory +) + +// Main is the entrypoint for running mage. It exists external to mage's main +// function to allow it to be used from other programs, specifically so you can +// go run a simple file that run's mage's Main. +func Main() int { + return ParseAndRun(os.Stdout, os.Stderr, os.Stdin, os.Args[1:]) +} + +// Invocation contains the args for invoking a run of Mage. +type Invocation struct { + Debug bool // turn on debug messages + Dir string // directory to read magefiles from + Force bool // forces recreation of the compiled binary + Verbose bool // tells the magefile to print out log statements + List bool // tells the magefile to print out a list of targets + Help bool // tells the magefile to print out help for a specific target + Keep bool // tells mage to keep the generated main file after compiling + Timeout time.Duration // tells mage to set a timeout to running the targets + CompileOut string // tells mage to compile a static binary to this path, but not execute + GOOS string // sets the GOOS when producing a binary with -compileout + GOARCH string // sets the GOARCH when producing a binary with -compileout + Stdout io.Writer // writer to write stdout messages to + Stderr io.Writer // writer to write stderr messages to + Stdin io.Reader // reader to read stdin from + Args []string // args to pass to the compiled binary + GoCmd string // the go binary command to run + CacheDir string // the directory where we should store compiled binaries + HashFast bool // don't rely on GOCACHE, just hash the magefiles +} + +// ParseAndRun parses the command line, and then compiles and runs the mage +// files in the given directory with the given args (do not include the command +// name in the args). +func ParseAndRun(stdout, stderr io.Writer, stdin io.Reader, args []string) int { + errlog := log.New(stderr, "", 0) + out := log.New(stdout, "", 0) + inv, cmd, err := Parse(stderr, stdout, args) + inv.Stderr = stderr + inv.Stdin = stdin + if err == flag.ErrHelp { + return 0 + } + if err != nil { + errlog.Println("Error:", err) + return 2 + } + + switch cmd { + case Version: + out.Println("Mage Build Tool", gitTag) + out.Println("Build Date:", timestamp) + out.Println("Commit:", commitHash) + out.Println("built with:", runtime.Version()) + return 0 + case Init: + if err := generateInit(inv.Dir); err != nil { + errlog.Println("Error:", err) + return 1 + } + out.Println(initFile, "created") + return 0 + case Clean: + if err := removeContents(inv.CacheDir); err != nil { + out.Println("Error:", err) + return 1 + } + out.Println(inv.CacheDir, "cleaned") + return 0 + case CompileStatic: + return Invoke(inv) + case None: + return Invoke(inv) + default: + panic(fmt.Errorf("Unknown command type: %v", cmd)) + } +} + +// Parse parses the given args and returns structured data. If parse returns +// flag.ErrHelp, the calling process should exit with code 0. +func Parse(stderr, stdout io.Writer, args []string) (inv Invocation, cmd Command, err error) { + inv.Stdout = stdout + fs := flag.FlagSet{} + fs.SetOutput(stdout) + + // options flags + + fs.BoolVar(&inv.Force, "f", false, "force recreation of compiled magefile") + fs.BoolVar(&inv.Debug, "debug", mg.Debug(), "turn on debug messages") + fs.BoolVar(&inv.Verbose, "v", mg.Verbose(), "show verbose output when running mage targets") + fs.BoolVar(&inv.Help, "h", false, "show this help") + fs.DurationVar(&inv.Timeout, "t", 0, "timeout in duration parsable format (e.g. 5m30s)") + fs.BoolVar(&inv.Keep, "keep", false, "keep intermediate mage files around after running") + fs.StringVar(&inv.Dir, "d", ".", "run magefiles in the given directory") + fs.StringVar(&inv.GoCmd, "gocmd", mg.GoCmd(), "use the given go binary to compile the output") + fs.StringVar(&inv.GOOS, "goos", "", "set GOOS for binary produced with -compile") + fs.StringVar(&inv.GOARCH, "goarch", "", "set GOARCH for binary produced with -compile") + + // commands below + + fs.BoolVar(&inv.List, "l", false, "list mage targets in this directory") + var showVersion bool + fs.BoolVar(&showVersion, "version", false, "show version info for the mage binary") + var mageInit bool + fs.BoolVar(&mageInit, "init", false, "create a starting template if no mage files exist") + var clean bool + fs.BoolVar(&clean, "clean", false, "clean out old generated binaries from CACHE_DIR") + var compileOutPath string + fs.StringVar(&compileOutPath, "compile", "", "output a static binary to the given path") + + fs.Usage = func() { + fmt.Fprint(stdout, ` +mage [options] [target] + +Mage is a make-like command runner. See https://magefile.org for full docs. + +Commands: + -clean clean out old generated binaries from CACHE_DIR + -compile + output a static binary to the given path + -init create a starting template if no mage files exist + -l list mage targets in this directory + -h show this help + -version show version info for the mage binary + +Options: + -d + run magefiles in the given directory (default ".") + -debug turn on debug messages + -h show description of a target + -f force recreation of compiled magefile + -keep keep intermediate mage files around after running + -gocmd + use the given go binary to compile the output (default: "go") + -goos sets the GOOS for the binary created by -compile (default: current OS) + -goarch sets the GOARCH for the binary created by -compile (default: current arch) + -t + timeout in duration parsable format (e.g. 5m30s) + -v show verbose output when running mage targets +`[1:]) + } + err = fs.Parse(args) + if err == flag.ErrHelp { + // parse will have already called fs.Usage() + return inv, cmd, err + } + if err == nil && inv.Help && len(fs.Args()) == 0 { + fs.Usage() + // tell upstream, to just exit + return inv, cmd, flag.ErrHelp + } + + numCommands := 0 + switch { + case mageInit: + numCommands++ + cmd = Init + case compileOutPath != "": + numCommands++ + cmd = CompileStatic + inv.CompileOut = compileOutPath + inv.Force = true + case showVersion: + numCommands++ + cmd = Version + case clean: + numCommands++ + cmd = Clean + if fs.NArg() > 0 { + // Temporary dupe of below check until we refactor the other commands to use this check + return inv, cmd, errors.New("-h, -init, -clean, -compile and -version cannot be used simultaneously") + + } + } + if inv.Help { + numCommands++ + } + + if inv.Debug { + debug.SetOutput(stderr) + } + + inv.CacheDir = mg.CacheDir() + + if numCommands > 1 { + debug.Printf("%d commands defined", numCommands) + return inv, cmd, errors.New("-h, -init, -clean, -compile and -version cannot be used simultaneously") + } + + if cmd != CompileStatic && (inv.GOARCH != "" || inv.GOOS != "") { + return inv, cmd, errors.New("-goos and -goarch only apply when running with -compile") + } + + inv.Args = fs.Args() + if inv.Help && len(inv.Args) > 1 { + return inv, cmd, errors.New("-h can only show help for a single target") + } + + if len(inv.Args) > 0 && cmd != None { + return inv, cmd, fmt.Errorf("unexpected arguments to command: %q", inv.Args) + } + inv.HashFast = mg.HashFast() + return inv, cmd, err +} + +// Invoke runs Mage with the given arguments. +func Invoke(inv Invocation) int { + errlog := log.New(inv.Stderr, "", 0) + if inv.GoCmd == "" { + inv.GoCmd = "go" + } + if inv.Dir == "" { + inv.Dir = "." + } + if inv.CacheDir == "" { + inv.CacheDir = mg.CacheDir() + } + + files, err := Magefiles(inv.Dir, inv.GOOS, inv.GOARCH, inv.GoCmd, inv.Stderr, inv.Debug) + if err != nil { + errlog.Println("Error determining list of magefiles:", err) + return 1 + } + + if len(files) == 0 { + errlog.Println("No .go files marked with the mage build tag in this directory.") + return 1 + } + debug.Printf("found magefiles: %s", strings.Join(files, ", ")) + exePath := inv.CompileOut + if inv.CompileOut == "" { + exePath, err = ExeName(inv.GoCmd, inv.CacheDir, files) + if err != nil { + errlog.Println("Error getting exe name:", err) + return 1 + } + } + debug.Println("output exe is ", exePath) + + useCache := false + if inv.HashFast { + debug.Println("user has set MAGEFILE_HASHFAST, so we'll ignore GOCACHE") + } else { + s, err := internal.OutputDebug(inv.GoCmd, "env", "GOCACHE") + if err != nil { + errlog.Printf("failed to run %s env GOCACHE: %s", inv.GoCmd, err) + return 1 + } + + // if GOCACHE exists, always rebuild, so we catch transitive + // dependencies that have changed. + if s != "" { + debug.Println("go build cache exists, will ignore any compiled binary") + useCache = true + } + } + + if !useCache { + _, err = os.Stat(exePath) + switch { + case err == nil: + if inv.Force { + debug.Println("ignoring existing executable") + } else { + debug.Println("Running existing exe") + return RunCompiled(inv, exePath, errlog) + } + case os.IsNotExist(err): + debug.Println("no existing exe, creating new") + default: + debug.Printf("error reading existing exe at %v: %v", exePath, err) + debug.Println("creating new exe") + } + } + + // parse wants dir + filenames... arg + fnames := make([]string, 0, len(files)) + for i := range files { + fnames = append(fnames, filepath.Base(files[i])) + } + if inv.Debug { + parse.EnableDebug() + } + debug.Println("parsing files") + info, err := parse.PrimaryPackage(inv.GoCmd, inv.Dir, fnames) + if err != nil { + errlog.Println("Error parsing magefiles:", err) + return 1 + } + + main := filepath.Join(inv.Dir, mainfile) + binaryName := "mage" + if inv.CompileOut != "" { + binaryName = filepath.Base(inv.CompileOut) + } + + err = GenerateMainfile(binaryName, main, info) + if err != nil { + errlog.Println("Error:", err) + return 1 + } + if !inv.Keep { + defer os.RemoveAll(main) + } + files = append(files, main) + if err := Compile(inv.GOOS, inv.GOARCH, inv.Dir, inv.GoCmd, exePath, files, inv.Debug, inv.Stderr, inv.Stdout); err != nil { + errlog.Println("Error:", err) + return 1 + } + if !inv.Keep { + // move aside this file before we run the compiled version, in case the + // compiled file screws things up. Yes this doubles up with the above + // defer, that's ok. + os.RemoveAll(main) + } else { + debug.Print("keeping mainfile") + } + + if inv.CompileOut != "" { + return 0 + } + + return RunCompiled(inv, exePath, errlog) +} + +type mainfileTemplateData struct { + Description string + Funcs []*parse.Function + DefaultFunc parse.Function + Aliases map[string]*parse.Function + Imports []*parse.Import + BinaryName string +} + +// Magefiles returns the list of magefiles in dir. +func Magefiles(magePath, goos, goarch, goCmd string, stderr io.Writer, isDebug bool) ([]string, error) { + start := time.Now() + defer func() { + debug.Println("time to scan for Magefiles:", time.Since(start)) + }() + fail := func(err error) ([]string, error) { + return nil, err + } + + env, err := internal.EnvWithGOOS(goos, goarch) + if err != nil { + return nil, err + } + + debug.Println("getting all non-mage files in", magePath) + + // // first, grab all the files with no build tags specified.. this is actually + // // our exclude list of things without the mage build tag. + cmd := exec.Command(goCmd, "list", "-e", "-f", `{{join .GoFiles "||"}}`) + cmd.Env = env + buf := &bytes.Buffer{} + cmd.Stderr = buf + cmd.Dir = magePath + b, err := cmd.Output() + if err != nil { + stderr := buf.String() + // if the error is "cannot find module", that can mean that there's no + // non-mage files, which is fine, so ignore it. + if !strings.Contains(stderr, "cannot find module for path") { + return fail(fmt.Errorf("failed to list non-mage gofiles: %v: %s", err, stderr)) + } + } + list := strings.TrimSpace(string(b)) + debug.Println("found non-mage files", list) + exclude := map[string]bool{} + for _, f := range strings.Split(list, "||") { + if f != "" { + debug.Printf("marked file as non-mage: %q", f) + exclude[f] = true + } + } + debug.Println("getting all files plus mage files") + cmd = exec.Command(goCmd, "list", "-tags=mage", "-e", "-f", `{{join .GoFiles "||"}}`) + cmd.Env = env + + buf.Reset() + cmd.Dir = magePath + b, err = cmd.Output() + if err != nil { + return fail(fmt.Errorf("failed to list mage gofiles: %v: %s", err, buf.Bytes())) + } + + list = strings.TrimSpace(string(b)) + files := []string{} + for _, f := range strings.Split(list, "||") { + if f != "" && !exclude[f] { + files = append(files, f) + } + } + for i := range files { + files[i] = filepath.Join(magePath, files[i]) + } + return files, nil +} + +// Compile uses the go tool to compile the files into an executable at path. +func Compile(goos, goarch, magePath, goCmd, compileTo string, gofiles []string, isDebug bool, stderr, stdout io.Writer) error { + debug.Println("compiling to", compileTo) + debug.Println("compiling using gocmd:", goCmd) + if isDebug { + internal.RunDebug(goCmd, "version") + internal.RunDebug(goCmd, "env") + } + environ, err := internal.EnvWithGOOS(goos, goarch) + if err != nil { + return err + } + // strip off the path since we're setting the path in the build command + for i := range gofiles { + gofiles[i] = filepath.Base(gofiles[i]) + } + debug.Printf("running %s build -o %s %s", goCmd, compileTo, strings.Join(gofiles, " ")) + c := exec.Command(goCmd, append([]string{"build", "-o", compileTo}, gofiles...)...) + c.Env = environ + c.Stderr = stderr + c.Stdout = stdout + c.Dir = magePath + start := time.Now() + err = c.Run() + debug.Println("time to compile Magefile:", time.Since(start)) + if err != nil { + return errors.New("error compiling magefiles") + } + return nil +} + +// GenerateMainfile generates the mage mainfile at path. +func GenerateMainfile(binaryName, path string, info *parse.PkgInfo) error { + debug.Println("Creating mainfile at", path) + + f, err := os.Create(path) + if err != nil { + return fmt.Errorf("error creating generated mainfile: %v", err) + } + defer f.Close() + data := mainfileTemplateData{ + Description: info.Description, + Funcs: info.Funcs, + Aliases: info.Aliases, + Imports: info.Imports, + BinaryName: binaryName, + } + + if info.DefaultFunc != nil { + data.DefaultFunc = *info.DefaultFunc + } + + debug.Println("writing new file at", path) + if err := mainfileTemplate.Execute(f, data); err != nil { + return fmt.Errorf("can't execute mainfile template: %v", err) + } + if err := f.Close(); err != nil { + return fmt.Errorf("error closing generated mainfile: %v", err) + } + // we set an old modtime on the generated mainfile so that the go tool + // won't think it has changed more recently than the compiled binary. + longAgo := time.Now().Add(-time.Hour * 24 * 365 * 10) + if err := os.Chtimes(path, longAgo, longAgo); err != nil { + return fmt.Errorf("error setting old modtime on generated mainfile: %v", err) + } + return nil +} + +// ExeName reports the executable filename that this version of Mage would +// create for the given magefiles. +func ExeName(goCmd, cacheDir string, files []string) (string, error) { + var hashes []string + for _, s := range files { + h, err := hashFile(s) + if err != nil { + return "", err + } + hashes = append(hashes, h) + } + // hash the mainfile template to ensure if it gets updated, we make a new + // binary. + hashes = append(hashes, fmt.Sprintf("%x", sha1.Sum([]byte(mageMainfileTplString)))) + sort.Strings(hashes) + ver, err := internal.OutputDebug(goCmd, "version") + if err != nil { + return "", err + } + hash := sha1.Sum([]byte(strings.Join(hashes, "") + magicRebuildKey + ver)) + filename := fmt.Sprintf("%x", hash) + + out := filepath.Join(cacheDir, filename) + if runtime.GOOS == "windows" { + out += ".exe" + } + return out, nil +} + +func hashFile(fn string) (string, error) { + f, err := os.Open(fn) + if err != nil { + return "", fmt.Errorf("can't open input file for hashing: %#v", err) + } + defer f.Close() + + h := sha1.New() + if _, err := io.Copy(h, f); err != nil { + return "", fmt.Errorf("can't write data to hash: %v", err) + } + return fmt.Sprintf("%x", h.Sum(nil)), nil +} + +func generateInit(dir string) error { + debug.Println("generating default magefile in", dir) + f, err := os.Create(filepath.Join(dir, initFile)) + if err != nil { + return fmt.Errorf("could not create mage template: %v", err) + } + defer f.Close() + + if err := initOutput.Execute(f, nil); err != nil { + return fmt.Errorf("can't execute magefile template: %v", err) + } + + return nil +} + +// RunCompiled runs an already-compiled mage command with the given args, +func RunCompiled(inv Invocation, exePath string, errlog *log.Logger) int { + debug.Println("running binary", exePath) + c := exec.Command(exePath, inv.Args...) + c.Stderr = inv.Stderr + c.Stdout = inv.Stdout + c.Stdin = inv.Stdin + c.Dir = inv.Dir + // intentionally pass through unaltered os.Environ here.. your magefile has + // to deal with it. + c.Env = os.Environ() + if inv.Verbose { + c.Env = append(c.Env, "MAGEFILE_VERBOSE=1") + } + if inv.List { + c.Env = append(c.Env, "MAGEFILE_LIST=1") + } + if inv.Help { + c.Env = append(c.Env, "MAGEFILE_HELP=1") + } + if inv.Debug { + c.Env = append(c.Env, "MAGEFILE_DEBUG=1") + } + if inv.GoCmd != "" { + c.Env = append(c.Env, fmt.Sprintf("MAGEFILE_GOCMD=%s", inv.GoCmd)) + } + if inv.Timeout > 0 { + c.Env = append(c.Env, fmt.Sprintf("MAGEFILE_TIMEOUT=%s", inv.Timeout.String())) + } + debug.Print("running magefile with mage vars:\n", strings.Join(filter(c.Env, "MAGEFILE"), "\n")) + err := c.Run() + if !sh.CmdRan(err) { + errlog.Printf("failed to run compiled magefile: %v", err) + } + return sh.ExitStatus(err) +} + +func filter(list []string, prefix string) []string { + var out []string + for _, s := range list { + if strings.HasPrefix(s, prefix) { + out = append(out, s) + } + } + return out +} + +// removeContents removes all files but not any subdirectories in the given +// directory. +func removeContents(dir string) error { + debug.Println("removing all files in", dir) + files, err := ioutil.ReadDir(dir) + if err != nil { + if os.IsNotExist(err) { + return nil + } + return err + } + for _, f := range files { + if f.IsDir() { + continue + } + err = os.Remove(filepath.Join(dir, f.Name())) + if err != nil { + return err + } + } + return nil + +} diff --git a/vendor/github.com/magefile/mage/mage/template.go b/vendor/github.com/magefile/mage/mage/template.go new file mode 100644 index 000000000000..dc943fd86122 --- /dev/null +++ b/vendor/github.com/magefile/mage/mage/template.go @@ -0,0 +1,318 @@ +package mage + +// this template uses the "data" + +// var only for tests +var mageMainfileTplString = `// +build ignore + +package main + +import ( + "context" + "flag" + "fmt" + "io/ioutil" + "log" + "os" + "path/filepath" + "sort" + "strconv" + "strings" + "text/tabwriter" + "time" + {{range .Imports}}{{.UniqueName}} "{{.Path}}" + {{end}} +) + +func main() { + // Use local types and functions in order to avoid name conflicts with additional magefiles. + type arguments struct { + Verbose bool // print out log statements + List bool // print out a list of targets + Help bool // print out help for a specific target + Timeout time.Duration // set a timeout to running the targets + Args []string // args contain the non-flag command-line arguments + } + + parseBool := func(env string) bool { + val := os.Getenv(env) + if val == "" { + return false + } + b, err := strconv.ParseBool(val) + if err != nil { + log.Printf("warning: environment variable %s is not a valid bool value: %v", env, val) + return false + } + return b + } + + parseDuration := func(env string) time.Duration { + val := os.Getenv(env) + if val == "" { + return 0 + } + d, err := time.ParseDuration(val) + if err != nil { + log.Printf("warning: environment variable %s is not a valid duration value: %v", env, val) + return 0 + } + return d + } + args := arguments{} + fs := flag.FlagSet{} + fs.SetOutput(os.Stdout) + + // default flag set with ExitOnError and auto generated PrintDefaults should be sufficient + fs.BoolVar(&args.Verbose, "v", parseBool("MAGEFILE_VERBOSE"), "show verbose output when running targets") + fs.BoolVar(&args.List, "l", parseBool("MAGEFILE_LIST"), "list targets for this binary") + fs.BoolVar(&args.Help, "h", parseBool("MAGEFILE_HELP"), "print out help for a specific target") + fs.DurationVar(&args.Timeout, "t", parseDuration("MAGEFILE_TIMEOUT"), "timeout in duration parsable format (e.g. 5m30s)") + fs.Usage = func() { + fmt.Fprintf(os.Stdout, ` + "`" + ` +%s [options] [target] + +Commands: + -l list targets in this binary + -h show this help + +Options: + -h show description of a target + -t + timeout in duration parsable format (e.g. 5m30s) + -v show verbose output when running targets + ` + "`" + `[1:], filepath.Base(os.Args[0])) + } + if err := fs.Parse(os.Args[1:]); err != nil { + // flag will have printed out an error already. + return + } + args.Args = fs.Args() + if args.Help && len(args.Args) == 0 { + fs.Usage() + return + } + + list := func() error { + {{with .Description}}fmt.Println(` + "`{{.}}\n`" + `) + {{- end}} + {{- $default := .DefaultFunc}} + targets := map[string]string{ + {{- range .Funcs}} + "{{lowerFirst .TargetName}}{{if and (eq .Name $default.Name) (eq .Receiver $default.Receiver)}}*{{end}}": {{printf "%q" .Synopsis}}, + {{- end}} + {{- range .Imports}}{{$imp := .}} + {{- range .Info.Funcs}} + "{{lowerFirst .TargetName}}{{if and (eq .Name $default.Name) (eq .Receiver $default.Receiver)}}*{{end}}": {{printf "%q" .Synopsis}}, + {{- end}} + {{- end}} + } + + keys := make([]string, 0, len(targets)) + for name := range targets { + keys = append(keys, name) + } + sort.Strings(keys) + + fmt.Println("Targets:") + w := tabwriter.NewWriter(os.Stdout, 0, 4, 4, ' ', 0) + for _, name := range keys { + fmt.Fprintf(w, " %v\t%v\n", name, targets[name]) + } + err := w.Flush() + {{- if .DefaultFunc.Name}} + if err == nil { + fmt.Println("\n* default target") + } + {{- end}} + return err + } + + var ctx context.Context + var ctxCancel func() + + getContext := func() (context.Context, func()) { + if ctx != nil { + return ctx, ctxCancel + } + + if args.Timeout != 0 { + ctx, ctxCancel = context.WithTimeout(context.Background(), args.Timeout) + } else { + ctx = context.Background() + ctxCancel = func() {} + } + return ctx, ctxCancel + } + + runTarget := func(fn func(context.Context) error) interface{} { + var err interface{} + ctx, cancel := getContext() + d := make(chan interface{}) + go func() { + defer func() { + err := recover() + d <- err + }() + err := fn(ctx) + d <- err + }() + select { + case <-ctx.Done(): + cancel() + e := ctx.Err() + fmt.Printf("ctx err: %v\n", e) + return e + case err = <-d: + cancel() + return err + } + } + // This is necessary in case there aren't any targets, to avoid an unused + // variable error. + _ = runTarget + + handleError := func(logger *log.Logger, err interface{}) { + if err != nil { + logger.Printf("Error: %v\n", err) + type code interface { + ExitStatus() int + } + if c, ok := err.(code); ok { + os.Exit(c.ExitStatus()) + } + os.Exit(1) + } + } + _ = handleError + + log.SetFlags(0) + if !args.Verbose { + log.SetOutput(ioutil.Discard) + } + logger := log.New(os.Stderr, "", 0) + if args.List { + if err := list(); err != nil { + log.Println(err) + os.Exit(1) + } + return + } + + targets := map[string]bool { + {{range $alias, $funci := .Aliases}}"{{lower $alias}}": true, + {{end}} + {{range .Funcs}}"{{lower .TargetName}}": true, + {{end}} + {{range .Imports}} + {{$imp := .}} + {{range $alias, $funci := .Info.Aliases}}"{{if ne $imp.Alias "."}}{{lower $imp.Alias}}:{{end}}{{lower $alias}}": true, + {{end}} + {{range .Info.Funcs}}"{{lower .TargetName}}": true, + {{end}} + {{end}} + } + + var unknown []string + for _, arg := range args.Args { + if !targets[strings.ToLower(arg)] { + unknown = append(unknown, arg) + } + } + if len(unknown) == 1 { + logger.Println("Unknown target specified:", unknown[0]) + os.Exit(2) + } + if len(unknown) > 1 { + logger.Println("Unknown targets specified:", strings.Join(unknown, ", ")) + os.Exit(2) + } + + if args.Help { + if len(args.Args) < 1 { + logger.Println("no target specified") + os.Exit(1) + } + switch strings.ToLower(args.Args[0]) { + {{range .Funcs}}case "{{lower .TargetName}}": + fmt.Print("{{$.BinaryName}} {{lower .TargetName}}:\n\n") + {{if ne .Comment "" -}} + fmt.Println({{printf "%q" .Comment}}) + fmt.Println() + {{end}} + var aliases []string + {{- $name := .Name -}} + {{- $recv := .Receiver -}} + {{range $alias, $func := $.Aliases}} + {{if and (eq $name $func.Name) (eq $recv $func.Receiver)}}aliases = append(aliases, "{{$alias}}"){{end -}} + {{- end}} + if len(aliases) > 0 { + fmt.Printf("Aliases: %s\n\n", strings.Join(aliases, ", ")) + } + return + {{end}} + default: + logger.Printf("Unknown target: %q\n", args.Args[0]) + os.Exit(1) + } + } + if len(args.Args) < 1 { + {{- if .DefaultFunc.Name}} + ignoreDefault, _ := strconv.ParseBool(os.Getenv("MAGEFILE_IGNOREDEFAULT")) + if ignoreDefault { + if err := list(); err != nil { + logger.Println("Error:", err) + os.Exit(1) + } + return + } + {{.DefaultFunc.ExecCode}} + handleError(logger, err) + return + {{- else}} + if err := list(); err != nil { + logger.Println("Error:", err) + os.Exit(1) + } + return + {{- end}} + } + for _, target := range args.Args { + switch strings.ToLower(target) { + {{range $alias, $func := .Aliases}} + case "{{lower $alias}}": + target = "{{$func.TargetName}}" + {{- end}} + } + switch strings.ToLower(target) { + {{range .Funcs }} + case "{{lower .TargetName}}": + if args.Verbose { + logger.Println("Running target:", "{{.TargetName}}") + } + {{.ExecCode}} + handleError(logger, err) + {{- end}} + {{range .Imports}} + {{$imp := .}} + {{range .Info.Funcs }} + case "{{lower .TargetName}}": + if args.Verbose { + logger.Println("Running target:", "{{.TargetName}}") + } + {{.ExecCode}} + handleError(logger, err) + {{- end}} + {{- end}} + default: + // should be impossible since we check this above. + logger.Printf("Unknown target: %q\n", args.Args[0]) + os.Exit(1) + } + } +} + + + + +` diff --git a/vendor/github.com/magefile/mage/magefile.go b/vendor/github.com/magefile/mage/magefile.go new file mode 100644 index 000000000000..0f2f12130153 --- /dev/null +++ b/vendor/github.com/magefile/mage/magefile.go @@ -0,0 +1,108 @@ +//+build mage + +// This is the build script for Mage. The install target is all you really need. +// The release target is for generating official releases and is really only +// useful to project admins. +package main + +import ( + "errors" + "fmt" + "os" + "path/filepath" + "regexp" + "runtime" + "strings" + "time" + + "github.com/magefile/mage/mg" + "github.com/magefile/mage/sh" +) + +// Runs "go install" for mage. This generates the version info the binary. +func Install() error { + name := "mage" + if runtime.GOOS == "windows" { + name += ".exe" + } + + gocmd := mg.GoCmd() + // use GOBIN if set in the environment, otherwise fall back to first path + // in GOPATH environment string + bin, err := sh.Output(gocmd, "env", "GOBIN") + if err != nil { + return fmt.Errorf("can't determine GOBIN: %v", err) + } + if bin == "" { + gopath, err := sh.Output(gocmd, "env", "GOPATH") + if err != nil { + return fmt.Errorf("can't determine GOPATH: %v", err) + } + paths := strings.Split(gopath, string([]rune{os.PathListSeparator})) + bin = filepath.Join(paths[0], "bin") + } + // specifically don't mkdirall, if you have an invalid gopath in the first + // place, that's not on us to fix. + if err := os.Mkdir(bin, 0700); err != nil && !os.IsExist(err) { + return fmt.Errorf("failed to create %q: %v", bin, err) + } + path := filepath.Join(bin, name) + + // we use go build here because if someone built with go get, then `go + // install` turns into a no-op, and `go install -a` fails on people's + // machines that have go installed in a non-writeable directory (such as + // normal OS installs in /usr/bin) + return sh.RunV(gocmd, "build", "-o", path, "-ldflags="+flags(), "github.com/magefile/mage") +} + +var releaseTag = regexp.MustCompile(`^v1\.[0-9]+\.[0-9]+$`) + +// Generates a new release. Expects the TAG environment variable to be set, +// which will create a new tag with that name. +func Release() (err error) { + tag := os.Getenv("TAG") + if !releaseTag.MatchString(tag) { + return errors.New("TAG environment variable must be in semver v1.x.x format, but was " + tag) + } + + if err := sh.RunV("git", "tag", "-a", tag, "-m", tag); err != nil { + return err + } + if err := sh.RunV("git", "push", "origin", tag); err != nil { + return err + } + defer func() { + if err != nil { + sh.RunV("git", "tag", "--delete", "$TAG") + sh.RunV("git", "push", "--delete", "origin", "$TAG") + } + }() + return sh.RunV("goreleaser") +} + +// Remove the temporarily generated files from Release. +func Clean() error { + return sh.Rm("dist") +} + +func flags() string { + timestamp := time.Now().Format(time.RFC3339) + hash := hash() + tag := tag() + if tag == "" { + tag = "dev" + } + return fmt.Sprintf(`-X "github.com/magefile/mage/mage.timestamp=%s" -X "github.com/magefile/mage/mage.commitHash=%s" -X "github.com/magefile/mage/mage.gitTag=%s"`, timestamp, hash, tag) +} + +// tag returns the git tag for the current branch or "" if none. +func tag() string { + s, _ := sh.Output("git", "describe", "--tags") + return s +} + +// hash returns the git hash for the current repo or "" if none. +func hash() string { + hash, _ := sh.Output("git", "rev-parse", "--short", "HEAD") + return hash +} diff --git a/vendor/github.com/magefile/mage/main.go b/vendor/github.com/magefile/mage/main.go new file mode 100644 index 000000000000..d596ac7f0673 --- /dev/null +++ b/vendor/github.com/magefile/mage/main.go @@ -0,0 +1,11 @@ +package main + +import ( + "os" + + "github.com/magefile/mage/mage" +) + +func main() { + os.Exit(mage.Main()) +} diff --git a/vendor/github.com/magefile/mage/parse/parse.go b/vendor/github.com/magefile/mage/parse/parse.go new file mode 100644 index 000000000000..ebe1775fa7e3 --- /dev/null +++ b/vendor/github.com/magefile/mage/parse/parse.go @@ -0,0 +1,751 @@ +package parse + +import ( + "errors" + "fmt" + "go/ast" + "go/doc" + "go/parser" + "go/token" + "io/ioutil" + "log" + "os" + "strings" + "time" + + "github.com/magefile/mage/internal" +) + +const importTag = "mage:import" + +var debug = log.New(ioutil.Discard, "DEBUG: ", log.Ltime|log.Lmicroseconds) + +// EnableDebug turns on debug logging. +func EnableDebug() { + debug.SetOutput(os.Stderr) +} + +// PkgInfo contains inforamtion about a package of files according to mage's +// parsing rules. +type PkgInfo struct { + AstPkg *ast.Package + DocPkg *doc.Package + Description string + Funcs []*Function + DefaultFunc *Function + Aliases map[string]*Function + Imports []*Import +} + +// Function represented a job function from a mage file +type Function struct { + PkgAlias string + Package string + ImportPath string + Name string + Receiver string + IsError bool + IsContext bool + Synopsis string + Comment string +} + +// ID returns user-readable information about where this function is defined. +func (f Function) ID() string { + path := "" + if f.ImportPath != "" { + path = f.ImportPath + } + receiver := "" + if f.Receiver != "" { + receiver = f.Receiver + "." + } + return fmt.Sprintf("%s.%s%s", path, receiver, f.Name) +} + +// TargetName returns the name of the target as it should appear when used from +// the mage cli. It is always lowercase. +func (f Function) TargetName() string { + var names []string + + for _, s := range []string{f.PkgAlias, f.Receiver, f.Name} { + if s != "" { + names = append(names, s) + } + } + return strings.Join(names, ":") +} + +// ExecCode returns code for the template switch to run the target. +// It wraps each target call to match the func(context.Context) error that +// runTarget requires. +func (f Function) ExecCode() (string, error) { + name := f.Name + if f.Receiver != "" { + name = f.Receiver + "{}." + name + } + if f.Package != "" { + name = f.Package + "." + name + } + + if f.IsContext && f.IsError { + out := ` + wrapFn := func(ctx context.Context) error { + return %s(ctx) + } + err := runTarget(wrapFn)`[1:] + return fmt.Sprintf(out, name), nil + } + if f.IsContext && !f.IsError { + out := ` + wrapFn := func(ctx context.Context) error { + %s(ctx) + return nil + } + err := runTarget(wrapFn)`[1:] + return fmt.Sprintf(out, name), nil + } + if !f.IsContext && f.IsError { + out := ` + wrapFn := func(ctx context.Context) error { + return %s() + } + err := runTarget(wrapFn)`[1:] + return fmt.Sprintf(out, name), nil + } + if !f.IsContext && !f.IsError { + out := ` + wrapFn := func(ctx context.Context) error { + %s() + return nil + } + err := runTarget(wrapFn)`[1:] + return fmt.Sprintf(out, name), nil + } + return "", fmt.Errorf("Error formatting ExecCode code for %#v", f) +} + +// PrimaryPackage parses a package. If files is non-empty, it will only parse the files given. +func PrimaryPackage(gocmd, path string, files []string) (*PkgInfo, error) { + info, err := Package(path, files) + if err != nil { + return nil, err + } + + if err := setImports(gocmd, info); err != nil { + return nil, err + } + + setDefault(info) + setAliases(info) + return info, nil +} + +func checkDupes(info *PkgInfo, imports []*Import) error { + funcs := map[string][]*Function{} + for _, f := range info.Funcs { + funcs[strings.ToLower(f.TargetName())] = append(funcs[strings.ToLower(f.TargetName())], f) + } + for _, imp := range imports { + for _, f := range imp.Info.Funcs { + target := strings.ToLower(f.TargetName()) + funcs[target] = append(funcs[target], f) + } + } + for alias, f := range info.Aliases { + if len(funcs[alias]) != 0 { + var ids []string + for _, f := range funcs[alias] { + ids = append(ids, f.ID()) + } + return fmt.Errorf("alias %q duplicates existing target(s): %s\n", alias, strings.Join(ids, ", ")) + } + funcs[alias] = append(funcs[alias], f) + } + var dupes []string + for target, list := range funcs { + if len(list) > 1 { + dupes = append(dupes, target) + } + } + if len(dupes) == 0 { + return nil + } + errs := make([]string, 0, len(dupes)) + for _, d := range dupes { + var ids []string + for _, f := range funcs[d] { + ids = append(ids, f.ID()) + } + errs = append(errs, fmt.Sprintf("%q target has multiple definitions: %s\n", d, strings.Join(ids, ", "))) + } + return errors.New(strings.Join(errs, "\n")) +} + +// Package compiles information about a mage package. +func Package(path string, files []string) (*PkgInfo, error) { + start := time.Now() + defer func() { + debug.Println("time parse Magefiles:", time.Since(start)) + }() + fset := token.NewFileSet() + pkg, err := getPackage(path, files, fset) + if err != nil { + return nil, err + } + p := doc.New(pkg, "./", 0) + pi := &PkgInfo{ + AstPkg: pkg, + DocPkg: p, + Description: toOneLine(p.Doc), + } + + setNamespaces(pi) + setFuncs(pi) + + hasDupes, names := checkDupeTargets(pi) + if hasDupes { + msg := "Build targets must be case insensitive, thus the following targets conflict:\n" + for _, v := range names { + if len(v) > 1 { + msg += " " + strings.Join(v, ", ") + "\n" + } + } + return nil, errors.New(msg) + } + + return pi, nil +} + +func getNamedImports(gocmd string, pkgs map[string]string) ([]*Import, error) { + var imports []*Import + for alias, pkg := range pkgs { + debug.Printf("getting import package %q, alias %q", pkg, alias) + imp, err := getImport(gocmd, pkg, alias) + if err != nil { + return nil, err + } + imports = append(imports, imp) + } + return imports, nil +} + +func getImport(gocmd, importpath, alias string) (*Import, error) { + out, err := internal.OutputDebug(gocmd, "list", "-f", "{{.Dir}}||{{.Name}}", importpath) + if err != nil { + return nil, err + } + parts := strings.Split(out, "||") + if len(parts) != 2 { + return nil, fmt.Errorf("incorrect data from go list: %s", out) + } + dir, name := parts[0], parts[1] + debug.Printf("parsing imported package %q from dir %q", importpath, dir) + info, err := Package(dir, nil) + if err != nil { + return nil, err + } + for i := range info.Funcs { + debug.Printf("setting alias %q and package %q on func %v", alias, name, info.Funcs[i].Name) + info.Funcs[i].PkgAlias = alias + info.Funcs[i].ImportPath = importpath + } + return &Import{Alias: alias, Name: name, Path: importpath, Info: *info}, nil +} + +type Import struct { + Alias string + Name string + UniqueName string // a name unique across all imports + Path string + Info PkgInfo +} + +func setFuncs(pi *PkgInfo) { + for _, f := range pi.DocPkg.Funcs { + if f.Recv != "" { + debug.Printf("skipping method %s.%s", f.Recv, f.Name) + // skip methods + continue + } + if !ast.IsExported(f.Name) { + debug.Printf("skipping non-exported function %s", f.Name) + // skip non-exported functions + continue + } + if typ := funcType(f.Decl.Type); typ != invalidType { + debug.Printf("found target %v", f.Name) + pi.Funcs = append(pi.Funcs, &Function{ + Name: f.Name, + Comment: toOneLine(f.Doc), + Synopsis: sanitizeSynopsis(f), + IsError: typ == errorType || typ == contextErrorType, + IsContext: typ == contextVoidType || typ == contextErrorType, + }) + } else { + debug.Printf("skipping function with invalid signature func %s(%v)(%v)", f.Name, fieldNames(f.Decl.Type.Params), fieldNames(f.Decl.Type.Results)) + } + } +} + +func setNamespaces(pi *PkgInfo) { + for _, t := range pi.DocPkg.Types { + if !isNamespace(t) { + continue + } + debug.Printf("found namespace %s %s", pi.DocPkg.ImportPath, t.Name) + for _, f := range t.Methods { + if !ast.IsExported(f.Name) { + continue + } + typ := funcType(f.Decl.Type) + if typ == invalidType { + continue + } + debug.Printf("found namespace method %s %s.%s", pi.DocPkg.ImportPath, t.Name, f.Name) + pi.Funcs = append(pi.Funcs, &Function{ + Name: f.Name, + Receiver: t.Name, + Comment: toOneLine(f.Doc), + Synopsis: sanitizeSynopsis(f), + IsError: typ == errorType || typ == contextErrorType, + IsContext: typ == contextVoidType || typ == contextErrorType, + }) + } + } +} + +func setImports(gocmd string, pi *PkgInfo) error { + importNames := map[string]string{} + rootImports := []string{} + for _, f := range pi.AstPkg.Files { + for _, d := range f.Decls { + gen, ok := d.(*ast.GenDecl) + if !ok || gen.Tok != token.IMPORT { + continue + } + for j := 0; j < len(gen.Specs); j++ { + spec := gen.Specs[j] + impspec := spec.(*ast.ImportSpec) + if len(gen.Specs) == 1 && gen.Lparen == token.NoPos && impspec.Doc == nil { + impspec.Doc = gen.Doc + } + name, alias, ok := getImportPath(impspec) + if !ok { + continue + } + if alias != "" { + debug.Printf("found %s: %s (%s)", importTag, name, alias) + if importNames[alias] != "" { + return fmt.Errorf("duplicate import alias: %q", alias) + } + importNames[alias] = name + } else { + debug.Printf("found %s: %s", importTag, name) + rootImports = append(rootImports, name) + } + } + } + } + imports, err := getNamedImports(gocmd, importNames) + if err != nil { + return err + } + for _, s := range rootImports { + imp, err := getImport(gocmd, s, "") + if err != nil { + return err + } + imports = append(imports, imp) + } + if err := checkDupes(pi, imports); err != nil { + return err + } + + // have to set unique package names on imports + used := map[string]bool{} + for _, imp := range imports { + unique := imp.Name + "_mageimport" + x := 1 + for used[unique] { + unique = fmt.Sprintf("%s_mageimport%d", imp.Name, x) + x++ + } + used[unique] = true + imp.UniqueName = unique + for _, f := range imp.Info.Funcs { + f.Package = unique + } + } + pi.Imports = imports + return nil +} + +func getImportPath(imp *ast.ImportSpec) (path, alias string, ok bool) { + if imp.Doc == nil || len(imp.Doc.List) == 9 { + return "", "", false + } + // import is always the last comment + s := imp.Doc.List[len(imp.Doc.List)-1].Text + + // trim comment start and normalize for anyone who has spaces or not between + // "//"" and the text + vals := strings.Fields(strings.ToLower(s[2:])) + if len(vals) == 0 { + return "", "", false + } + if vals[0] != importTag { + return "", "", false + } + path, ok = lit2string(imp.Path) + if !ok { + return "", "", false + } + + switch len(vals) { + case 1: + // just the import tag, this is a root import + return path, "", true + case 2: + // also has an alias + return path, vals[1], true + default: + log.Println("warning: ignoring malformed", importTag, "for import", path) + return "", "", false + } +} + +func isNamespace(t *doc.Type) bool { + if len(t.Decl.Specs) != 1 { + return false + } + id, ok := t.Decl.Specs[0].(*ast.TypeSpec) + if !ok { + return false + } + sel, ok := id.Type.(*ast.SelectorExpr) + if !ok { + return false + } + ident, ok := sel.X.(*ast.Ident) + if !ok { + return false + } + return ident.Name == "mg" && sel.Sel.Name == "Namespace" +} + +func fieldNames(flist *ast.FieldList) string { + if flist == nil { + return "" + } + list := flist.List + if len(list) == 0 { + return "" + } + args := make([]string, 0, len(list)) + for _, f := range list { + names := make([]string, 0, len(f.Names)) + for _, n := range f.Names { + if n.Name != "" { + names = append(names, n.Name) + } + } + nms := strings.Join(names, ", ") + if nms != "" { + nms += " " + } + args = append(args, nms+fmt.Sprint(f.Type)) + } + return strings.Join(args, ", ") +} + +// checkDupeTargets checks a package for duplicate target names. +func checkDupeTargets(info *PkgInfo) (hasDupes bool, names map[string][]string) { + names = map[string][]string{} + lowers := map[string]bool{} + for _, f := range info.Funcs { + low := strings.ToLower(f.Name) + if f.Receiver != "" { + low = strings.ToLower(f.Receiver) + ":" + low + } + if lowers[low] { + hasDupes = true + } + lowers[low] = true + names[low] = append(names[low], f.Name) + } + return hasDupes, names +} + +// sanitizeSynopsis sanitizes function Doc to create a summary. +func sanitizeSynopsis(f *doc.Func) string { + synopsis := doc.Synopsis(f.Doc) + + // If the synopsis begins with the function name, remove it. This is done to + // not repeat the text. + // From: + // clean Clean removes the temporarily generated files + // To: + // clean removes the temporarily generated files + if syns := strings.Split(synopsis, " "); strings.EqualFold(f.Name, syns[0]) { + return strings.Join(syns[1:], " ") + } + + return synopsis +} + +func setDefault(pi *PkgInfo) { + for _, v := range pi.DocPkg.Vars { + for x, name := range v.Names { + if name != "Default" { + continue + } + spec := v.Decl.Specs[x].(*ast.ValueSpec) + if len(spec.Values) != 1 { + log.Println("warning: default declaration has multiple values") + } + + f, err := getFunction(spec.Values[0], pi) + if err != nil { + log.Println("warning, default declaration malformed:", err) + return + } + pi.DefaultFunc = f + return + } + } +} + +func lit2string(l *ast.BasicLit) (string, bool) { + if !strings.HasPrefix(l.Value, `"`) || !strings.HasSuffix(l.Value, `"`) { + return "", false + } + return strings.Trim(l.Value, `"`), true +} + +func setAliases(pi *PkgInfo) { + for _, v := range pi.DocPkg.Vars { + for x, name := range v.Names { + if name != "Aliases" { + continue + } + spec, ok := v.Decl.Specs[x].(*ast.ValueSpec) + if !ok { + log.Println("warning: aliases declaration is not a value") + return + } + if len(spec.Values) != 1 { + log.Println("warning: aliases declaration has multiple values") + } + comp, ok := spec.Values[0].(*ast.CompositeLit) + if !ok { + log.Println("warning: aliases declaration is not a map") + return + } + pi.Aliases = map[string]*Function{} + for _, elem := range comp.Elts { + kv, ok := elem.(*ast.KeyValueExpr) + if !ok { + log.Printf("warning: alias declaration %q is not a map element", elem) + continue + } + k, ok := kv.Key.(*ast.BasicLit) + if !ok || k.Kind != token.STRING { + log.Printf("warning: alias key is not a string literal %q", elem) + continue + } + + alias, ok := lit2string(k) + if !ok { + log.Println("warning: malformed name for alias", elem) + continue + } + f, err := getFunction(kv.Value, pi) + if err != nil { + log.Printf("warning, alias malformed: %v", err) + continue + } + pi.Aliases[alias] = f + } + return + } + } +} + +func getFunction(exp ast.Expr, pi *PkgInfo) (*Function, error) { + + // selector expressions are in LIFO format. + // So, in foo.bar.baz the first selector.Name is + // actually "baz", the second is "bar", and the last is "foo" + + var pkg, receiver, funcname string + switch v := exp.(type) { + case *ast.Ident: + // "foo" : Bar + funcname = v.Name + case *ast.SelectorExpr: + // need to handle + // namespace.Func + // import.Func + // import.namespace.Func + + // "foo" : ?.bar + funcname = v.Sel.Name + switch x := v.X.(type) { + case *ast.Ident: + // "foo" : baz.bar + // this is either a namespace or package + firstname := x.Name + for _, f := range pi.Funcs { + if firstname == f.Receiver && funcname == f.Name { + return f, nil + } + } + // not a namespace, let's try imported packages + for _, imp := range pi.Imports { + if firstname == imp.Name { + for _, f := range imp.Info.Funcs { + if funcname == f.Name { + return f, nil + } + } + break + } + } + return nil, fmt.Errorf("%q is not a known target", exp) + case *ast.SelectorExpr: + // "foo" : bar.Baz.Bat + // must be package.Namespace.Func + sel, ok := v.X.(*ast.SelectorExpr) + if !ok { + return nil, fmt.Errorf("%q is must denote a target function but was %T", exp, v.X) + } + receiver = sel.Sel.Name + id, ok := sel.X.(*ast.Ident) + if !ok { + return nil, fmt.Errorf("%q is must denote a target function but was %T", exp, v.X) + } + pkg = id.Name + default: + return nil, fmt.Errorf("%q is not valid", exp) + } + default: + return nil, fmt.Errorf("target %s is not a function", exp) + } + if pkg == "" { + for _, f := range pi.Funcs { + if f.Name == funcname && f.Receiver == receiver { + return f, nil + } + } + return nil, fmt.Errorf("unknown function %s.%s", receiver, funcname) + } + for _, imp := range pi.Imports { + if imp.Name == pkg { + for _, f := range imp.Info.Funcs { + if f.Name == funcname && f.Receiver == receiver { + return f, nil + } + } + return nil, fmt.Errorf("unknown function %s.%s.%s", pkg, receiver, funcname) + } + } + return nil, fmt.Errorf("unknown package for function %q", exp) +} + +// getPackage returns the non-test package at the given path. +func getPackage(path string, files []string, fset *token.FileSet) (*ast.Package, error) { + var filter func(f os.FileInfo) bool + if len(files) > 0 { + fm := make(map[string]bool, len(files)) + for _, f := range files { + fm[f] = true + } + + filter = func(f os.FileInfo) bool { + return fm[f.Name()] + } + } + + pkgs, err := parser.ParseDir(fset, path, filter, parser.ParseComments) + if err != nil { + return nil, fmt.Errorf("failed to parse directory: %v", err) + } + + for name, pkg := range pkgs { + if !strings.HasSuffix(name, "_test") { + return pkg, nil + } + } + return nil, fmt.Errorf("no non-test packages found in %s", path) +} + +func hasContextParam(ft *ast.FuncType) bool { + if ft.Params.NumFields() != 1 { + return false + } + ret := ft.Params.List[0] + sel, ok := ret.Type.(*ast.SelectorExpr) + if !ok { + return false + } + pkg, ok := sel.X.(*ast.Ident) + if !ok { + return false + } + if pkg.Name != "context" { + return false + } + return sel.Sel.Name == "Context" +} + +func hasVoidReturn(ft *ast.FuncType) bool { + res := ft.Results + return res.NumFields() == 0 +} + +func hasErrorReturn(ft *ast.FuncType) bool { + res := ft.Results + if res.NumFields() != 1 { + return false + } + ret := res.List[0] + if len(ret.Names) > 1 { + return false + } + return fmt.Sprint(ret.Type) == "error" +} + +type functype int + +const ( + invalidType functype = iota + voidType + errorType + contextVoidType + contextErrorType +) + +func funcType(ft *ast.FuncType) functype { + if hasContextParam(ft) { + if hasVoidReturn(ft) { + return contextVoidType + } + if hasErrorReturn(ft) { + return contextErrorType + } + } + if ft.Params.NumFields() == 0 { + if hasVoidReturn(ft) { + return voidType + } + if hasErrorReturn(ft) { + return errorType + } + } + return invalidType +} + +func toOneLine(s string) string { + return strings.TrimSpace(strings.Replace(s, "\n", " ", -1)) +} diff --git a/vendor/github.com/pierrre/gotestcover/.gitignore b/vendor/github.com/pierrre/gotestcover/.gitignore new file mode 100644 index 000000000000..1b3cea9a5a15 --- /dev/null +++ b/vendor/github.com/pierrre/gotestcover/.gitignore @@ -0,0 +1,2 @@ +coverage.txt +coverage.html \ No newline at end of file diff --git a/vendor/github.com/pierrre/gotestcover/.travis.yml b/vendor/github.com/pierrre/gotestcover/.travis.yml new file mode 100644 index 000000000000..36f11f05e0fd --- /dev/null +++ b/vendor/github.com/pierrre/gotestcover/.travis.yml @@ -0,0 +1,23 @@ +language: go + +sudo: false + +go: + - 1.5.3 + - tip + +before_install: + # Redo the travis setup but with the pierre/gotestcover path. This is needed so the package path is correct + - mkdir -p $HOME/gopath/src/github.com/pierrre/gotestcover + - rsync -az ${TRAVIS_BUILD_DIR}/ $HOME/gopath/src/github.com/pierrre/gotestcover + - export TRAVIS_BUILD_DIR=$HOME/gopath/src/github.com/pierrre/gotestcover + - cd $HOME/gopath/src/github.com/pierrre/gotestcover + +install: make setup + +script: + - make check + - make coverage + +after_success: + - bash <(curl -s https://codecov.io/bash) diff --git a/vendor/github.com/pierrre/gotestcover/LICENSE b/vendor/github.com/pierrre/gotestcover/LICENSE new file mode 100644 index 000000000000..210d800c5ebc --- /dev/null +++ b/vendor/github.com/pierrre/gotestcover/LICENSE @@ -0,0 +1,7 @@ +Copyright (C) 2015 Pierre Durand + +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. \ No newline at end of file diff --git a/vendor/github.com/pierrre/gotestcover/Makefile b/vendor/github.com/pierrre/gotestcover/Makefile new file mode 100644 index 000000000000..97e3b8528e38 --- /dev/null +++ b/vendor/github.com/pierrre/gotestcover/Makefile @@ -0,0 +1,19 @@ +#/bin/bash + +setup: + go get -u -v github.com/golang/lint/golint + go get -v -t ./... + +check: + gofmt -d . + go tool vet . + golint + +coverage: + gotestcover -coverprofile=coverage.txt github.com/pierrre/gotestcover + go tool cover -html=coverage.txt -o=coverage.html + +clean: + -rm coverage.txt + -rm coverage.html + gofmt -w . \ No newline at end of file diff --git a/vendor/github.com/pierrre/gotestcover/README.md b/vendor/github.com/pierrre/gotestcover/README.md new file mode 100644 index 000000000000..5ee605a29b4d --- /dev/null +++ b/vendor/github.com/pierrre/gotestcover/README.md @@ -0,0 +1,19 @@ +# Go test cover with multiple packages support + +## Features +- Coverage profile with multiple packages (`go test` doesn't support that) + +## Install +`go get github.com/pierrre/gotestcover` + +## Usage +```sh +gotestcover -coverprofile=cover.out mypackage +go tool cover -html=cover.out -o=cover.html +``` + +Run on multiple package with: +- `package1 package2` +- `package/...` + +Some `go test / build` flags are available. diff --git a/vendor/github.com/pierrre/gotestcover/gotestcover.go b/vendor/github.com/pierrre/gotestcover/gotestcover.go new file mode 100644 index 000000000000..8a914b900eae --- /dev/null +++ b/vendor/github.com/pierrre/gotestcover/gotestcover.go @@ -0,0 +1,282 @@ +// Package gotestcover provides multiple packages support for Go test cover. +package main + +import ( + "bufio" + "bytes" + "flag" + "fmt" + "io/ioutil" + "os" + "os/exec" + "runtime" + "strings" + "sync" +) + +var ( + // go build + flagA bool + flagX bool + flagRace bool + flagTags string + + // go test + flagV bool + flagCount int + flagCPU string + flagParallel string + flagRun string + flagShort bool + flagTimeout string + flagCoverMode string + flagCoverProfile string + + // custom + flagParallelPackages = runtime.GOMAXPROCS(0) + + // GAE/Go + flagGoogleAppEngine bool +) + +func main() { + err := run() + if err != nil { + fmt.Println(err) + os.Exit(1) + } +} + +func run() error { + err := parseFlags() + if err != nil { + return err + } + pkgArgs, flagArgs := parseArgs() + pkgs, err := resolvePackages(pkgArgs) + if err != nil { + return err + } + cov, failed := runAllPackageTests(pkgs, flagArgs, func(out string) { + fmt.Print(out) + }) + err = writeCoverProfile(cov) + if err != nil { + return err + } + if failed { + return fmt.Errorf("test failed") + } + return nil +} + +func parseFlags() error { + flag.BoolVar(&flagA, "a", flagA, "see 'go build' help") + flag.BoolVar(&flagX, "x", flagX, "see 'go build' help") + flag.BoolVar(&flagRace, "race", flagRace, "see 'go build' help") + flag.StringVar(&flagTags, "tags", flagTags, "see 'go build' help") + + flag.BoolVar(&flagV, "v", flagV, "see 'go test' help") + flag.IntVar(&flagCount, "count", flagCount, "see 'go test' help") + flag.StringVar(&flagCPU, "cpu", flagCPU, "see 'go test' help") + flag.StringVar(&flagParallel, "parallel", flagParallel, "see 'go test' help") + flag.StringVar(&flagRun, "run", flagRun, "see 'go test' help") + flag.BoolVar(&flagShort, "short", flagShort, "see 'go test' help") + flag.StringVar(&flagTimeout, "timeout", flagTimeout, "see 'go test' help") + flag.StringVar(&flagCoverMode, "covermode", flagCoverMode, "see 'go test' help") + flag.StringVar(&flagCoverProfile, "coverprofile", flagCoverProfile, "see 'go test' help") + + flag.IntVar(&flagParallelPackages, "parallelpackages", flagParallelPackages, "Number of package test run in parallel") + + flag.BoolVar(&flagGoogleAppEngine, "gae", flagGoogleAppEngine, "Bool of Command exec in GAE/Go") + + flag.Parse() + if flagCoverProfile == "" { + return fmt.Errorf("flag coverprofile must be set") + } + if flagParallelPackages < 1 { + return fmt.Errorf("flag parallelpackages must be greater than or equal to 1") + } + return nil +} + +func parseArgs() (pkgArgs, flagArgs []string) { + args := flag.Args() + for i, a := range args { + if strings.HasPrefix(a, "-") { + return args[:i], args[i:] + } + } + return args, nil +} + +func resolvePackages(pkgArgs []string) ([]string, error) { + cmdArgs := []string{"list"} + cmdArgs = append(cmdArgs, pkgArgs...) + cmdOut, err := runGoCommand(cmdArgs...) + if err != nil { + return nil, err + } + var pkgs []string + sc := bufio.NewScanner(bytes.NewReader(cmdOut)) + for sc.Scan() { + pkgs = append(pkgs, sc.Text()) + } + return pkgs, nil +} + +func runAllPackageTests(pkgs []string, flgs []string, pf func(string)) ([]byte, bool) { + pkgch := make(chan string) + type res struct { + out string + cov []byte + err error + } + resch := make(chan res) + wg := new(sync.WaitGroup) + wg.Add(flagParallelPackages) + go func() { + for _, pkg := range pkgs { + pkgch <- pkg + } + close(pkgch) + wg.Wait() + close(resch) + }() + for i := 0; i < flagParallelPackages; i++ { + go func() { + for p := range pkgch { + out, cov, err := runPackageTests(p, flgs) + resch <- res{ + out: out, + cov: cov, + err: err, + } + } + wg.Done() + }() + } + failed := false + var cov []byte + for r := range resch { + if r.err == nil { + pf(r.out) + cov = append(cov, r.cov...) + } else { + pf(r.err.Error()) + failed = true + } + } + return cov, failed +} + +func runPackageTests(pkg string, flgs []string) (out string, cov []byte, err error) { + coverFile, err := ioutil.TempFile("", "gotestcover-") + if err != nil { + return "", nil, err + } + defer os.Remove(coverFile.Name()) + defer coverFile.Close() + var args []string + args = append(args, "test") + + if flagA { + args = append(args, "-a") + } + if flagX { + args = append(args, "-x") + } + if flagRace { + args = append(args, "-race") + } + if flagTags != "" { + args = append(args, "-tags", flagTags) + } + + if flagV { + args = append(args, "-v") + } + if flagCount != 0 { + args = append(args, "-count", fmt.Sprint(flagCount)) + } + if flagCPU != "" { + args = append(args, "-cpu", flagCPU) + } + if flagParallel != "" { + args = append(args, "-parallel", flagParallel) + } + if flagRun != "" { + args = append(args, "-run", flagRun) + } + if flagShort { + args = append(args, "-short") + } + if flagTimeout != "" { + args = append(args, "-timeout", flagTimeout) + } + args = append(args, "-cover") + if flagCoverMode != "" { + args = append(args, "-covermode", flagCoverMode) + } + args = append(args, "-coverprofile", coverFile.Name()) + + args = append(args, pkg) + + args = append(args, flgs...) + + cmdOut, err := runGoCommand(args...) + if err != nil { + return "", nil, err + } + cov, err = ioutil.ReadAll(coverFile) + if err != nil { + return "", nil, err + } + cov = removeFirstLine(cov) + return string(cmdOut), cov, nil +} + +func writeCoverProfile(cov []byte) error { + if len(cov) == 0 { + return nil + } + buf := new(bytes.Buffer) + mode := flagCoverMode + if mode == "" { + if flagRace { + mode = "atomic" + } else { + mode = "set" + } + } + fmt.Fprintf(buf, "mode: %s\n", mode) + buf.Write(cov) + return ioutil.WriteFile(flagCoverProfile, buf.Bytes(), os.FileMode(0644)) +} + +func runGoCommand(args ...string) ([]byte, error) { + goCmd := "go" + if flagGoogleAppEngine { + goCmd = "goapp" + } + cmd := exec.Command(goCmd, args...) + out, err := cmd.CombinedOutput() + if err != nil { + return nil, fmt.Errorf("command %s: %s\n%s", cmd.Args, err, out) + } + return out, nil +} + +func removeFirstLine(b []byte) []byte { + out := new(bytes.Buffer) + sc := bufio.NewScanner(bytes.NewReader(b)) + firstLine := true + for sc.Scan() { + if firstLine { + firstLine = false + continue + } + fmt.Fprintf(out, "%s\n", sc.Bytes()) + } + return out.Bytes() +} diff --git a/vendor/github.com/pkg/errors/.travis.yml b/vendor/github.com/pkg/errors/.travis.yml index d4b92663bacf..9159de03e03d 100644 --- a/vendor/github.com/pkg/errors/.travis.yml +++ b/vendor/github.com/pkg/errors/.travis.yml @@ -1,15 +1,10 @@ language: go go_import_path: github.com/pkg/errors go: - - 1.4.x - - 1.5.x - - 1.6.x - - 1.7.x - - 1.8.x - - 1.9.x - - 1.10.x - 1.11.x + - 1.12.x + - 1.13.x - tip script: - - go test -v ./... + - make check diff --git a/vendor/github.com/pkg/errors/Makefile b/vendor/github.com/pkg/errors/Makefile new file mode 100644 index 000000000000..ce9d7cded649 --- /dev/null +++ b/vendor/github.com/pkg/errors/Makefile @@ -0,0 +1,44 @@ +PKGS := github.com/pkg/errors +SRCDIRS := $(shell go list -f '{{.Dir}}' $(PKGS)) +GO := go + +check: test vet gofmt misspell unconvert staticcheck ineffassign unparam + +test: + $(GO) test $(PKGS) + +vet: | test + $(GO) vet $(PKGS) + +staticcheck: + $(GO) get honnef.co/go/tools/cmd/staticcheck + staticcheck -checks all $(PKGS) + +misspell: + $(GO) get github.com/client9/misspell/cmd/misspell + misspell \ + -locale GB \ + -error \ + *.md *.go + +unconvert: + $(GO) get github.com/mdempsky/unconvert + unconvert -v $(PKGS) + +ineffassign: + $(GO) get github.com/gordonklaus/ineffassign + find $(SRCDIRS) -name '*.go' | xargs ineffassign + +pedantic: check errcheck + +unparam: + $(GO) get mvdan.cc/unparam + unparam ./... + +errcheck: + $(GO) get github.com/kisielk/errcheck + errcheck $(PKGS) + +gofmt: + @echo Checking code is gofmted + @test -z "$(shell gofmt -s -l -d -e $(SRCDIRS) | tee /dev/stderr)" diff --git a/vendor/github.com/pkg/errors/README.md b/vendor/github.com/pkg/errors/README.md index 6483ba2afb51..54dfdcb12ea1 100644 --- a/vendor/github.com/pkg/errors/README.md +++ b/vendor/github.com/pkg/errors/README.md @@ -41,11 +41,18 @@ default: [Read the package documentation for more information](https://godoc.org/github.com/pkg/errors). +## Roadmap + +With the upcoming [Go2 error proposals](https://go.googlesource.com/proposal/+/master/design/go2draft.md) this package is moving into maintenance mode. The roadmap for a 1.0 release is as follows: + +- 0.9. Remove pre Go 1.9 and Go 1.10 support, address outstanding pull requests (if possible) +- 1.0. Final release. + ## Contributing -We welcome pull requests, bug fixes and issue reports. With that said, the bar for adding new symbols to this package is intentionally set high. +Because of the Go2 errors changes, this package is not accepting proposals for new functionality. With that said, we welcome pull requests, bug fixes and issue reports. -Before proposing a change, please discuss your change by raising an issue. +Before sending a PR, please discuss your change by raising an issue. ## License diff --git a/vendor/github.com/pkg/errors/errors.go b/vendor/github.com/pkg/errors/errors.go index 7421f326ffe8..161aea258296 100644 --- a/vendor/github.com/pkg/errors/errors.go +++ b/vendor/github.com/pkg/errors/errors.go @@ -82,7 +82,7 @@ // // if err, ok := err.(stackTracer); ok { // for _, f := range err.StackTrace() { -// fmt.Printf("%+s:%d", f) +// fmt.Printf("%+s:%d\n", f, f) // } // } // @@ -159,6 +159,9 @@ type withStack struct { func (w *withStack) Cause() error { return w.error } +// Unwrap provides compatibility for Go 1.13 error chains. +func (w *withStack) Unwrap() error { return w.error } + func (w *withStack) Format(s fmt.State, verb rune) { switch verb { case 'v': @@ -241,6 +244,9 @@ type withMessage struct { func (w *withMessage) Error() string { return w.msg + ": " + w.cause.Error() } func (w *withMessage) Cause() error { return w.cause } +// Unwrap provides compatibility for Go 1.13 error chains. +func (w *withMessage) Unwrap() error { return w.cause } + func (w *withMessage) Format(s fmt.State, verb rune) { switch verb { case 'v': diff --git a/vendor/github.com/pkg/errors/go113.go b/vendor/github.com/pkg/errors/go113.go new file mode 100644 index 000000000000..be0d10d0c793 --- /dev/null +++ b/vendor/github.com/pkg/errors/go113.go @@ -0,0 +1,38 @@ +// +build go1.13 + +package errors + +import ( + stderrors "errors" +) + +// Is reports whether any error in err's chain matches target. +// +// The chain consists of err itself followed by the sequence of errors obtained by +// repeatedly calling Unwrap. +// +// An error is considered to match a target if it is equal to that target or if +// it implements a method Is(error) bool such that Is(target) returns true. +func Is(err, target error) bool { return stderrors.Is(err, target) } + +// As finds the first error in err's chain that matches target, and if so, sets +// target to that error value and returns true. +// +// The chain consists of err itself followed by the sequence of errors obtained by +// repeatedly calling Unwrap. +// +// An error matches target if the error's concrete value is assignable to the value +// pointed to by target, or if the error has a method As(interface{}) bool such that +// As(target) returns true. In the latter case, the As method is responsible for +// setting target. +// +// As will panic if target is not a non-nil pointer to either a type that implements +// error, or to any interface type. As returns false if err is nil. +func As(err error, target interface{}) bool { return stderrors.As(err, target) } + +// Unwrap returns the result of calling the Unwrap method on err, if err's +// type contains an Unwrap method returning error. +// Otherwise, Unwrap returns nil. +func Unwrap(err error) error { + return stderrors.Unwrap(err) +} diff --git a/vendor/github.com/pkg/errors/stack.go b/vendor/github.com/pkg/errors/stack.go index 2874a048cf3e..779a8348fb9c 100644 --- a/vendor/github.com/pkg/errors/stack.go +++ b/vendor/github.com/pkg/errors/stack.go @@ -5,10 +5,13 @@ import ( "io" "path" "runtime" + "strconv" "strings" ) // Frame represents a program counter inside a stack frame. +// For historical reasons if Frame is interpreted as a uintptr +// its value represents the program counter + 1. type Frame uintptr // pc returns the program counter for this frame; @@ -37,6 +40,15 @@ func (f Frame) line() int { return line } +// name returns the name of this function, if known. +func (f Frame) name() string { + fn := runtime.FuncForPC(f.pc()) + if fn == nil { + return "unknown" + } + return fn.Name() +} + // Format formats the frame according to the fmt.Formatter interface. // // %s source file @@ -54,22 +66,16 @@ func (f Frame) Format(s fmt.State, verb rune) { case 's': switch { case s.Flag('+'): - pc := f.pc() - fn := runtime.FuncForPC(pc) - if fn == nil { - io.WriteString(s, "unknown") - } else { - file, _ := fn.FileLine(pc) - fmt.Fprintf(s, "%s\n\t%s", fn.Name(), file) - } + io.WriteString(s, f.name()) + io.WriteString(s, "\n\t") + io.WriteString(s, f.file()) default: io.WriteString(s, path.Base(f.file())) } case 'd': - fmt.Fprintf(s, "%d", f.line()) + io.WriteString(s, strconv.Itoa(f.line())) case 'n': - name := runtime.FuncForPC(f.pc()).Name() - io.WriteString(s, funcname(name)) + io.WriteString(s, funcname(f.name())) case 'v': f.Format(s, 's') io.WriteString(s, ":") @@ -77,6 +83,16 @@ func (f Frame) Format(s fmt.State, verb rune) { } } +// MarshalText formats a stacktrace Frame as a text string. The output is the +// same as that of fmt.Sprintf("%+v", f), but without newlines or tabs. +func (f Frame) MarshalText() ([]byte, error) { + name := f.name() + if name == "unknown" { + return []byte(name), nil + } + return []byte(fmt.Sprintf("%s %s:%d", name, f.file(), f.line())), nil +} + // StackTrace is stack of Frames from innermost (newest) to outermost (oldest). type StackTrace []Frame @@ -94,16 +110,30 @@ func (st StackTrace) Format(s fmt.State, verb rune) { switch { case s.Flag('+'): for _, f := range st { - fmt.Fprintf(s, "\n%+v", f) + io.WriteString(s, "\n") + f.Format(s, verb) } case s.Flag('#'): fmt.Fprintf(s, "%#v", []Frame(st)) default: - fmt.Fprintf(s, "%v", []Frame(st)) + st.formatSlice(s, verb) } case 's': - fmt.Fprintf(s, "%s", []Frame(st)) + st.formatSlice(s, verb) + } +} + +// formatSlice will format this StackTrace into the given buffer as a slice of +// Frame, only valid when called with '%s' or '%v'. +func (st StackTrace) formatSlice(s fmt.State, verb rune) { + io.WriteString(s, "[") + for i, f := range st { + if i > 0 { + io.WriteString(s, " ") + } + f.Format(s, verb) } + io.WriteString(s, "]") } // stack represents a stack of program counters. diff --git a/vendor/github.com/tsg/go-daemon/.gitignore b/vendor/github.com/tsg/go-daemon/.gitignore new file mode 100644 index 000000000000..b6be56846841 --- /dev/null +++ b/vendor/github.com/tsg/go-daemon/.gitignore @@ -0,0 +1,2 @@ +*.swp +god diff --git a/vendor/github.com/tsg/go-daemon/LICENSE b/vendor/github.com/tsg/go-daemon/LICENSE new file mode 100644 index 000000000000..168a95e31ffd --- /dev/null +++ b/vendor/github.com/tsg/go-daemon/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2013-2014 Alexandre Fiori. 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. + * The names of authors or contributors may NOT 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/tsg/go-daemon/Makefile b/vendor/github.com/tsg/go-daemon/Makefile new file mode 100644 index 000000000000..9717e7e496fd --- /dev/null +++ b/vendor/github.com/tsg/go-daemon/Makefile @@ -0,0 +1,23 @@ +# Copyright 2013-2014 Alexandre Fiori +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +PKG=go-daemon-1.2 +TGZ=$(PKG).tar.gz + +all: god + +god: + cc god.c -o god -lpthread + +clean: + rm -f god $(TGZ) + +install: god + mkdir -p $(DESTDIR)/usr/bin + install -m 755 god $(DESTDIR)/usr/bin + +archive: + git archive --format tar --prefix=$(PKG)/ HEAD . | gzip > $(TGZ) + +.PHONY: god diff --git a/vendor/github.com/tsg/go-daemon/README.md b/vendor/github.com/tsg/go-daemon/README.md new file mode 100644 index 000000000000..6063922dc1aa --- /dev/null +++ b/vendor/github.com/tsg/go-daemon/README.md @@ -0,0 +1,73 @@ +# Go daemon + +Go daemon (or just **god**) is a utility to "daemonize" Go programs +that originally only run in foreground and write logs to the console. + +Go daemon can turn these programs into daemons by managing essential aspects +of their execution. The process of making a program become a daemon has very +peculiar steps and can be done outside the code. This is what **god** is for. + +It executes a program for you doing things that daemons do: switch to another +user and group, switch the directory of execution, detach from the terminal +and create a pid file. While the program runs, **god** consumes its output +(stdout and stderr) and write to a log file *using minimum system resources*. + +It also handles all signals (SIGINT, SIGTERM, etc) and forward them to the +program being managed. On SIGHUP, **god** recycles its log file making it +easy to integrate with logrotate. If SIGHUP is not supported by your program, +**god** can handle the signal itself and not forward it, making your program +immune to hangups. + +Go daemon is inspired by [twistd](http://twistedmatrix.com/documents/current/core/howto/basics.html#auto1), +but primarily for running servers written in the +[Go Programming Language](http://golang.org) that don't (or just can't) +care about daemonizing. However, it can also be used for running php, python +and any other type of long lived programs that need to be daemonized. + +A typical command line looks like this: + + god --nohup --logfile foo.log --pidfile foo.pid --user nobody --group nobody --rundir /opt/foo -- ./foobar --foobar-opts + + +## Why? + +Like if there's not enough options out there: upstart, systemd, launchd, +daemontools, supervisord, runit, you name it. There's also utilities like +apache's logger, etc. + +Go daemon aims at being as simple as possible in regards to deployment and +usage, and to run with minimum resources. It doesn't supervise the program, +just run it as a daemon and takes care of its console output. It mixes well +with upstart and logrotate, for example. + +Go daemon is not needed on systems with [systemd](http://www.freedesktop.org/wiki/Software/systemd/). + + +## Building + +Go daemon is written in C and needs to be compiled. Debian and Ubuntu can +install the compiler and tools with the following command: + + apt-get install build-essential + +Then build and install it: + + make + make install + +The `god` command line tool should be ready to use. + +### Binary packages + +Go daemon can be packaged for both [debian](debian/README.Debian.md) and +[rpm](rpm/README.md) based systems and has been tested on Ubuntu, CentOS and +RHEL. + +Ubuntu 12.04 packages are available at + and can be installed +with following commands: + + apt-get install python-software-properties + add-apt-repository ppa:fiorix/go-daemon + apt-get update + apt-get install go-daemon diff --git a/vendor/github.com/tsg/go-daemon/daemon.go b/vendor/github.com/tsg/go-daemon/daemon.go new file mode 100644 index 000000000000..9d3072094bef --- /dev/null +++ b/vendor/github.com/tsg/go-daemon/daemon.go @@ -0,0 +1 @@ +package daemon diff --git a/vendor/github.com/tsg/go-daemon/go.mod b/vendor/github.com/tsg/go-daemon/go.mod new file mode 100644 index 000000000000..128e118f10b7 --- /dev/null +++ b/vendor/github.com/tsg/go-daemon/go.mod @@ -0,0 +1,3 @@ +module github.com/tsg/go-daemon + +go 1.13 diff --git a/vendor/github.com/tsg/go-daemon/god.c b/vendor/github.com/tsg/go-daemon/god.c new file mode 100644 index 000000000000..7f63e081efd9 --- /dev/null +++ b/vendor/github.com/tsg/go-daemon/god.c @@ -0,0 +1,313 @@ +// Copyright 2013-2014 Alexandre Fiori +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +void usage() { + printf( + "Use: god [options] [--] program [arguments]\n" + "Options:\n" + "-h --help show this help and exit\n" + "-v --version show version and exit\n" + "-f --foreground run in foreground\n" + "-n --nohup make the program immune to SIGHUP\n" + "-l --logfile FILE write the program's stdout and stderr to FILE\n" + "-p --pidfile FILE write pid to FILE\n" + "-r --rundir DIR switch to DIR before executing the program\n" + "-u --user USER switch to USER before executing the program\n" + "-g --group GROUP switch to GROUP before executing the program\n" + "\nThe program's output go to a blackhole if no logfile is set.\n" + "Log files are recycled on SIGHUP.\n" + ); + exit(1); +} + +static int nohup = 0; +static int logfd[2]; // pipe +static pid_t childpid = 0; +static FILE *logfp = NULL; +static FILE *pidfp = NULL; +static char logfile[PATH_MAX]; +static char pidfile[PATH_MAX]; +static char linebuf[1024]; +static struct passwd *pwd = NULL; +static struct group *grp = NULL; +static pthread_mutex_t logger_mutex; + +void daemon_main(int optind, char **argv); +void *logger_thread(void *cmdname); +void sighup(int signum); +void sigfwd(int signum); + +int main(int argc, char **argv) { + char rundir[PATH_MAX]; + char user[64]; + char group[64]; + int foreground = 0; + struct stat exec_stat; + + memset(logfile, 0, sizeof logfile); + memset(pidfile, 0, sizeof pidfile); + memset(rundir, 0, sizeof rundir); + memset(user, 0, sizeof user); + memset(group, 0, sizeof group); + + static struct option opts[] = { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, 'v' }, + { "foreground", no_argument, NULL, 'f' }, + { "nohup", no_argument, NULL, 'n' }, + { "logfile", required_argument, NULL, 'l' }, + { "pidfile", required_argument, NULL, 'p' }, + { "rundir", required_argument, NULL, 'r' }, + { "user", required_argument, NULL, 'u' }, + { "group", required_argument, NULL, 'g' }, + { NULL, 0, NULL, 0 }, + }; + + int ch; + while (1) { + ch = getopt_long(argc, argv, "l:p:r:u:g:hvfns", opts, NULL); + if (ch == -1) + break; + + switch (ch) { + case 'v': + printf("Go daemon v1.2\n"); + printf("http://github.com/fiorix/go-daemon\n"); + return 0; + case 'f': + foreground = 1; + break; + case 'n': + nohup = 1; + break; + case 'l': + strncpy(logfile, optarg, sizeof logfile - 1); + break; + case 'p': + strncpy(pidfile, optarg, sizeof pidfile - 1); + break; + case 'r': + strncpy(rundir, optarg, sizeof rundir - 1); + break; + case 'u': + strncpy(user, optarg, sizeof user - 1); + break; + case 'g': + strncpy(group, optarg, sizeof group - 1); + break; + default: + usage(); + } + } + + // utility is expected to be argv's leftovers. + if (optind >= argc) + usage(); + + if (*rundir != 0 && chdir(rundir) == -1) { + perror("failed to switch to rundir"); + return 1; + } + + if (*user != 0 && (pwd = getpwnam(user)) == NULL) { + fprintf(stderr, "failed to switch to user %s: %s\n", + user, strerror(errno)); + return 1; + } + + if (*group != 0 && (grp = getgrnam(group)) == NULL) { + fprintf(stderr, "failed to switch to group %s: %s\n", + group, strerror(errno)); + return 1; + } + + if (*logfile != 0 && (logfp = fopen(logfile, "a")) == NULL) { + perror("failed to open logfile"); + return 1; + } + if (logfp) + setvbuf(logfp, linebuf, _IOLBF, sizeof linebuf); + + if (*pidfile != 0 && (pidfp = fopen(pidfile, "w+")) == NULL) { + perror("failed to open pidfile"); + return 1; + } + + if (grp != NULL && setegid(grp->gr_gid) == -1) { + fprintf(stderr, "failed to switch to group %s: %s\n", + group, strerror(errno)); + return 1; + } + + if (pwd != NULL && seteuid(pwd->pw_uid) == -1) { + fprintf(stderr, "failed to switch to user %s: %s\n", + user, strerror(errno)); + return 1; + } + + if (stat(argv[optind], &exec_stat) < 0) { + fprintf(stderr, "failed to stat %s: %s\n", + argv[optind], strerror(errno)); + return 1; + } + if (!(exec_stat.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) { + fprintf(stderr, "permission denied: %s\n", + argv[optind]); + return 1; + } + + if (foreground) { + daemon_main(optind, argv); + } else { + // Daemonize. + pid_t pid = fork(); + if (pid) { + waitpid(pid, NULL, 0); + } else if (!pid) { + if ((pid = fork())) { + exit(0); + } else if (!pid) { + close(0); + close(1); + close(2); + daemon_main(optind, argv); + } else { + perror("fork"); + exit(1); + } + } else { + perror("fork"); + exit(1); + } + } + + return 0; +} + +void daemon_main(int optind, char **argv) { + if (pidfp) { + fprintf(pidfp, "%d\n", getpid()); + fclose(pidfp); + } + // Fwd all signals to the child, except SIGHUP. + int signum; + for (signum = 1; signum < 33; signum++) { + if (signal(signum, sigfwd) == SIG_IGN) + signal(signum, SIG_IGN); + } + signal(SIGHUP, sighup); + pipe(logfd); + if ((childpid = fork())) { + close(logfd[1]); + pthread_t logth; + pthread_create(&logth, NULL, logger_thread, argv[optind]); + waitpid(childpid, NULL, 0); + pthread_join(logth, NULL); + } else if (!childpid) { + close(logfd[0]); + close(0); + close(1); + close(2); + dup2(logfd[1], 1); + dup2(logfd[1], 2); + execvp(argv[optind], argv + optind); + printf("\x1b%s", strerror(errno)); + fflush(stdout); + close(logfd[1]); + close(1); + close(2); + } else { + perror("fork"); + exit(1); + } + if (pidfp) + unlink(pidfile); +} + +void *logger_thread(void *cmdname) { + int n; + char buf[4096]; + int has_read = 0; + + while(1) { + // read() will fail when the child process fails + // to execute or dies, and closes its terminal. + // This is what terminates this thread and therefore + // the main thread can move along. + n = read(logfd[0], buf, sizeof buf); + if (n <= 0) + break; + + buf[n] = 0; + if (!has_read) { + has_read = 1; + if (*buf == '\x1b') { + char *p = buf; + printf("%s: %s\n", (char *) cmdname, ++p); + close(logfd[0]); + break; + } + } + + pthread_mutex_lock(&logger_mutex); + if (logfp) { + fwrite(buf, 1, n, logfp); + //fflush(logfp); + } + pthread_mutex_unlock(&logger_mutex); + } + + return NULL; +} + +void sighup(int signum) { + if (pwd != NULL) { + seteuid(getuid()); + } + if (grp != NULL) { + setegid(getgid()); + } + pthread_mutex_lock(&logger_mutex); + if (logfp) { + FILE *fp = fopen(logfile, "a"); + if (fp != NULL) { + fclose(logfp); + logfp = fp; + setvbuf(logfp, linebuf, _IOLBF, sizeof linebuf); + } + } + if (grp != NULL) { + setegid(grp->gr_gid); + } + if (pwd != NULL) { + seteuid(pwd->pw_uid); + } + pthread_mutex_unlock(&logger_mutex); + if (!nohup && childpid) // nonohup :~ + kill(childpid, signum); +} + +void sigfwd(int signum) { + if (childpid) + kill(childpid, signum); +} diff --git a/vendor/golang.org/x/tools/cmd/stringer/stringer.go b/vendor/golang.org/x/tools/cmd/stringer/stringer.go new file mode 100644 index 000000000000..e1468693f095 --- /dev/null +++ b/vendor/golang.org/x/tools/cmd/stringer/stringer.go @@ -0,0 +1,650 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Stringer is a tool to automate the creation of methods that satisfy the fmt.Stringer +// interface. Given the name of a (signed or unsigned) integer type T that has constants +// defined, stringer will create a new self-contained Go source file implementing +// func (t T) String() string +// The file is created in the same package and directory as the package that defines T. +// It has helpful defaults designed for use with go generate. +// +// Stringer works best with constants that are consecutive values such as created using iota, +// but creates good code regardless. In the future it might also provide custom support for +// constant sets that are bit patterns. +// +// For example, given this snippet, +// +// package painkiller +// +// type Pill int +// +// const ( +// Placebo Pill = iota +// Aspirin +// Ibuprofen +// Paracetamol +// Acetaminophen = Paracetamol +// ) +// +// running this command +// +// stringer -type=Pill +// +// in the same directory will create the file pill_string.go, in package painkiller, +// containing a definition of +// +// func (Pill) String() string +// +// That method will translate the value of a Pill constant to the string representation +// of the respective constant name, so that the call fmt.Print(painkiller.Aspirin) will +// print the string "Aspirin". +// +// Typically this process would be run using go generate, like this: +// +// //go:generate stringer -type=Pill +// +// If multiple constants have the same value, the lexically first matching name will +// be used (in the example, Acetaminophen will print as "Paracetamol"). +// +// With no arguments, it processes the package in the current directory. +// Otherwise, the arguments must name a single directory holding a Go package +// or a set of Go source files that represent a single Go package. +// +// The -type flag accepts a comma-separated list of types so a single run can +// generate methods for multiple types. The default output file is t_string.go, +// where t is the lower-cased name of the first type listed. It can be overridden +// with the -output flag. +// +// The -linecomment flag tells stringer to generate the text of any line comment, trimmed +// of leading spaces, instead of the constant name. For instance, if the constants above had a +// Pill prefix, one could write +// +// PillAspirin // Aspirin +// +// to suppress it in the output. +package main // import "golang.org/x/tools/cmd/stringer" + +import ( + "bytes" + "flag" + "fmt" + "go/ast" + "go/constant" + "go/format" + "go/token" + "go/types" + "io/ioutil" + "log" + "os" + "path/filepath" + "sort" + "strings" + + "golang.org/x/tools/go/packages" +) + +var ( + typeNames = flag.String("type", "", "comma-separated list of type names; must be set") + output = flag.String("output", "", "output file name; default srcdir/_string.go") + trimprefix = flag.String("trimprefix", "", "trim the `prefix` from the generated constant names") + linecomment = flag.Bool("linecomment", false, "use line comment text as printed text when present") + buildTags = flag.String("tags", "", "comma-separated list of build tags to apply") +) + +// Usage is a replacement usage function for the flags package. +func Usage() { + fmt.Fprintf(os.Stderr, "Usage of stringer:\n") + fmt.Fprintf(os.Stderr, "\tstringer [flags] -type T [directory]\n") + fmt.Fprintf(os.Stderr, "\tstringer [flags] -type T files... # Must be a single package\n") + fmt.Fprintf(os.Stderr, "For more information, see:\n") + fmt.Fprintf(os.Stderr, "\thttp://godoc.org/golang.org/x/tools/cmd/stringer\n") + fmt.Fprintf(os.Stderr, "Flags:\n") + flag.PrintDefaults() +} + +func main() { + log.SetFlags(0) + log.SetPrefix("stringer: ") + flag.Usage = Usage + flag.Parse() + if len(*typeNames) == 0 { + flag.Usage() + os.Exit(2) + } + types := strings.Split(*typeNames, ",") + var tags []string + if len(*buildTags) > 0 { + tags = strings.Split(*buildTags, ",") + } + + // We accept either one directory or a list of files. Which do we have? + args := flag.Args() + if len(args) == 0 { + // Default: process whole package in current directory. + args = []string{"."} + } + + // Parse the package once. + var dir string + g := Generator{ + trimPrefix: *trimprefix, + lineComment: *linecomment, + } + // TODO(suzmue): accept other patterns for packages (directories, list of files, import paths, etc). + if len(args) == 1 && isDirectory(args[0]) { + dir = args[0] + } else { + if len(tags) != 0 { + log.Fatal("-tags option applies only to directories, not when files are specified") + } + dir = filepath.Dir(args[0]) + } + + g.parsePackage(args, tags) + + // Print the header and package clause. + g.Printf("// Code generated by \"stringer %s\"; DO NOT EDIT.\n", strings.Join(os.Args[1:], " ")) + g.Printf("\n") + g.Printf("package %s", g.pkg.name) + g.Printf("\n") + g.Printf("import \"strconv\"\n") // Used by all methods. + + // Run generate for each type. + for _, typeName := range types { + g.generate(typeName) + } + + // Format the output. + src := g.format() + + // Write to file. + outputName := *output + if outputName == "" { + baseName := fmt.Sprintf("%s_string.go", types[0]) + outputName = filepath.Join(dir, strings.ToLower(baseName)) + } + err := ioutil.WriteFile(outputName, src, 0644) + if err != nil { + log.Fatalf("writing output: %s", err) + } +} + +// isDirectory reports whether the named file is a directory. +func isDirectory(name string) bool { + info, err := os.Stat(name) + if err != nil { + log.Fatal(err) + } + return info.IsDir() +} + +// Generator holds the state of the analysis. Primarily used to buffer +// the output for format.Source. +type Generator struct { + buf bytes.Buffer // Accumulated output. + pkg *Package // Package we are scanning. + + trimPrefix string + lineComment bool +} + +func (g *Generator) Printf(format string, args ...interface{}) { + fmt.Fprintf(&g.buf, format, args...) +} + +// File holds a single parsed file and associated data. +type File struct { + pkg *Package // Package to which this file belongs. + file *ast.File // Parsed AST. + // These fields are reset for each type being generated. + typeName string // Name of the constant type. + values []Value // Accumulator for constant values of that type. + + trimPrefix string + lineComment bool +} + +type Package struct { + name string + defs map[*ast.Ident]types.Object + files []*File +} + +// parsePackage analyzes the single package constructed from the patterns and tags. +// parsePackage exits if there is an error. +func (g *Generator) parsePackage(patterns []string, tags []string) { + cfg := &packages.Config{ + Mode: packages.LoadSyntax, + // TODO: Need to think about constants in test files. Maybe write type_string_test.go + // in a separate pass? For later. + Tests: false, + BuildFlags: []string{fmt.Sprintf("-tags=%s", strings.Join(tags, " "))}, + } + pkgs, err := packages.Load(cfg, patterns...) + if err != nil { + log.Fatal(err) + } + if len(pkgs) != 1 { + log.Fatalf("error: %d packages found", len(pkgs)) + } + g.addPackage(pkgs[0]) +} + +// addPackage adds a type checked Package and its syntax files to the generator. +func (g *Generator) addPackage(pkg *packages.Package) { + g.pkg = &Package{ + name: pkg.Name, + defs: pkg.TypesInfo.Defs, + files: make([]*File, len(pkg.Syntax)), + } + + for i, file := range pkg.Syntax { + g.pkg.files[i] = &File{ + file: file, + pkg: g.pkg, + trimPrefix: g.trimPrefix, + lineComment: g.lineComment, + } + } +} + +// generate produces the String method for the named type. +func (g *Generator) generate(typeName string) { + values := make([]Value, 0, 100) + for _, file := range g.pkg.files { + // Set the state for this run of the walker. + file.typeName = typeName + file.values = nil + if file.file != nil { + ast.Inspect(file.file, file.genDecl) + values = append(values, file.values...) + } + } + + if len(values) == 0 { + log.Fatalf("no values defined for type %s", typeName) + } + // Generate code that will fail if the constants change value. + g.Printf("func _() {\n") + g.Printf("\t// An \"invalid array index\" compiler error signifies that the constant values have changed.\n") + g.Printf("\t// Re-run the stringer command to generate them again.\n") + g.Printf("\tvar x [1]struct{}\n") + for _, v := range values { + g.Printf("\t_ = x[%s - %s]\n", v.originalName, v.str) + } + g.Printf("}\n") + runs := splitIntoRuns(values) + // The decision of which pattern to use depends on the number of + // runs in the numbers. If there's only one, it's easy. For more than + // one, there's a tradeoff between complexity and size of the data + // and code vs. the simplicity of a map. A map takes more space, + // but so does the code. The decision here (crossover at 10) is + // arbitrary, but considers that for large numbers of runs the cost + // of the linear scan in the switch might become important, and + // rather than use yet another algorithm such as binary search, + // we punt and use a map. In any case, the likelihood of a map + // being necessary for any realistic example other than bitmasks + // is very low. And bitmasks probably deserve their own analysis, + // to be done some other day. + switch { + case len(runs) == 1: + g.buildOneRun(runs, typeName) + case len(runs) <= 10: + g.buildMultipleRuns(runs, typeName) + default: + g.buildMap(runs, typeName) + } +} + +// splitIntoRuns breaks the values into runs of contiguous sequences. +// For example, given 1,2,3,5,6,7 it returns {1,2,3},{5,6,7}. +// The input slice is known to be non-empty. +func splitIntoRuns(values []Value) [][]Value { + // We use stable sort so the lexically first name is chosen for equal elements. + sort.Stable(byValue(values)) + // Remove duplicates. Stable sort has put the one we want to print first, + // so use that one. The String method won't care about which named constant + // was the argument, so the first name for the given value is the only one to keep. + // We need to do this because identical values would cause the switch or map + // to fail to compile. + j := 1 + for i := 1; i < len(values); i++ { + if values[i].value != values[i-1].value { + values[j] = values[i] + j++ + } + } + values = values[:j] + runs := make([][]Value, 0, 10) + for len(values) > 0 { + // One contiguous sequence per outer loop. + i := 1 + for i < len(values) && values[i].value == values[i-1].value+1 { + i++ + } + runs = append(runs, values[:i]) + values = values[i:] + } + return runs +} + +// format returns the gofmt-ed contents of the Generator's buffer. +func (g *Generator) format() []byte { + src, err := format.Source(g.buf.Bytes()) + if err != nil { + // Should never happen, but can arise when developing this code. + // The user can compile the output to see the error. + log.Printf("warning: internal error: invalid Go generated: %s", err) + log.Printf("warning: compile the package to analyze the error") + return g.buf.Bytes() + } + return src +} + +// Value represents a declared constant. +type Value struct { + originalName string // The name of the constant. + name string // The name with trimmed prefix. + // The value is stored as a bit pattern alone. The boolean tells us + // whether to interpret it as an int64 or a uint64; the only place + // this matters is when sorting. + // Much of the time the str field is all we need; it is printed + // by Value.String. + value uint64 // Will be converted to int64 when needed. + signed bool // Whether the constant is a signed type. + str string // The string representation given by the "go/constant" package. +} + +func (v *Value) String() string { + return v.str +} + +// byValue lets us sort the constants into increasing order. +// We take care in the Less method to sort in signed or unsigned order, +// as appropriate. +type byValue []Value + +func (b byValue) Len() int { return len(b) } +func (b byValue) Swap(i, j int) { b[i], b[j] = b[j], b[i] } +func (b byValue) Less(i, j int) bool { + if b[i].signed { + return int64(b[i].value) < int64(b[j].value) + } + return b[i].value < b[j].value +} + +// genDecl processes one declaration clause. +func (f *File) genDecl(node ast.Node) bool { + decl, ok := node.(*ast.GenDecl) + if !ok || decl.Tok != token.CONST { + // We only care about const declarations. + return true + } + // The name of the type of the constants we are declaring. + // Can change if this is a multi-element declaration. + typ := "" + // Loop over the elements of the declaration. Each element is a ValueSpec: + // a list of names possibly followed by a type, possibly followed by values. + // If the type and value are both missing, we carry down the type (and value, + // but the "go/types" package takes care of that). + for _, spec := range decl.Specs { + vspec := spec.(*ast.ValueSpec) // Guaranteed to succeed as this is CONST. + if vspec.Type == nil && len(vspec.Values) > 0 { + // "X = 1". With no type but a value. If the constant is untyped, + // skip this vspec and reset the remembered type. + typ = "" + + // If this is a simple type conversion, remember the type. + // We don't mind if this is actually a call; a qualified call won't + // be matched (that will be SelectorExpr, not Ident), and only unusual + // situations will result in a function call that appears to be + // a type conversion. + ce, ok := vspec.Values[0].(*ast.CallExpr) + if !ok { + continue + } + id, ok := ce.Fun.(*ast.Ident) + if !ok { + continue + } + typ = id.Name + } + if vspec.Type != nil { + // "X T". We have a type. Remember it. + ident, ok := vspec.Type.(*ast.Ident) + if !ok { + continue + } + typ = ident.Name + } + if typ != f.typeName { + // This is not the type we're looking for. + continue + } + // We now have a list of names (from one line of source code) all being + // declared with the desired type. + // Grab their names and actual values and store them in f.values. + for _, name := range vspec.Names { + if name.Name == "_" { + continue + } + // This dance lets the type checker find the values for us. It's a + // bit tricky: look up the object declared by the name, find its + // types.Const, and extract its value. + obj, ok := f.pkg.defs[name] + if !ok { + log.Fatalf("no value for constant %s", name) + } + info := obj.Type().Underlying().(*types.Basic).Info() + if info&types.IsInteger == 0 { + log.Fatalf("can't handle non-integer constant type %s", typ) + } + value := obj.(*types.Const).Val() // Guaranteed to succeed as this is CONST. + if value.Kind() != constant.Int { + log.Fatalf("can't happen: constant is not an integer %s", name) + } + i64, isInt := constant.Int64Val(value) + u64, isUint := constant.Uint64Val(value) + if !isInt && !isUint { + log.Fatalf("internal error: value of %s is not an integer: %s", name, value.String()) + } + if !isInt { + u64 = uint64(i64) + } + v := Value{ + originalName: name.Name, + value: u64, + signed: info&types.IsUnsigned == 0, + str: value.String(), + } + if c := vspec.Comment; f.lineComment && c != nil && len(c.List) == 1 { + v.name = strings.TrimSpace(c.Text()) + } else { + v.name = strings.TrimPrefix(v.originalName, f.trimPrefix) + } + f.values = append(f.values, v) + } + } + return false +} + +// Helpers + +// usize returns the number of bits of the smallest unsigned integer +// type that will hold n. Used to create the smallest possible slice of +// integers to use as indexes into the concatenated strings. +func usize(n int) int { + switch { + case n < 1<<8: + return 8 + case n < 1<<16: + return 16 + default: + // 2^32 is enough constants for anyone. + return 32 + } +} + +// declareIndexAndNameVars declares the index slices and concatenated names +// strings representing the runs of values. +func (g *Generator) declareIndexAndNameVars(runs [][]Value, typeName string) { + var indexes, names []string + for i, run := range runs { + index, name := g.createIndexAndNameDecl(run, typeName, fmt.Sprintf("_%d", i)) + if len(run) != 1 { + indexes = append(indexes, index) + } + names = append(names, name) + } + g.Printf("const (\n") + for _, name := range names { + g.Printf("\t%s\n", name) + } + g.Printf(")\n\n") + + if len(indexes) > 0 { + g.Printf("var (") + for _, index := range indexes { + g.Printf("\t%s\n", index) + } + g.Printf(")\n\n") + } +} + +// declareIndexAndNameVar is the single-run version of declareIndexAndNameVars +func (g *Generator) declareIndexAndNameVar(run []Value, typeName string) { + index, name := g.createIndexAndNameDecl(run, typeName, "") + g.Printf("const %s\n", name) + g.Printf("var %s\n", index) +} + +// createIndexAndNameDecl returns the pair of declarations for the run. The caller will add "const" and "var". +func (g *Generator) createIndexAndNameDecl(run []Value, typeName string, suffix string) (string, string) { + b := new(bytes.Buffer) + indexes := make([]int, len(run)) + for i := range run { + b.WriteString(run[i].name) + indexes[i] = b.Len() + } + nameConst := fmt.Sprintf("_%s_name%s = %q", typeName, suffix, b.String()) + nameLen := b.Len() + b.Reset() + fmt.Fprintf(b, "_%s_index%s = [...]uint%d{0, ", typeName, suffix, usize(nameLen)) + for i, v := range indexes { + if i > 0 { + fmt.Fprintf(b, ", ") + } + fmt.Fprintf(b, "%d", v) + } + fmt.Fprintf(b, "}") + return b.String(), nameConst +} + +// declareNameVars declares the concatenated names string representing all the values in the runs. +func (g *Generator) declareNameVars(runs [][]Value, typeName string, suffix string) { + g.Printf("const _%s_name%s = \"", typeName, suffix) + for _, run := range runs { + for i := range run { + g.Printf("%s", run[i].name) + } + } + g.Printf("\"\n") +} + +// buildOneRun generates the variables and String method for a single run of contiguous values. +func (g *Generator) buildOneRun(runs [][]Value, typeName string) { + values := runs[0] + g.Printf("\n") + g.declareIndexAndNameVar(values, typeName) + // The generated code is simple enough to write as a Printf format. + lessThanZero := "" + if values[0].signed { + lessThanZero = "i < 0 || " + } + if values[0].value == 0 { // Signed or unsigned, 0 is still 0. + g.Printf(stringOneRun, typeName, usize(len(values)), lessThanZero) + } else { + g.Printf(stringOneRunWithOffset, typeName, values[0].String(), usize(len(values)), lessThanZero) + } +} + +// Arguments to format are: +// [1]: type name +// [2]: size of index element (8 for uint8 etc.) +// [3]: less than zero check (for signed types) +const stringOneRun = `func (i %[1]s) String() string { + if %[3]si >= %[1]s(len(_%[1]s_index)-1) { + return "%[1]s(" + strconv.FormatInt(int64(i), 10) + ")" + } + return _%[1]s_name[_%[1]s_index[i]:_%[1]s_index[i+1]] +} +` + +// Arguments to format are: +// [1]: type name +// [2]: lowest defined value for type, as a string +// [3]: size of index element (8 for uint8 etc.) +// [4]: less than zero check (for signed types) +/* + */ +const stringOneRunWithOffset = `func (i %[1]s) String() string { + i -= %[2]s + if %[4]si >= %[1]s(len(_%[1]s_index)-1) { + return "%[1]s(" + strconv.FormatInt(int64(i + %[2]s), 10) + ")" + } + return _%[1]s_name[_%[1]s_index[i] : _%[1]s_index[i+1]] +} +` + +// buildMultipleRuns generates the variables and String method for multiple runs of contiguous values. +// For this pattern, a single Printf format won't do. +func (g *Generator) buildMultipleRuns(runs [][]Value, typeName string) { + g.Printf("\n") + g.declareIndexAndNameVars(runs, typeName) + g.Printf("func (i %s) String() string {\n", typeName) + g.Printf("\tswitch {\n") + for i, values := range runs { + if len(values) == 1 { + g.Printf("\tcase i == %s:\n", &values[0]) + g.Printf("\t\treturn _%s_name_%d\n", typeName, i) + continue + } + g.Printf("\tcase %s <= i && i <= %s:\n", &values[0], &values[len(values)-1]) + if values[0].value != 0 { + g.Printf("\t\ti -= %s\n", &values[0]) + } + g.Printf("\t\treturn _%s_name_%d[_%s_index_%d[i]:_%s_index_%d[i+1]]\n", + typeName, i, typeName, i, typeName, i) + } + g.Printf("\tdefault:\n") + g.Printf("\t\treturn \"%s(\" + strconv.FormatInt(int64(i), 10) + \")\"\n", typeName) + g.Printf("\t}\n") + g.Printf("}\n") +} + +// buildMap handles the case where the space is so sparse a map is a reasonable fallback. +// It's a rare situation but has simple code. +func (g *Generator) buildMap(runs [][]Value, typeName string) { + g.Printf("\n") + g.declareNameVars(runs, typeName, "") + g.Printf("\nvar _%s_map = map[%s]string{\n", typeName, typeName) + n := 0 + for _, values := range runs { + for _, value := range values { + g.Printf("\t%s: _%s_name[%d:%d],\n", &value, typeName, n, n+len(value.name)) + n += len(value.name) + } + } + g.Printf("}\n\n") + g.Printf(stringMap, typeName) +} + +// Argument to format is the type name. +const stringMap = `func (i %[1]s) String() string { + if str, ok := _%[1]s_map[i]; ok { + return str + } + return "%[1]s(" + strconv.FormatInt(int64(i), 10) + ")" +} +` diff --git a/vendor/modules.txt b/vendor/modules.txt index 5afb73a56a10..7335dffb51d9 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -383,6 +383,9 @@ github.com/elastic/go-libaudit/aucoalesce github.com/elastic/go-libaudit/auparse github.com/elastic/go-libaudit/rule github.com/elastic/go-libaudit/rule/flags +# github.com/elastic/go-licenser v0.2.1 +github.com/elastic/go-licenser +github.com/elastic/go-licenser/licensing # github.com/elastic/go-lookslike v0.3.0 github.com/elastic/go-lookslike github.com/elastic/go-lookslike/internal/llreflect @@ -564,7 +567,11 @@ github.com/lib/pq github.com/lib/pq/oid github.com/lib/pq/scram # github.com/magefile/mage v1.9.0 +github.com/magefile/mage +github.com/magefile/mage/internal +github.com/magefile/mage/mage github.com/magefile/mage/mg +github.com/magefile/mage/parse github.com/magefile/mage/sh github.com/magefile/mage/target # github.com/mattn/go-colorable v0.0.8 @@ -600,7 +607,9 @@ github.com/opencontainers/runc/libcontainer/user # github.com/pierrec/lz4 v2.2.6+incompatible github.com/pierrec/lz4 github.com/pierrec/lz4/internal/xxh32 -# github.com/pkg/errors v0.8.1 +# github.com/pierrre/gotestcover v0.0.0-20160113212533-7b94f124d338 +github.com/pierrre/gotestcover +# github.com/pkg/errors v0.9.1 github.com/pkg/errors # github.com/pmezard/go-difflib v1.0.0 github.com/pmezard/go-difflib/difflib @@ -644,6 +653,8 @@ github.com/stretchr/objx github.com/stretchr/testify/assert github.com/stretchr/testify/mock github.com/stretchr/testify/require +# github.com/tsg/go-daemon v0.0.0-20200123164349-4b60efc26d5f +github.com/tsg/go-daemon # github.com/tsg/gopacket v0.0.0-20190320122513-dd3d0e41124a github.com/tsg/gopacket github.com/tsg/gopacket/afpacket @@ -803,6 +814,7 @@ golang.org/x/text/unicode/norm golang.org/x/time/rate # golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2 golang.org/x/tools/cmd/goimports +golang.org/x/tools/cmd/stringer golang.org/x/tools/go/analysis golang.org/x/tools/go/analysis/passes/inspect golang.org/x/tools/go/ast/astutil diff --git a/x-pack/filebeat/processors/decode_cef/cef/cef.go b/x-pack/filebeat/processors/decode_cef/cef/cef.go index c3cee5ff02d4..1023e5e892aa 100644 --- a/x-pack/filebeat/processors/decode_cef/cef/cef.go +++ b/x-pack/filebeat/processors/decode_cef/cef/cef.go @@ -13,7 +13,7 @@ import ( // Parser is generated from a ragel state machine using the following command: //go:generate ragel -Z -G1 cef.rl -o parser.go -//go:generate go fmt parser.go +//go:generate goimports -l -w parser.go // An SVG rendering of the state machine can be viewed by opening cef.svg in // Chrome / Firefox.