diff --git a/.travis.yml b/.travis.yml
index e23dec5a..bf593a69 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -4,9 +4,6 @@ go:
- 1.11.x
- 1.12.x
-before_script:
- - go get github.com/valyala/quicktemplate
-
script: make check_generated test
after_success:
diff --git a/Makefile b/Makefile
index 639e4572..930a948d 100644
--- a/Makefile
+++ b/Makefile
@@ -1,3 +1,5 @@
+export GO111MODULE = on
+
test: build
GL_TEST_RUN=1 ./golangci-lint run -v
GL_TEST_RUN=1 ./golangci-lint run --fast --no-config -v --skip-dirs 'test/testdata_etc,pkg/golinters/goanalysis/(checker|passes)'
@@ -32,9 +34,9 @@ release:
curl -sL https://git.io/goreleaser | bash
update_deps:
- GO111MODULE=on go mod verify
- GO111MODULE=on go mod tidy
+ go mod verify
+ go mod tidy
rm -rf vendor
- GO111MODULE=on go mod vendor
+ go mod vendor
.PHONY: test
diff --git a/go.mod b/go.mod
index 919e7b7c..99b3e478 100644
--- a/go.mod
+++ b/go.mod
@@ -49,6 +49,7 @@ require (
github.com/spf13/pflag v1.0.1
github.com/spf13/viper v1.0.2
github.com/stretchr/testify v1.2.2
+ github.com/valyala/quicktemplate v1.1.1
golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a // indirect
golang.org/x/net v0.0.0-20190313220215-9f648a60d977 // indirect
golang.org/x/sys v0.0.0-20190312061237-fead79001313 // indirect
diff --git a/go.sum b/go.sum
index 935d55d7..1a5a7a68 100644
--- a/go.sum
+++ b/go.sum
@@ -86,6 +86,10 @@ github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANyt
github.com/kisielk/gotool v0.0.0-20161130080628-0de1eaf82fa3/go.mod h1:jxZFDH7ILpTPQTk+E2s+z4CUas9lVNjIuKR4c5/zKgM=
github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
+github.com/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
+github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
+github.com/klauspost/cpuid v0.0.0-20180405133222-e7e905edc00e/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
+github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
@@ -150,12 +154,19 @@ github.com/spf13/viper v1.0.2 h1:Ncr3ZIuJn322w2k1qmzXDnkLAdQMlJqBa9kfAH+irso=
github.com/spf13/viper v1.0.2/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM=
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
+github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
+github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
+github.com/valyala/fasthttp v1.2.0/go.mod h1:4vX61m6KN+xDduDNwXrhIAVZaZaZiQ1luJk8LWSxF3s=
+github.com/valyala/quicktemplate v1.1.1 h1:C58y/wN0FMTi2PR0n3onltemfFabany53j7M6SDDB8k=
+github.com/valyala/quicktemplate v1.1.1/go.mod h1:EH+4AkTd43SvgIbQHYu59/cJyxDoOVRUAfrukLPuGJ4=
+github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a h1:YX8ljsm6wXlHZO+aRz9Exqr0evNhKRNe5K/gi+zKh4U=
golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/net v0.0.0-20170915142106-8351a756f30f/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd h1:nTDtHvHSdCn1m6ITfMRqtOd/9+7a3s8RBNOZ3eYZzJA=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20180911220305-26e67e76b6c3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190313220215-9f648a60d977 h1:actzWV6iWn3GLqN8dZjzsB+CLt+gaV2+wsxroxiQI8I=
golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
diff --git a/scripts/gen_readme/main.go b/scripts/gen_readme/main.go
index b0db3fd9..f649dfab 100644
--- a/scripts/gen_readme/main.go
+++ b/scripts/gen_readme/main.go
@@ -53,18 +53,18 @@ func buildTemplateContext() (map[string]interface{}, error) {
return nil, fmt.Errorf("can't read .golangci.example.yml: %s", err)
}
- if err = exec.Command("go", "install", "./cmd/...").Run(); err != nil {
+ if err = exec.Command("make", "build").Run(); err != nil {
return nil, fmt.Errorf("can't run go install: %s", err)
}
- lintersOut, err := exec.Command("golangci-lint", "help", "linters").Output()
+ lintersOut, err := exec.Command("./golangci-lint", "help", "linters").Output()
if err != nil {
return nil, fmt.Errorf("can't run linters cmd: %s", err)
}
lintersOutParts := bytes.Split(lintersOut, []byte("\n\n"))
- helpCmd := exec.Command("golangci-lint", "run", "-h")
+ helpCmd := exec.Command("./golangci-lint", "run", "-h")
helpCmd.Env = append(helpCmd.Env, os.Environ()...)
helpCmd.Env = append(helpCmd.Env, "HELP_RUN=1") // make default concurrency stable: don't depend on machine CPU number
help, err := helpCmd.Output()
diff --git a/test/data.go b/test/data.go
index 710e3914..e5320b3b 100644
--- a/test/data.go
+++ b/test/data.go
@@ -3,7 +3,7 @@ package test
import "path/filepath"
const testdataDir = "testdata"
-const binName = "golangci-lint"
+const binName = "../golangci-lint"
func getProjectRoot() string {
return filepath.Join("..", "...")
diff --git a/test/run_test.go b/test/run_test.go
index a191341d..0f8a7907 100644
--- a/test/run_test.go
+++ b/test/run_test.go
@@ -10,6 +10,8 @@ import (
"github.com/golangci/golangci-lint/test/testshared"
"github.com/golangci/golangci-lint/pkg/exitcodes"
+
+ _ "github.com/valyala/quicktemplate"
)
func getCommonRunArgs() []string {
@@ -25,13 +27,13 @@ func TestAutogeneratedNoIssues(t *testing.T) {
}
func TestEmptyDirRun(t *testing.T) {
- testshared.NewLintRunner(t).Run(getTestDataDir("nogofiles")).
+ testshared.NewLintRunner(t, "GO111MODULE=off").Run(getTestDataDir("nogofiles")).
ExpectExitCode(exitcodes.NoGoFiles).
ExpectOutputContains(": no go files to analyze")
}
func TestNotExistingDirRun(t *testing.T) {
- testshared.NewLintRunner(t).Run(getTestDataDir("no_such_dir")).
+ testshared.NewLintRunner(t, "GO111MODULE=off").Run(getTestDataDir("no_such_dir")).
ExpectExitCode(exitcodes.Failure).
ExpectOutputContains(`cannot find package \"./testdata/no_such_dir\"`)
}
diff --git a/test/testshared/testshared.go b/test/testshared/testshared.go
index 1ea71652..18eff223 100644
--- a/test/testshared/testshared.go
+++ b/test/testshared/testshared.go
@@ -4,7 +4,6 @@ import (
"io/ioutil"
"os"
"os/exec"
- "path/filepath"
"strings"
"syscall"
@@ -17,27 +16,26 @@ import (
type LintRunner struct {
t assert.TestingT
log logutils.Log
-
- installed bool
+ env []string
}
-func NewLintRunner(t assert.TestingT) *LintRunner {
+func NewLintRunner(t assert.TestingT, environ ...string) *LintRunner {
log := logutils.NewStderrLog("test")
log.SetLevel(logutils.LogLevelInfo)
return &LintRunner{
t: t,
log: log,
+ env: environ,
}
}
func (r *LintRunner) Install() {
- if r.installed {
+ if _, err := os.Stat("../golangci-lint"); err == nil {
return
}
- cmd := exec.Command("go", "install", filepath.Join("..", "cmd", "golangci-lint"))
+ cmd := exec.Command("make", "-C", "..", "build")
assert.NoError(r.t, cmd.Run(), "Can't go install golangci-lint")
- r.installed = true
}
type RunResult struct {
@@ -82,7 +80,8 @@ func (r *LintRunner) Run(args ...string) *RunResult {
runArgs := append([]string{"run"}, args...)
r.log.Infof("golangci-lint %s", strings.Join(runArgs, " "))
- cmd := exec.Command("golangci-lint", runArgs...)
+ cmd := exec.Command("../golangci-lint", runArgs...)
+ cmd.Env = append(os.Environ(), r.env...)
out, err := cmd.CombinedOutput()
if err != nil {
if exitError, ok := err.(*exec.ExitError); ok {
diff --git a/vendor/github.com/valyala/bytebufferpool/.travis.yml b/vendor/github.com/valyala/bytebufferpool/.travis.yml
new file mode 100644
index 00000000..6a6ec2eb
--- /dev/null
+++ b/vendor/github.com/valyala/bytebufferpool/.travis.yml
@@ -0,0 +1,15 @@
+language: go
+
+go:
+ - 1.6
+
+script:
+ # build test for supported platforms
+ - GOOS=linux go build
+ - GOOS=darwin go build
+ - GOOS=freebsd go build
+ - GOOS=windows go build
+ - GOARCH=386 go build
+
+ # run tests on a standard platform
+ - go test -v ./...
diff --git a/vendor/github.com/valyala/bytebufferpool/LICENSE b/vendor/github.com/valyala/bytebufferpool/LICENSE
new file mode 100644
index 00000000..f7c935c2
--- /dev/null
+++ b/vendor/github.com/valyala/bytebufferpool/LICENSE
@@ -0,0 +1,22 @@
+The MIT License (MIT)
+
+Copyright (c) 2016 Aliaksandr Valialkin, VertaMedia
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
diff --git a/vendor/github.com/valyala/bytebufferpool/README.md b/vendor/github.com/valyala/bytebufferpool/README.md
new file mode 100644
index 00000000..061357e8
--- /dev/null
+++ b/vendor/github.com/valyala/bytebufferpool/README.md
@@ -0,0 +1,21 @@
+[](https://travis-ci.org/valyala/bytebufferpool)
+[](http://godoc.org/github.com/valyala/bytebufferpool)
+[](http://goreportcard.com/report/valyala/bytebufferpool)
+
+# bytebufferpool
+
+An implementation of a pool of byte buffers with anti-memory-waste protection.
+
+The pool may waste limited amount of memory due to fragmentation.
+This amount equals to the maximum total size of the byte buffers
+in concurrent use.
+
+# Benchmark results
+Currently bytebufferpool is fastest and most effective buffer pool written in Go.
+
+You can find results [here](https://omgnull.github.io/go-benchmark/buffer/).
+
+# bytebufferpool users
+
+* [fasthttp](https://github.com/valyala/fasthttp)
+* [quicktemplate](https://github.com/valyala/quicktemplate)
diff --git a/vendor/github.com/valyala/bytebufferpool/bytebuffer.go b/vendor/github.com/valyala/bytebufferpool/bytebuffer.go
new file mode 100644
index 00000000..07a055a2
--- /dev/null
+++ b/vendor/github.com/valyala/bytebufferpool/bytebuffer.go
@@ -0,0 +1,111 @@
+package bytebufferpool
+
+import "io"
+
+// ByteBuffer provides byte buffer, which can be used for minimizing
+// memory allocations.
+//
+// ByteBuffer may be used with functions appending data to the given []byte
+// slice. See example code for details.
+//
+// Use Get for obtaining an empty byte buffer.
+type ByteBuffer struct {
+
+ // B is a byte buffer to use in append-like workloads.
+ // See example code for details.
+ B []byte
+}
+
+// Len returns the size of the byte buffer.
+func (b *ByteBuffer) Len() int {
+ return len(b.B)
+}
+
+// ReadFrom implements io.ReaderFrom.
+//
+// The function appends all the data read from r to b.
+func (b *ByteBuffer) ReadFrom(r io.Reader) (int64, error) {
+ p := b.B
+ nStart := int64(len(p))
+ nMax := int64(cap(p))
+ n := nStart
+ if nMax == 0 {
+ nMax = 64
+ p = make([]byte, nMax)
+ } else {
+ p = p[:nMax]
+ }
+ for {
+ if n == nMax {
+ nMax *= 2
+ bNew := make([]byte, nMax)
+ copy(bNew, p)
+ p = bNew
+ }
+ nn, err := r.Read(p[n:])
+ n += int64(nn)
+ if err != nil {
+ b.B = p[:n]
+ n -= nStart
+ if err == io.EOF {
+ return n, nil
+ }
+ return n, err
+ }
+ }
+}
+
+// WriteTo implements io.WriterTo.
+func (b *ByteBuffer) WriteTo(w io.Writer) (int64, error) {
+ n, err := w.Write(b.B)
+ return int64(n), err
+}
+
+// Bytes returns b.B, i.e. all the bytes accumulated in the buffer.
+//
+// The purpose of this function is bytes.Buffer compatibility.
+func (b *ByteBuffer) Bytes() []byte {
+ return b.B
+}
+
+// Write implements io.Writer - it appends p to ByteBuffer.B
+func (b *ByteBuffer) Write(p []byte) (int, error) {
+ b.B = append(b.B, p...)
+ return len(p), nil
+}
+
+// WriteByte appends the byte c to the buffer.
+//
+// The purpose of this function is bytes.Buffer compatibility.
+//
+// The function always returns nil.
+func (b *ByteBuffer) WriteByte(c byte) error {
+ b.B = append(b.B, c)
+ return nil
+}
+
+// WriteString appends s to ByteBuffer.B.
+func (b *ByteBuffer) WriteString(s string) (int, error) {
+ b.B = append(b.B, s...)
+ return len(s), nil
+}
+
+// Set sets ByteBuffer.B to p.
+func (b *ByteBuffer) Set(p []byte) {
+ b.B = append(b.B[:0], p...)
+}
+
+// SetString sets ByteBuffer.B to s.
+func (b *ByteBuffer) SetString(s string) {
+ b.B = append(b.B[:0], s...)
+}
+
+// String returns string representation of ByteBuffer.B.
+func (b *ByteBuffer) String() string {
+ return string(b.B)
+}
+
+// Reset makes ByteBuffer.B empty.
+func (b *ByteBuffer) Reset() {
+ b.B = b.B[:0]
+}
diff --git a/vendor/github.com/valyala/bytebufferpool/doc.go b/vendor/github.com/valyala/bytebufferpool/doc.go
new file mode 100644
index 00000000..e511b7c5
--- /dev/null
+++ b/vendor/github.com/valyala/bytebufferpool/doc.go
@@ -0,0 +1,7 @@
+// Package bytebufferpool implements a pool of byte buffers
+// with anti-fragmentation protection.
+//
+// The pool may waste limited amount of memory due to fragmentation.
+// This amount equals to the maximum total size of the byte buffers
+// in concurrent use.
+package bytebufferpool
diff --git a/vendor/github.com/valyala/bytebufferpool/pool.go b/vendor/github.com/valyala/bytebufferpool/pool.go
new file mode 100644
index 00000000..8bb4134d
--- /dev/null
+++ b/vendor/github.com/valyala/bytebufferpool/pool.go
@@ -0,0 +1,151 @@
+package bytebufferpool
+
+import (
+ "sort"
+ "sync"
+ "sync/atomic"
+)
+
+const (
+ minBitSize = 6 // 2**6=64 is a CPU cache line size
+ steps = 20
+
+ minSize = 1 << minBitSize
+ maxSize = 1 << (minBitSize + steps - 1)
+
+ calibrateCallsThreshold = 42000
+ maxPercentile = 0.95
+)
+
+// Pool represents byte buffer pool.
+//
+// Distinct pools may be used for distinct types of byte buffers.
+// Properly determined byte buffer types with their own pools may help reducing
+// memory waste.
+type Pool struct {
+ calls [steps]uint64
+ calibrating uint64
+
+ defaultSize uint64
+ maxSize uint64
+
+ pool sync.Pool
+}
+
+var defaultPool Pool
+
+// Get returns an empty byte buffer from the pool.
+//
+// Got byte buffer may be returned to the pool via Put call.
+// This reduces the number of memory allocations required for byte buffer
+// management.
+func Get() *ByteBuffer { return defaultPool.Get() }
+
+// Get returns new byte buffer with zero length.
+//
+// The byte buffer may be returned to the pool via Put after the use
+// in order to minimize GC overhead.
+func (p *Pool) Get() *ByteBuffer {
+ v := p.pool.Get()
+ if v != nil {
+ return v.(*ByteBuffer)
+ }
+ return &ByteBuffer{
+ B: make([]byte, 0, atomic.LoadUint64(&p.defaultSize)),
+ }
+}
+
+// Put returns byte buffer to the pool.
+//
+// ByteBuffer.B mustn't be touched after returning it to the pool.
+// Otherwise data races will occur.
+func Put(b *ByteBuffer) { defaultPool.Put(b) }
+
+// Put releases byte buffer obtained via Get to the pool.
+//
+// The buffer mustn't be accessed after returning to the pool.
+func (p *Pool) Put(b *ByteBuffer) {
+ idx := index(len(b.B))
+
+ if atomic.AddUint64(&p.calls[idx], 1) > calibrateCallsThreshold {
+ p.calibrate()
+ }
+
+ maxSize := int(atomic.LoadUint64(&p.maxSize))
+ if maxSize == 0 || cap(b.B) <= maxSize {
+ b.Reset()
+ p.pool.Put(b)
+ }
+}
+
+func (p *Pool) calibrate() {
+ if !atomic.CompareAndSwapUint64(&p.calibrating, 0, 1) {
+ return
+ }
+
+ a := make(callSizes, 0, steps)
+ var callsSum uint64
+ for i := uint64(0); i < steps; i++ {
+ calls := atomic.SwapUint64(&p.calls[i], 0)
+ callsSum += calls
+ a = append(a, callSize{
+ calls: calls,
+ size: minSize << i,
+ })
+ }
+ sort.Sort(a)
+
+ defaultSize := a[0].size
+ maxSize := defaultSize
+
+ maxSum := uint64(float64(callsSum) * maxPercentile)
+ callsSum = 0
+ for i := 0; i < steps; i++ {
+ if callsSum > maxSum {
+ break
+ }
+ callsSum += a[i].calls
+ size := a[i].size
+ if size > maxSize {
+ maxSize = size
+ }
+ }
+
+ atomic.StoreUint64(&p.defaultSize, defaultSize)
+ atomic.StoreUint64(&p.maxSize, maxSize)
+
+ atomic.StoreUint64(&p.calibrating, 0)
+}
+
+type callSize struct {
+ calls uint64
+ size uint64
+}
+
+type callSizes []callSize
+
+func (ci callSizes) Len() int {
+ return len(ci)
+}
+
+func (ci callSizes) Less(i, j int) bool {
+ return ci[i].calls > ci[j].calls
+}
+
+func (ci callSizes) Swap(i, j int) {
+ ci[i], ci[j] = ci[j], ci[i]
+}
+
+func index(n int) int {
+ n--
+ n >>= minBitSize
+ idx := 0
+ for n > 0 {
+ n >>= 1
+ idx++
+ }
+ if idx >= steps {
+ idx = steps - 1
+ }
+ return idx
+}
diff --git a/vendor/github.com/valyala/quicktemplate/.gitignore b/vendor/github.com/valyala/quicktemplate/.gitignore
new file mode 100644
index 00000000..6e92f57d
--- /dev/null
+++ b/vendor/github.com/valyala/quicktemplate/.gitignore
@@ -0,0 +1 @@
+tags
diff --git a/vendor/github.com/valyala/quicktemplate/.travis.yml b/vendor/github.com/valyala/quicktemplate/.travis.yml
new file mode 100644
index 00000000..4a1c6773
--- /dev/null
+++ b/vendor/github.com/valyala/quicktemplate/.travis.yml
@@ -0,0 +1,19 @@
+language: go
+
+go:
+ - 1.11.x
+ - 1.12.x
+ - tip
+
+before_install:
+ - go get -u github.com/valyala/quicktemplate/qtc
+ - go generate
+
+script:
+ # build test for supported platforms
+ - GOOS=linux go build
+ - GOOS=darwin go build
+ - GOOS=freebsd go build
+
+ # run tests on a standard platform
+ - go test -v ./...
diff --git a/vendor/github.com/valyala/quicktemplate/LICENSE b/vendor/github.com/valyala/quicktemplate/LICENSE
new file mode 100644
index 00000000..f7c935c2
--- /dev/null
+++ b/vendor/github.com/valyala/quicktemplate/LICENSE
@@ -0,0 +1,22 @@
+The MIT License (MIT)
+
+Copyright (c) 2016 Aliaksandr Valialkin, VertaMedia
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
diff --git a/vendor/github.com/valyala/quicktemplate/QuickTemplate.xml b/vendor/github.com/valyala/quicktemplate/QuickTemplate.xml
new file mode 100644
index 00000000..700d55e8
--- /dev/null
+++ b/vendor/github.com/valyala/quicktemplate/QuickTemplate.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/vendor/github.com/valyala/quicktemplate/README.md b/vendor/github.com/valyala/quicktemplate/README.md
new file mode 100644
index 00000000..3c104f40
--- /dev/null
+++ b/vendor/github.com/valyala/quicktemplate/README.md
@@ -0,0 +1,621 @@
+[](https://travis-ci.org/valyala/quicktemplate)
+[](http://godoc.org/github.com/valyala/quicktemplate)
+[](https://goreportcard.com/report/github.com/valyala/quicktemplate)
+
+# quicktemplate
+
+A fast, powerful, yet easy to use template engine for Go.
+Inspired by the [Mako templates](http://www.makotemplates.org/) philosophy.
+
+# Features
+
+ * [Extremely fast](#performance-comparison-with-htmltemplate).
+ Templates are converted into Go code and then compiled.
+ * Quicktemplate syntax is very close to Go - there is no need to learn
+ yet another template language before starting to use quicktemplate.
+ * Almost all bugs are caught during template compilation, so production
+ suffers less from template-related bugs.
+ * Easy to use. See [quickstart](#quick-start) and [examples](https://github.com/valyala/quicktemplate/tree/master/examples)
+ for details.
+ * Powerful. Arbitrary Go code may be embedded into and mixed with templates.
+ Be careful with this power - do not query the database and/or external resources from
+ templates unless you miss the PHP way in Go :) This power is mostly for
+ arbitrary data transformations.
+ * Easy to use template inheritance powered by [Go interfaces](https://golang.org/doc/effective_go.html#interfaces).
+ See [this example](https://github.com/valyala/quicktemplate/tree/master/examples/basicserver) for details.
+ * Templates are compiled into a single binary, so there is no need to copy
+ template files to the server.
+
+# Drawbacks
+
+ * Templates cannot be updated on the fly on the server, since they
+ are compiled into a single binary.
+ Take a look at [fasttemplate](https://github.com/valyala/fasttemplate)
+ if you need a fast template engine for simple dynamically updated templates.
+
+# Performance comparison with html/template
+
+Quicktemplate is more than 20x faster than [html/template](https://golang.org/pkg/html/template/).
+The following simple template is used in the benchmark:
+
+ * [html/template version](https://github.com/valyala/quicktemplate/blob/master/testdata/templates/bench.tpl)
+ * [quicktemplate version](https://github.com/valyala/quicktemplate/blob/master/testdata/templates/bench.qtpl)
+
+Benchmark results:
+
+```
+$ go test -bench='Benchmark(Quick|HTML)Template' -benchmem github.com/valyala/quicktemplate/tests
+BenchmarkQuickTemplate1-4 10000000 120 ns/op 0 B/op 0 allocs/op
+BenchmarkQuickTemplate10-4 3000000 441 ns/op 0 B/op 0 allocs/op
+BenchmarkQuickTemplate100-4 300000 3945 ns/op 0 B/op 0 allocs/op
+BenchmarkHTMLTemplate1-4 500000 2501 ns/op 752 B/op 23 allocs/op
+BenchmarkHTMLTemplate10-4 100000 12442 ns/op 3521 B/op 117 allocs/op
+BenchmarkHTMLTemplate100-4 10000 123392 ns/op 34498 B/op 1152 allocs/op
+```
+
+[goTemplateBenchmark](https://github.com/SlinSo/goTemplateBenchmark) compares QuickTemplate with numerous Go templating packages. QuickTemplate performs favorably.
+
+# Security
+
+ * All template placeholders are HTML-escaped by default.
+ * Template placeholders for JSON strings prevent from ``-based
+ XSS attacks:
+
+ ```qtpl
+ {% func FailedXSS() %}
+
+ {% endfunc %}
+ ```
+
+# Examples
+
+See [examples](https://github.com/valyala/quicktemplate/tree/master/examples).
+
+# Quick start
+
+First of all, install the `quicktemplate` package
+and [quicktemplate compiler](https://github.com/valyala/quicktemplate/tree/master/qtc) (`qtc`):
+
+```
+go get -u github.com/valyala/quicktemplate
+go get -u github.com/valyala/quicktemplate/qtc
+```
+
+Let's start with a minimal template example:
+
+```qtpl
+All text outside function templates is treated as comments,
+i.e. it is just ignored by quicktemplate compiler (`qtc`). It is for humans.
+
+Hello is a simple template function.
+{% func Hello(name string) %}
+ Hello, {%s name %}!
+{% endfunc %}
+```
+
+Save this file into a `templates` folder under the name `hello.qtpl`
+and run `qtc` inside this folder.
+
+If everything went OK, `hello.qtpl.go` file should appear in the `templates` folder.
+This file contains Go code for `hello.qtpl`. Let's use it!
+
+Create a file main.go outside `templates` folder and put the following
+code there:
+
+```go
+package main
+
+import (
+ "fmt"
+
+ "./templates"
+)
+
+func main() {
+ fmt.Printf("%s\n", templates.Hello("Foo"))
+ fmt.Printf("%s\n", templates.Hello("Bar"))
+}
+```
+
+Then issue `go run`. If everything went OK, you'll see something like this:
+
+```
+
+ Hello, Foo!
+
+
+ Hello, Bar!
+
+```
+
+Let's create more a complex template which calls other template functions,
+contains loops, conditions, breaks, continues and returns.
+Put the following template into `templates/greetings.qtpl`:
+
+```qtpl
+
+Greetings greets up to 42 names.
+It also greets John differently comparing to others.
+{% func Greetings(names []string) %}
+ {% if len(names) == 0 %}
+ Nobody to greet :(
+ {% return %}
+ {% endif %}
+
+ {% for i, name := range names %}
+ {% if i == 42 %}
+ I'm tired to greet so many people...
+ {% break %}
+ {% elseif name == "John" %}
+ {%= sayHi("Mr. " + name) %}
+ {% continue %}
+ {% else %}
+ {%= Hello(name) %}
+ {% endif %}
+ {% endfor %}
+{% endfunc %}
+
+sayHi is unexported, since it starts with lowercase letter.
+{% func sayHi(name string) %}
+ Hi, {%s name %}
+{% endfunc %}
+
+Note that every template file may contain an arbitrary number
+of template functions. For instance, this file contains Greetings and sayHi
+functions.
+```
+
+Run `qtc` inside `templates` folder. Now the folder should contain
+two files with Go code: `hello.qtpl.go` and `greetings.qtpl.go`. These files
+form a single `templates` Go package. Template functions and other template
+stuff is shared between template files located in the same folder.
+So `Hello` template function may be used inside `greetings.qtpl` while
+it is defined in `hello.qtpl`.
+Moreover, the folder may contain ordinary Go files, so its contents may
+be used inside templates and vice versa.
+The package name inside template files may be overriden
+with `{% package packageName %}`.
+
+Now put the following code into `main.go`:
+
+```go
+package main
+
+import (
+ "bytes"
+ "fmt"
+
+ "./templates"
+)
+
+func main() {
+ names := []string{"Kate", "Go", "John", "Brad"}
+
+ // qtc creates Write* function for each template function.
+ // Such functions accept io.Writer as first parameter:
+ var buf bytes.Buffer
+ templates.WriteGreetings(&buf, names)
+
+ fmt.Printf("buf=\n%s", buf.Bytes())
+}
+```
+
+Careful readers may notice different output tags were used in these
+templates: `{%s name %}` and `{%= Hello(name) %}`. What's the difference?
+The `{%s x %}` is used for printing HTML-safe strings, while `{%= F() %}`
+is used for embedding template function calls. Quicktemplate supports also
+other output tags:
+
+ * `{%d num %}` for integers.
+ * `{%f float %}` for float64.
+ Floating point precision may be set via `{%f.precision float %}`.
+ For example, `{%f.2 1.2345 %}` outputs `1.23`.
+ * `{%z bytes %}` for byte slices.
+ * `{%q str %}` and `{%qz bytes %}` for JSON-compatible quoted strings.
+ * `{%j str %}` and `{%jz bytes %}` for embedding str into a JSON string. Unlike `{%q str %}`,
+ it doesn't quote the string.
+ * `{%u str %}` and `{%uz bytes %}` for [URL encoding](https://en.wikipedia.org/wiki/Percent-encoding)
+ the given str.
+ * `{%v anything %}` is equivalent to `%v` in [printf-like functions](https://golang.org/pkg/fmt/).
+
+All the output tags except `{%= F() %}` produce HTML-safe output, i.e. they
+escape `<` to `<`, `>` to `>`, etc. If you don't want HTML-safe output,
+then just put `=` after the tag. For example: `{%s= "
This h1 won't be escaped
" %}`.
+
+As you may notice `{%= F() %}` and `{%s= F() %}` produce the same output for `{% func F() %}`.
+But the first one is optimized for speed - it avoids memory allocations and copies.
+It is therefore recommended to stick to it when embedding template function calls.
+
+Additionally, the following extensions are supported for `{%= F() %}`:
+
+ * `{%=h F() %}` produces html-escaped output.
+ * `{%=u F() %}` produces [URL-encoded](https://en.wikipedia.org/wiki/Percent-encoding) output.
+ * `{%=q F() %}` produces quoted json string.
+ * `{%=j F() %}` produces json string without quotes.
+ * `{%=uh F() %}` produces html-safe URL-encoded output.
+ * `{%=qh F() %}` produces html-safe quoted json string.
+ * `{%=jh F() %}` produces html-safe json string without quotes.
+
+All output tags except `{%= F() %}` family may contain arbitrary valid
+Go expressions instead of just an identifier. For example:
+
+```qtpl
+Import fmt for fmt.Sprintf()
+{% import "fmt" %}
+
+FmtFunc uses fmt.Sprintf() inside output tag
+{% func FmtFunc(s string) %}
+ {%s fmt.Sprintf("FmtFunc accepted %q string", s) %}
+{% endfunc %}
+```
+
+There are other useful tags supported by quicktemplate:
+
+ * `{% comment %}`
+
+ ```qtpl
+ {% comment %}
+ This is a comment. It won't trap into the output.
+ It may contain {% arbitrary tags %}. They are just ignored.
+ {% endcomment %}
+ ```
+
+ * `{% plain %}`
+
+ ```qtpl
+ {% plain %}
+ Tags will {% trap into %} the output {% unmodified %}.
+ Plain block may contain invalid and {% incomplete tags.
+ {% endplain %}
+ ```
+
+ * `{% collapsespace %}`
+
+ ```qtpl
+ {% collapsespace %}
+
+
space between lines
+ and {%s "tags" %}
+
is collapsed into a single space
+ unless{% newline %}or{% space %}is used